"""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 class genieSetup(cometModule.cometModule): """A class to run genie Monte Carlo """ ########################################################### def getOutputFilename(self): """Get the output filename""" self.outname = self.createFileName("dummy") return self.outname ########################################################### def getModuleName(self): """Return module name""" return "genieSetup" ########################################################### def getShortModuleName(self): """Return module name""" return "gnsp" ####################################################################### 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 # Check the free nucleon splines. if self.config.options.has_option("neutrino","genie_freenucl_splines"): if not os.path.isfile(self.config.options.get("neutrino","genie_freenucl_splines")): self.config.log.error("Cannot find genie free nucleon splines file "+self.config.options.get("neutrino","genie_freenucl_splines")) 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 for flux file if being asked to pre-generate flux interaction probabilities if self.config.options.has_option("neutrino","genie_generate_flux_probs"): if self.config.options.getboolean("neutrino","genie_generate_flux_probs"): # Require a flux file for this 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.lor.error("Genie setup being run to pre-generate flux interaction probabilities, 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 setup being run to pre-generate flux interaction probabilities, 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 # Unless the 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 process(self): """Run the jobs for Genie""" # Get the geometry from SimG4 geoFile = self._generateGeometry() if not geoFile: self.config.log.stop("genieSetup: Error generating geometry file") if not os.path.isfile(geoFile): self.config.log.stop("genieSetup: 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" # 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" # Define the master volume for generation. masterVolume = "all" if self.config.options.has_option("neutrino","master_volume"): masterVolume = self.config.options.get("neutrino","master_volume") # Decide whether to generate xsec table if self.config.options.has_option("neutrino","genie_xs_table"): # Use the a pre-generated one job += "export GSPLOAD="+self.config.options.get("neutrino","genie_xs_table")+"\n" else : # Otherwise generate it now self.config.log.output("About to generate cross section splines. This can take a while and should be separated from other genie setup jobs. See the documentation, configuring genie for IcedustControl for details.") if self.config.options.has_option("neutrino","genie_freenucl_splines"): job += "export GSPLOAD="+self.config.options.get("neutrino","genie_freenucl_splines")+"\n" else : self.config.log.error("Generating genie cross section splines without specifying any free nucleon splines. See the documentation, configuring genie for IcedustControl for details.") # Generate the cross section table. xstable = "genie_comet_"+masterVolume+"_xs_table_"+self.config.genieVersion+".xml" job += "$GENIE/bin/gmkspl" job += " -p 12,-12,14,-14,16,-16" job += " -f "+geoFile job += " -o "+xstable job += "\n" # Now load this table in for the next stages. job += "export GSPLOAD="+xstable+"\n" # Pre-generate flux interaction probabilities for use in later # event generation jobs if self.config.options.has_option("neutrino","genie_generate_flux_probs"): # Now run gT2Kevgen in special mode to compute interaction probabilities job += "$GENIE/bin/gT2Kevgen -S " if self.config.options.has_option("neutrino","genie_flux_probs_file_name"): job += self.config.options.get("neutrino","genie_flux_probs_file_name")+" " # 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 # If requested, specify the neutrino type neutrinospecies="" 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" # If requested, override default flux region 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 # Specify the flux file(s), flux location and neutrino list 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 setup being run to pre-generate flux interaction probabilities, 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 += " -L mm" job += " -D clhep_def_density_unit" # 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") job += "\n" # Generate max interaction paths to be used as input for event generation. This # is the old way to generate events and should only really be used for validation if self.config.options.has_option("neutrino","genie_generate_paths"): # Now generate the path lengths. paths = "genie_comet_"+masterVolume+"_paths_"+self.config.genieVersion+".xml" job += "$GENIE/bin/gmxpl" job += " -f "+geoFile job += " -o "+paths job += " -L mm" job += " -D clhep_def_density_unit" if masterVolume: job += " -t "+masterVolume job += "\n" # Create an emtpy output file to finish things off. job += "touch "+self.getOutputFilename()+"\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) ############################################################ 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"