Source code for pymchelper.executor.options

import logging
import os
import sys


[docs]class MCEnvironment: """ `MCEnvironment` subclasses are helpful to discover which MC engine (i.e. FLUKA or SHIELD-HIT12A) is being used they provide information about expected executable filename, by inspecting the path to executable filename (i.e. checking if it ends with `rfluka`) we can find corresponding code type """ executable_filename = None
[docs]class FlukaEnvironment(MCEnvironment): """ FLUKA Environment """ executable_filename = 'rfluka'
[docs]class SH12AEnvironmentLinux(MCEnvironment): """ SHIELD-HIT12A Environment for Linux """ executable_filename = 'shieldhit'
[docs]class SH12AEnvironmentWindows(MCEnvironment): """ SHIELD-HIT12A Environment for Windows """ executable_filename = 'shieldhit.exe'
[docs]class SimulationSettings: """ This class is responsible for keeping track of options for MC simulation: - location of the MC simulator executable - additional options provided by the user - location of the input files or directories Moreover this class performs automatic discovery of the MC input (i.e. whether this is SHIELD-HIT12A input or FLUKA input) """ def __init__(self, input_path, simulator_exec_path=None, cmdline_opts=None): # input file or directory self.input_path = input_path # discover the type of MC engine based on the type of input files/directories # `self._mc_environment` is set to one of the `MCEnvironment` subclasses self._mc_environment = self._discover_mc_engine(input_path) # set `self.executable_path` to the value provided by user, or if it is missing # perform automatic discovery of the *location* of MC engine executable file by scanning PATH env. variable self.executable_path = simulator_exec_path if not self.executable_path: self.executable_path = self._discover_mc_exec_location(self._mc_environment.executable_filename) # set extra options (i.e. `--time 00:15:30 -v`) for the MC engine self.cmdline_opts = cmdline_opts if cmdline_opts else '' # sanity check for None value # if extra options are provided, perform options validation # in case the options are not supported by MC engine, validation method will throw an exception if self.cmdline_opts: self._validate_cmdline_opt(self.cmdline_opts)
[docs] def set_rng_seed(self, rng_seed): """ This methods modifies command line options of the MC engine by setting (or overriding) the value of RNG seed TODO this method is specific to SH12A, more general should be added TODO add support for RNG seed provided as --seedofset, instead of -N """ # transform option list from plain string to a list of values for easier manipulation options_list = self.cmdline_opts.split() # If RNG seed is missing on the option list, then the code below will set it to given value if '-N' not in options_list: self.cmdline_opts += " -N {:d}".format(rng_seed) # if RNG is present on the option list, then we override its value else: # in SHIELD-HIT12A RNG seed is specified by -N option index_of_rng_opt = options_list.index('-N') # find index of '-N' options_list[index_of_rng_opt + 1] = str(rng_seed) # override the value of current -N option self.cmdline_opts = ' '.join(options_list) # reconstruct option string
[docs] def set_no_of_primaries(self, number_of_primaries): """ This methods modifies command line options of the MC engine by setting (or overriding) the number of primaries to be simulated by each of the parallel jobs TODO this method is specific to SH12A, more general should be added TODO add support for no of primaries provided as --nstat, instead of -n """ # transform option list from plain string to a list of values for easier manipulation options_list = self.cmdline_opts.split() # If no of primaries is missing on the option list, then the code below will set it to given value if '-n' not in options_list: self.cmdline_opts += " -n {:d}".format(number_of_primaries) else: # see `set_rng_seed` for the logic index_of_prim_opt = options_list.index('-n') options_list[index_of_prim_opt + 1] = str(number_of_primaries) self.cmdline_opts = ' '.join(options_list)
@staticmethod def _validate_cmdline_opt(cmdline_opts): """ TODO this method is specific to SH12A, more general should be added """ # transform option list from plain string to a list of values for easier manipulation options_list = cmdline_opts.split() # transform option list to a set to ease finding common part of unsupported and current options options_set = set(options_list) # set of options which cannot be overwritten by the user # these include locations of the input files which are fixed to the temporary workspace directories # generated by the `pymchelper` code unsupported = {'-b', '--beamfile', '-g', '--geofile', '-m', '--matfile', '-d', '--detectfile'} # raise an error if some of the unsupported option was provided by user (i.e. via -m option to `runmc` command) if options_set & unsupported: # TODO replace exception with warning and ignore such options # skipcq: PYL-W0511 raise SyntaxError("Unsupported option encountered: {:s}".format(",".join(options_set & unsupported))) @staticmethod def _discover_mc_engine(input_path): """ Analyse the input path and based on its type set proper MC engine In case of failure return None """ # raise exception if invalid path is provided if not os.path.exists(input_path): raise Exception("Input path {:s} doesn't exists".format(input_path)) # Fluka input files are provided as the single file # TODO cross-check if the `*.inp` extension is needed # skipcq: PYL-W0511 if os.path.isfile(input_path): return FlukaEnvironment # SHIELD-HIT12A input is in the form of directory with multiple files # TODO add a check if the directory contains (beam.dat, mat.dat, geo.dat and detect.dat) # skipcq: PYL-W0511 if os.path.isdir(input_path): # in case pymchelper runs on Windows choose a SHIELD-HIT12A environment which is Windows specific # (executable file being `shieldhit.exe` instead of `shieldhit`) if sys.platform == 'win32': return SH12AEnvironmentWindows return SH12AEnvironmentLinux return None @staticmethod def _discover_mc_exec_location(exec_filename): """ Scans PATH variable for the possible location of the MC engine exec_filename. Works on POSIX (Linux and MacOSX) and Windows systems """ # PATH variable contains list of directories being separated by : on POSIX systems # and by ; on Windows systems. Here we set proper separator separator_char = ':' if sys.platform == 'win32': separator_char = ';' list_of_directories = [] # loop over all directories in PATH env variable for path_directory_entry in os.environ['PATH'].split(separator_char): logging.debug("Inspecting {:s}".format(path_directory_entry)) # check if PATH entry is a proper directory # some malicious users can add a files to PATH as well (although it doesn't make any sense) if os.path.isdir(path_directory_entry): # scan a PATH entry and loop over all filenames inside PATH entry directory using `os.listdir` if exec_filename in os.listdir(path_directory_entry): # add a directories for which we encounter `exec_filename` # (MC engine filename, like `rfluka` or `shieldhit`) list_of_directories.append(path_directory_entry) # raise exception if MC engine not found if not list_of_directories: raise Exception("Executable {:s} not found in PATH ({:s})".format(exec_filename, ",".join(sys.path))) # if `exec_filename` is found in multiple location, return full path to the first location (directory+filename) return os.path.join(list_of_directories[0], exec_filename) def __str__(self): """ Dump all settings into a string """ result = "{executable_path:s} {cmdline_opts:s}".format( executable_path=os.path.abspath(self.executable_path), cmdline_opts=self.cmdline_opts if self.cmdline_opts else '' ) return result
[docs]class SH12ASettings(SimulationSettings): """ TODO """