diff --git a/README.md b/README.md index 80c6da0..403a5d7 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,124 @@ -# mcstas-python-wrapper -A Python wrapper for Mcstas +# McStas Python Wrapper (mcpw) + +## Requirements + +A mcstas instrument with all components + +The Define Section of your instrument must have following Format: + + DEFINE INSTRUMENT 'instrument' + ( + double x = 1.0, //comment + + //comment + int i = 1, //comment + float f = 1.0, //comment + ) + +empty lines will be ignored + + +## Short Overview + +This Package offers several functions to improve your workflow with Mcstas Simuations and +Processing the simmulation results. + +The Functionality is build around the two Classes variables and mcvariables. + +### class variables +variables are global variables that apply to any simulation and contains the location of the main working directory. +it is automatically generated with the 'mcpw_setup' command and is saved in local_var.python_requires + +### class mcvariables +mcvariables contains all important variables to run a simulation. +the mcpw_setup command will create it from the given instrument file and put it into instrument_name.py file. + +### the instrument.py file +the instrument.py file will be the main file you will work in. +appart from the mcvariables class it will contain all your custom functions +for analysing and datatreatment. +here you import all necessary packages and all your functions you want to get executed you add into +the analyse() function or the post_mcrun_funktions() function. +the analyse and post_mcrun_funktions will be called by mcpw_manager and executed + + +## First Setup + +Requirements: + +the mcpw_setup command creates all necessary files in order to use the mcpw_manager command. + +cd to the directory where your mcstas instrument lies + +then execute mcpw_setup: + + mcpw_setup -I instrument.instr -d working_directory -m path_to_mcstas_executable -o output_directory -c component_directory + +necessary is only the -I instrument.intr argument. + +with the -d working_directory argument you can set a different directory than your current one as the main working directory + +with the -m argument you can give the location of your mcstas installation. only needed if you did not install mcstas with a packages manager + +with the -o argument you can specify the location of the output directory where the simulation results are put in. the default is 'simulation_results' in the main working directory + +with the -c argument you can specify extra locations for mcstas components + + +if you have no errors and have two files: local_var.py and instrument.py in your working directory the setup stepp is compleated + +## First Use + +with mcpw_manager you can execute your simulation and all relevant functions you added to the analyse and post_mcrun_funktions functions. + +the minimal command to run a simmulation is: + + mcpw_manager -p instrument.py local + + + + +## Command Usage + +### Usage of mcpw_manager + + usage: mcpw_manager [-h] -p PYTHON_FILE [-d RESULT_DIR] mode ... + + Control command for automatic mcstas usage for the Reseda Instrument + + optional arguments: + -h, --help show this help message and exit + -p PYTHON_FILE, --python_file PYTHON_FILE + path (absolute or not) to the python file containing mcvariables and analyse functions + -d RESULT_DIR, --result-dir RESULT_DIR + directory name for the simulationresults. If none is given or foulder name exists allrady, a increment Folder Name is generated + + modes: + Use 'manager mode --help' to view the help for any command. + + mode + server mcstas will be executed localy and the processed simulation results packed in a tarball + remote mcstas will be executed on a remote machine + local mcstas will be executed on localy + full mcstas will be executed on localy and the analyze function will be called after + analyse analyse function will be called + +### Usage of mcpw_setup + + usage: mcpw_setup [-h] -I INSTRUMENT [-d WORKING_DIR] [-m MCSTAS] [-o OUTPUT_DIR] [-c COMPONENT_DIR] mode ... + + Script to create a python file to control a McStas Instrument with MPW + + optional arguments: + -h, --help show this help message and exit + -I INSTRUMENT, --instrument INSTRUMENT + mcstas instrument you want to control with mpw + -d WORKING_DIR, --working_dir WORKING_DIR + path to working directory (optional) + -m MCSTAS, --mcstas MCSTAS + path to mcstas executable; default=mcstas + -o OUTPUT_DIR, --output_dir OUTPUT_DIR + name in the simulation results directory; default=simulation_results + -c COMPONENT_DIR, --component_dir COMPONENT_DIR + additional directory where mcstas will search for components; default="" + diff --git a/mcpw/manager.py b/mcpw/manager.py index adf5820..ca1c801 100755 --- a/mcpw/manager.py +++ b/mcpw/manager.py @@ -18,113 +18,116 @@ def error(self, message): raise ArgumentParserError(message) +def main(): + # defining the argument parser for nice usage + parser= ThrowingArgumentParser(description="Control command for automatic mcstas usage for the Reseda Instrument") -# defining the argument parser for nice usage -parser= ThrowingArgumentParser(description="Control command for automatic mcstas usage for the Reseda Instrument") + subparsers = parser.add_subparsers(title="modes", required=True, + description="Use 'manager mode --help' to view the help for any command.", + metavar='mode') -subparsers = parser.add_subparsers(title="modes", required=True, - description="Use 'manager mode --help' to view the help for any command.", - metavar='mode') + parser.add_argument('-p', '--python_file', dest='python_file', default='', type=str, required=True, + help='path (absolute or not) to the python file containing mcvariables and analyse functions') -parser.add_argument('-p', '--python_file', dest='python_file', default='', type=str, required=True, - help='path (absolute or not) to the python file containing mcvariables and analyse functions') + parser.add_argument('-d', '--result-dir', dest='result_dir', default='', type=str, + help='directory name for the simulationresults. If none is given or foulder name exists allrady, a increment Folder Name is generated') -parser.add_argument('-d', '--result-dir', dest='result_dir', default='', type=str, - help='directory name for the simulationresults. If none is given or foulder name exists allrady, a increment Folder Name is generated') + parser_server = subparsers.add_parser('server', help='mcstas will be executed localy and the processed simulation results packed in a tarball') + parser_server.set_defaults(func='server') -parser_server = subparsers.add_parser('server', help='mcstas will be executed localy and the processed simulation results packed in a tarball') -parser_server.set_defaults(func='server') + parser_remote = subparsers.add_parser('remote', help='mcstas will be executed on a remote machine') + parser_remote.set_defaults(func='remote') -parser_remote = subparsers.add_parser('remote', help='mcstas will be executed on a remote machine') -parser_remote.set_defaults(func='remote') + parser_local = subparsers.add_parser('local', help='mcstas will be executed on localy') + parser_local.set_defaults(func='local') -parser_local = subparsers.add_parser('local', help='mcstas will be executed on localy') -parser_local.set_defaults(func='local') + parser_full = subparsers.add_parser('full', help='mcstas will be executed on localy and the analyze function will be called after') + parser_full.set_defaults(func='full') -parser_full = subparsers.add_parser('full', help='mcstas will be executed on localy and the analyze function will be called after') -parser_full.set_defaults(func='full') + parser_analyse = subparsers.add_parser('analyse', help='analyse function will be called') + parser_analyse.set_defaults(func='analyse') -parser_analyse = subparsers.add_parser('analyse', help='analyse function will be called') -parser_analyse.set_defaults(func='analyse') + #retreiveng command arguments + try: + args = parser.parse_args() + except ArgumentParserError as e: + parser.print_help() + print(f"\n{e}") + exit(1) -#retreiveng command arguments -try: - args = parser.parse_args() -except ArgumentParserError as e: - parser.print_help() - print(f"\n{e}") - exit(1) + # importing var and mcvar from local_var.py and reseda.py files + sys.path.append(os.getcwd()) + sys.path.append(os.path.dirname(args.python_file)) + from local_var import variables -# importing var and mcvar from local_var.py and reseda.py files -sys.path.append(os.getcwd()) -from local_var import variables + var = variables() + valid_config(var) -var = variables() -valid_config(var) + # adding local working directory to PATH + sys.path.append(var.p_local) + # adding pyhton file location to PATH + #importing python_file as module + pyinstr = import_module(f"{os.path.basename(args.python_file).split('.')[0]}") -# adding local working directory to PATH -sys.path.append(var.p_local) -# adding pyhton file location to PATH -sys.path.append(os.path.dirname(args.python_file)) -#importing python_file as module -pyinstr = import_module(f"{os.path.basename(args.python_file).split('.')[0]}") + # pulling relevant functions and classes from python file + mcvariables = vars(pyinstr)['mcvariables'] + analyse = vars(pyinstr)['analyse'] + post_mcrun_funktions = vars(pyinstr)['post_mcrun_funktions'] + # initializing mcvariables class + mcvar = mcvariables() -# pulling relevant functions and classes from python file -mcvariables = vars(pyinstr)['mcvariables'] -analyse = vars(pyinstr)['analyse'] -post_mcrun_funktions = vars(pyinstr)['post_mcrun_funktions'] -# initializing mcvariables class -mcvar = mcvariables() - -msg = '' -#calling the correct function according to command arguments -if 'func' not in args: - # Fallback to --help. - parser.print_help() -else: - (mcvar.dn,msg) = get_result_path_from_input(var, mcvar, msg, args) # logic for retreiveng the correct name for the result foulder - valid_mcconfig(var,mcvar) - if args.func == 'analyse': - mcvar = pload(var.p_local/var.sim_res/mcvar.dn/'variables') #loading the correct variables + msg = '' + #calling the correct function according to command arguments + if 'func' not in args: + # Fallback to --help. + parser.print_help() + else: + (mcvar.dn,msg) = get_result_path_from_input(var, mcvar, msg, args) # logic for retreiveng the correct name for the result foulder valid_mcconfig(var,mcvar) - check_for_detector_output(var,mcvar) - analyse(var, mcvar, msg) #call analyse, defined in reseda.py - exit(0) - if args.func == 'server':#this runs the script in server mde - run_mcstas(var,mcvar) - run_compiler(var,mcvar) - run_instrument(var,mcvar) - check_for_detector_output(var,mcvar) - psave(mcvar, var.p_local/var.sim_res/mcvar.dn/'variables') #save mcstas variables - post_mcrun_funktions(var, mcvar, msg) # contains functions that get executed after mcstas finished and can i.e. reformate the output - sp.run(['tar', '-cf' '{}/{}.tar'.format(var.sim_res, mcvar.dn), var.sim_res/mcvar.dn]) #compress data - - elif args.func == 'remote':#use this if you want to run the simulation on a remote machine (setup has to be done beforhand) - sp.run(['scp', '-r', '-P', str(var.port), var.instr_file, '{}:{}'.format(var.server, var.p_server)])#copy mcstas-instrument to remote - sp.run(['scp', '-r', '-P', str(var.port), 'manager.py', '{}:{}'.format(var.server, var.p_server)])#copy this file to remote - sp.run(['scp', '-r', '-P', str(var.port), 'reseda.py', '{}:{}'.format(var.server, var.p_server)])#copy this file to remote - sp.run(['ssh' , '-p', str(var.port), var.server, 'cd {}; python {}manager.py server {}'.format(var.p_server, var.p_server,mcvar.dn)])#run this file with server atribute remote - sp.run(['scp', '-l', str(var.rate), '-r', '-P', str(var.port), '{}:{}.tar'.format(var.server, var.p_server/var.sim_res/mcvar.dn), var.p_local])#download data from remote - sp.run(['tar', '-xf', '{}.tar'.format(mcvar.dn)])#decompress data - - elif args.func == 'local':#use this to run the script localy - run_mcstas(var,mcvar) - run_compiler(var,mcvar) - run_instrument(var,mcvar) - check_for_detector_output(var,mcvar) - psave(mcvar, var.p_local/var.sim_res/mcvar.dn/'variables') #save mcstas variables - post_mcrun_funktions(var, mcvar, msg) # contains functions that get executed after mcstas finished and can i.e. reformate the output - - elif args.func == 'full': - run_mcstas(var,mcvar) - run_compiler(var,mcvar) - run_instrument(var,mcvar) - check_for_detector_output(var,mcvar) - psave(mcvar, var.p_local/var.sim_res/mcvar.dn/'variables') #save mcstas variables - post_mcrun_funktions(var, mcvar, msg) # contains functions that get executed after mcstas finished and can i.e. reformate the output - analyse(var, mcvar, msg) #call analyse, defined in reseda.py - print(msg) + if args.func == 'analyse': + mcvar = pload(var.p_local/var.sim_res/mcvar.dn/'variables') #loading the correct variables + valid_mcconfig(var,mcvar) + check_for_detector_output(var,mcvar) + analyse(var, mcvar, msg) #call analyse, defined in reseda.py + exit(0) + if args.func == 'server':#this runs the script in server mde + run_mcstas(var,mcvar) + run_compiler(var,mcvar) + run_instrument(var,mcvar) + check_for_detector_output(var,mcvar) + psave(mcvar, var.p_local/var.sim_res/mcvar.dn/'variables') #save mcstas variables + post_mcrun_funktions(var, mcvar, msg) # contains functions that get executed after mcstas finished and can i.e. reformate the output + sp.run(['tar', '-cf' '{}/{}.tar'.format(var.sim_res, mcvar.dn), var.sim_res/mcvar.dn]) #compress data + + elif args.func == 'remote':#use this if you want to run the simulation on a remote machine (setup has to be done beforhand) + sp.run(['scp', '-r', '-P', str(var.port), var.instr_file, '{}:{}'.format(var.server, var.p_server)])#copy mcstas-instrument to remote + sp.run(['scp', '-r', '-P', str(var.port), 'manager.py', '{}:{}'.format(var.server, var.p_server)])#copy this file to remote + sp.run(['scp', '-r', '-P', str(var.port), 'reseda.py', '{}:{}'.format(var.server, var.p_server)])#copy this file to remote + sp.run(['ssh' , '-p', str(var.port), var.server, 'cd {}; python {}manager.py server {}'.format(var.p_server, var.p_server,mcvar.dn)])#run this file with server atribute remote + sp.run(['scp', '-l', str(var.rate), '-r', '-P', str(var.port), '{}:{}.tar'.format(var.server, var.p_server/var.sim_res/mcvar.dn), var.p_local])#download data from remote + sp.run(['tar', '-xf', '{}.tar'.format(mcvar.dn)])#decompress data + + elif args.func == 'local':#use this to run the script localy + run_mcstas(var,mcvar) + run_compiler(var,mcvar) + run_instrument(var,mcvar) + check_for_detector_output(var,mcvar) + psave(mcvar, var.p_local/var.sim_res/mcvar.dn/'variables') #save mcstas variables + post_mcrun_funktions(var, mcvar, msg) # contains functions that get executed after mcstas finished and can i.e. reformate the output + + elif args.func == 'full': + run_mcstas(var,mcvar) + run_compiler(var,mcvar) + run_instrument(var,mcvar) + check_for_detector_output(var,mcvar) + psave(mcvar, var.p_local/var.sim_res/mcvar.dn/'variables') #save mcstas variables + post_mcrun_funktions(var, mcvar, msg) # contains functions that get executed after mcstas finished and can i.e. reformate the output + analyse(var, mcvar, msg) #call analyse, defined in reseda.py + print(msg) + +if __name__ == '__main__': + main() diff --git a/mcpw/setup.py b/mcpw/setup.py index 634700e..58181fc 100755 --- a/mcpw/setup.py +++ b/mcpw/setup.py @@ -17,68 +17,45 @@ def error(self, message): raise ArgumentParserError(message) +def main(): + # defining the argument parser for nice usage + parser= ThrowingArgumentParser(description="Script to create a python file to control a McStas Instrument with MPW") -# defining the argument parser for nice usage -parser= ThrowingArgumentParser(description="Script to create a python file to control a McStas Instrument with MPW") + subparsers = parser.add_subparsers(title="modes", + description="Use 'manager mode --help' to view the help for any command.", + metavar='mode') -subparsers = parser.add_subparsers(title="modes", - description="Use 'manager mode --help' to view the help for any command.", - metavar='mode') + parser.add_argument('-I', '--instrument', dest='instrument', default='', type=str, required=True, + help='mcstas instrument you want to control with mpw') + parser.add_argument('-d', '--working_dir', dest='working_dir', default=os.getcwd(), type=str, + help='path to working directory (optional)') + parser.add_argument('-m', '--mcstas', dest='mcstas', default='mcstas', type=str, + help='path to mcstas executable; default=mcstas') + parser.add_argument('-o', '--output_dir', dest='output_dir', default='simulation_results', type=str, + help='name in the simulation results directory; default=simulation_results') + parser.add_argument('-c', '--component_dir', dest='component_dir', default='', type=str, + help='additional directory where mcstas will search for components; default=""') -parser.add_argument('-I', '--instrument', dest='instrument', default='', type=str, required=True, - help='mcstas instrument you want to control with mpw') -parser.add_argument('-d', '--working_dir', dest='working_dir', default=os.getcwd(), type=str, - help='path to working directory (optional)') -parser.add_argument('-m', '--mcstas', dest='mcstas', default='mcstas', type=str, - help='path to mcstas executable; default=mcstas') -parser.add_argument('-o', '--output_dir', dest='output_dir', default='simulation_results', type=str, - help='name in the simulation results directory; default=simulation_results') -parser.add_argument('-c', '--component_dir', dest='component_dir', default='', type=str, - help='additional directory where mcstas will search for components; default=""') -#parser_analyse = subparsers.add_parser('analyse', help='analyse function will be called') -#parser_analyse.set_defaults(func='analyse') + #retreiveng command arguments + try: + args = parser.parse_args() + except ArgumentParserError as e: + print(e) + exit(1) + if not os.path.isfile(f"{args.working_dir}/local_var.py"): + create_local_var(args) + else: + print(f"local_var.py allready exists") + if not os.path.isfile(f"{args.working_dir}/{args.instrument.split('.')[0]}.py"): + create_python_file(args) + else: + print(f"{args.instrument.split('.')[0]}.py allready exists") -#retreiveng command arguments -try: - args = parser.parse_args() -except ArgumentParserError as e: - print(e) - exit(1) -if not os.path.isfile(f"{args.working_dir}/local_var.py"): - create_local_var(args) -else: - print(f"local_var.py allready exists") +if __name__ == '__main__': + main() -if not os.path.isfile(f"{args.working_dir}/{args.instrument.split('.')[0]}.py"): - create_python_file(args) -else: - print(f"{args.instrument.split('.')[0]}.py allready exists") - - - - - - -#msg = '' -##calling the correct function according to command arguments -#if 'func' not in args: -# # Fallback to --help. -# parser.print_help() -#else: -# (mcvar.dn,msg) = get_result_path_from_input(var, mcvar, msg, args) # logic for retreiveng the correct name for the result foulder -# if args.func == 'analyse': -# mcvar = pload(var.p/var.p_local/var.sim_res/mcvar.dn/'variables') #loading the correct variables -# analyse(var, mcvar, msg) #call analyse, defined in reseda.py -# exit(0) -# -# elif args.func == 'full': -# sp.run(mcrun_string(var, mcvar), shell=True) #run mcstas -# psave(mcvar, var.p/var.p_local/var.sim_res/mcvar.dn/'variables') #save mcstas variables -# post_mcrun_funktions(var, mcvar, msg) # contains functions that get executed after mcstas finished and can i.e. reformate the output -# analyse(var, mcvar, msg) #call analyse, defined in reseda.py -# print(msg) diff --git a/setup.cfg b/setup.cfg index 86417b5..744d3c2 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = mcpw -version = 0.0.10 +version = 0.1.0 author = Tincotema author_email = tincotema@genthree.io description = A lightweight mcstas python wrapper @@ -8,7 +8,7 @@ long_description = file: README.md long_description_content_type = text/markdown url = https://github.com/tincotema/mcstas-python-wrapper project_urls = - Bug Tracker = https://github.com/pypa/mcstas-python-wrapper/issues + Bug Tracker = https://github.com/tincotema/mcstas-python-wrapper/issues license = MIT python_requires = >=3.6 classifiers =