"""Class to process genie Monte Carlo. Genie is run as a program external to the main comet code. """ import cometModule import cometGeometry import cometRun import geomNameCheck import os import re class genieMC(cometModule.cometModule): """A class to run genie Monte Carlo """ ########################################################### def checkConfig(self): """Check and fix the Monte Carlo type.""" # The Monte Carlo type must be set to Genie if self.config.options.has_option("SimG4","mc_type"): if (self.config.options.get("SimG4","mc_type") == "Genie"): return True else: self.config.log.error("The config option SimG4/mc_type is not set to Genie, but running genieMC module. Reset this option to Genie") self.config.options.set("SimG4","mc_type","Genie") else: # The option doesn't exist, set it. self.config.log.error("The config option SimG4/mc_type is not set, but running genieMC module. Setting this option to Genie") # Create the section if it doesn't exist. if not self.config.options.has_section("SimG4"): self.config.options.add_section("SimG4") # Set the option self.config.options.set("SimG4","mc_type","Genie") ########################################################### def getOutputFilename(self): """Get the output filename""" self.outname = self.createFileName("root") return self.outname ########################################################### def getModuleName(self): """Return module name""" return "genieMC" ########################################################### def getShortModuleName(self): """Return module name""" return "gnmc" ####################################################################### def checkModuleConfig(self): """Checks the configuration""" # Make sure that the enviromnet setup script exists. if self.config.options.has_option("software","genie_setup_script"): script = self.config.options.get("software","genie_setup_script") if not os.path.isfile(script): self.config.log.error("Cannot locate specified Genie setup script "+script) return False else: self.config.log.error("Genie MC being run, but setup script not set in the config file. Please use the software/genie_setup_script option") return False # Make sure that the flux file exists. flux = "" if self.config.options.has_option("neutrino","flux_file") and ( self.config.options.has_option("neutrino","flux_file_path") or self.config.options.has_option("neutrino","flux_file_start") or self.config.options.has_option("neutrino","flux_file_stop") ): self.config.log.error("Genie MC being run, but multiple flux file input styles specified. Please use either neutrino/flux_file OR neutrino/flux_file_path and neutrino/flux_file_start and neutrino/flux_file_stop") return False if self.config.options.has_option("neutrino","flux_file"): flux = self.config.options.get("neutrino","flux_file") if not os.path.isfile(flux): self.config.log.error("Cannot locate specified neutrino flux file "+flux) return False elif self.config.options.has_option("neutrino","flux_file_path") and self.config.options.has_option("neutrino","flux_file_start") and self.config.options.has_option("neutrino","flux_file_stop"): flux = self.config.options.get("neutrino","flux_file_path") need_to_exit = False for filenum in range( int(self.config.options.get("neutrino","flux_file_start")), int(self.config.options.get("neutrino","flux_file_stop")) ): if not os.path.isfile(flux+"."+str(filenum)+".root"): self.config.log.error("Cannot locate specified neutrino flux file "+flux+"."+str(filenum)+".root") need_to_exit = True if need_to_exit: return False else: self.config.log.error("Genie MC being run, but no neutrino flux file specified. Please use either neutrino/flux_file OR neutrino/flux_file_path and neutrino/flux_file_start and neutrino/flux_file_stop") return False # Check the cross section table. if self.config.options.has_option("neutrino","genie_xs_table"): if not os.path.isfile(self.config.options.get("neutrino","genie_xs_table")): self.config.log.error("Cannot find genie xs table file "+self.config.options.get("neutrino","genie_xs_table")) return False # Check the path lengths. if self.config.options.has_option("neutrino","genie_paths"): if not os.path.isfile(self.config.options.get("neutrino","genie_paths")): self.config.log.error("Cannot find genie paths file "+self.config.options.get("neutrino","genie_paths")) return False if self.config.options.has_option("neutrino","flux_region"): region = self.config.options.get("neutrino","flux_region").upper() if not(region == "MAGNET" or region == "BASKET" or region == "INGRID" or region == "SAND"): self.config.log.error("Genie MC being run with invalid flux region. Please select magnet, basket or sand. Cannot continue") return False # Unless the force_geom_name has been specified check that the # master_volume name matches to one in a list of known volumes. if geomNameCheck.CheckTopVolumeName(self.config) == False: return False return True ########################################################### def checkOutput(self): """Method to check the output of Genie""" # Set the random number seed if used. if self.config.options.has_option("neutrino","random_seed"): seed = self.config.options.get("neutrino","random_seed") self.jobSeed = seed if (self.run): return self.run.rtc == 0 return True ####################################################################### def process(self): """Run the jobs for Genie""" # Get the geometry from SimG4 geoFile = self._generateGeometry() if not geoFile: self.config.log.stop("genieMC: Error generating geometry file") if not os.path.isfile(geoFile): self.config.log.stop("genieMC: Error generating geometry file") # Setup the job commands. # Start by executing the setup script, and unsetting LD_LIBRARY_PATH. job = "unset LD_LIBRARY_PATH\n" script = self.config.options.get("software","genie_setup_script") job += "source "+script+"\n" # Load the xs table. if self.config.options.has_option("neutrino","genie_xs_table"): job += "export GSPLOAD="+self.config.options.get("neutrino","genie_xs_table")+"\n" else: # This isn't an error condition, just a very strong warning. self.config.log.error("WARNING:: You have not specified a cross section table for Genie. Genie will now create one for itself during the genie job. This is very time consuming (>24h) and it is recommened that you generate this file first. See the genie documentation in IcedustControl for details.") # Set the GENIE random seed. if self.config.options.has_option("neutrino","random_seed"): seed = self.config.options.get("neutrino","random_seed") job += "export GSEED="+seed+"\n" # Cut down on Genie verbosity if self.config.options.has_option("neutrino","verbose"): if not self.config.options.getboolean("neutrino","verbose"): job += "export GPRODMODE=YES\n" else: job += "export GPRODMODE=YES\n" # See if we need to declare specific neutrino species for generation. neutrinospecies="" # Specify the neutrino type if self.config.options.has_option("neutrino","neutrino_type"): nu_type = self.config.options.get("neutrino","neutrino_type").upper() if nu_type.upper() == "BEAM": neutrinospecies += "" elif nu_type.upper() == "NUE": neutrinospecies += ",12" elif nu_type.upper() == "NUEBAR": neutrinospecies += ",-12" elif nu_type.upper() == "NUMU": neutrinospecies += ",14" elif nu_type.upper() == "NUMUBAR": neutrinospecies += ",-14" # What is the run number. We want to remove leading zeros. run = int(self.config.runnumber.split("-")[0]) # Use the job hash for unique naming. name = self.config.jobHash # Run Genie job += "$GENIE/bin/gT2Kevgen" # Specify flux region. Probably need to allow for more options than just magnet # and basket, such as the ingrid locations (nd3 and 4). For now just copy # the options from the NEUT module. flux_loc = "" region = "" if self.config.options.has_option("neutrino","flux_region"): region = self.config.options.get("neutrino","flux_region").upper() if region == "BASKET": flux_loc = "nd5" elif region == "INGRID": flux_loc = "nd34" elif region == "SAND": flux_loc = "nd13" else: flux_loc = "nd6" #default, MAGNET # Add the flux. Probably need to allow the location to be set. flux="" if self.config.options.has_option("neutrino","flux_file"): flux = self.config.options.get("neutrino","flux_file") elif self.config.options.has_option("neutrino","flux_file_path") and self.config.options.has_option("neutrino","flux_file_start") and self.config.options.has_option("neutrino","flux_file_stop"): flux = self.config.options.get("neutrino","flux_file_path") flux += "@" flux += self.config.options.get("neutrino","flux_file_start") flux += "@" flux += self.config.options.get("neutrino","flux_file_stop") else: self.config.log.error("Genie MC being run, but no neutrino flux file specified. Please use either neutrino/flux_file OR neutrino/flux_file_path and neutrino/flux_file_start and neutrino/flux_file_stop") self.run.rtc = 1 return job += " -f "+flux+","+flux_loc+neutrinospecies job += " -g "+geoFile job += " -r "+str(run) job += " -L mm" job += " -D clhep_def_density_unit" # GENIE now uses flux interaction probabilities (either pre-generated or generated # on the fly) as default method for event generation. Only use max path lengths # method requested if self.config.options.has_option("neutrino","genie_paths"): job += " -m "+self.config.options.get("neutrino","genie_paths") else: job += " -P " # Either use pre-generated flux interaction probs file if self.config.options.has_option("neutrino","genie_flux_probs_file_name"): job += self.config.options.get("neutrino","genie_flux_probs_file_name") # Or calculate them on the fly else: self.config.log.output("No pre-generated flux interaction probabilities file supplied for event generation. Flux probabilities will be calculated on the fly. This is only recommended for small flux files (<1M entries), for larger flux files you should pre-generate them for a given flux file using the genieSetup module.") job += " -o "+name # Check to see if need non default flux POT. if self.config.options.has_option("neutrino","flux_file_pot"): job += " -p "+self.config.options.get("neutrino","flux_file_pot") # Define the master volume for generation. masterVolume = "" if self.config.options.has_option("neutrino","master_volume"): masterVolume = self.config.options.get("neutrino","master_volume") if masterVolume: job += " -t "+masterVolume # Start at random position in flux file if self.config.options.has_option("neutrino","random_start"): # GENIE uses internal class for generting random numbers based on the GSEED variable use_random_start = self.config.options.getboolean("neutrino","random_start") if use_random_start: job += " -R " # The next bits define the size of the job. If nothing is specified it # will go through the input flux file once. if self.config.options.has_option("neutrino","pot"): job += " -e "+self.config.options.get("neutrino","pot")+"\n" elif self.config.options.has_option("neutrino","num_events"): job += " -n "+self.config.options.get("neutrino","num_events")+"\n" elif self.config.options.has_option("neutrino","num_cycles"): job += " -c "+self.config.options.get("neutrino","num_cycles")+"\n" self.run = cometRun.cometRun(job,self.config) self.run.setCallName(self.getModuleName()) # We don't want to configure cmt programs this time. self.run.setup = False self.run.run() self.config.log.output(self.run.stdout) self.config.log.error(self.run.stderr) # Rename the output. filename = self.getOutputFilename() outfile = name+"."+str(run)+".ghep.root" if os.path.isfile(outfile): os.rename(outfile,filename) else: self.config.log.stop("Cannot find Genie output file "+outfile) cleanup = True if self.config.options.has_option("neutrino","cleanup"): cleanup = self.config.options.getboolean("neutrino","cleanup") if cleanup: # Remove the converted flux and geometry files. os.unlink(geoFile) ############################################################ def _generateGeometry(self): """Method to generate the geometry file We run a very quick SimG4 job to do this.""" geoname = self.createFileName("geo") macname = self.createFileName("mac") macContents = "" # Geometry Switches. cometGeom = cometGeometry.cometGeometry(self.config) geometryControl = cometGeom.getMACCommands() if geometryControl: macContents += geometryControl else: # Warning already printed. return False # Now generate a single muon to run macContents += """ /comet/update """ try: macFile = open(macname,"w") macFile.write(macContents) except: self.config.log.stop("SimG4: Cannot write mac file "+macname) macFile.close() job = "SIMG4.exe " + " -o " + geoname + " " + macname self.run = cometRun.cometRun(job,self.config) self.run.setCallName(self.getModuleName()+"-geo") self.run.run() self.config.log.output(self.run.stdout) self.config.log.error(self.run.stderr) # Remove the mac file if required. cleanup = True if self.config.options.has_option("neutrino","cleanup"): cleanup = self.config.options.getboolean("neutrino","cleanup") if cleanup: os.unlink(macname) return geoname+".root"