class WhizardAnalysis(ModuleBase): """ Specific Module to run a Whizard job. """ def __init__(self): super(WhizardAnalysis, self).__init__() self.enable = True self.STEP_NUMBER = '' self.debug = True self.SteeringFile = '' self.OutputFile = '' self.NumberOfEvents = 1 self.Lumi = 0 self.applicationName = 'whizard' self.evttype = "" self.RandomSeed = 0 self.getProcessInFile = False self.datMan = DataManager() self.processlist = None self.parameters = {} self.susymodel = 0 self.Model = '' self.genmodel = GeneratorModels() self.eventstring = ['! ', 'Fatal error:', 'PYSTOP', 'No matrix element available', 'Floating point exception', 'Event generation finished.', " n_events","luminosity", " sum "] self.excludeAllButEventString = False self.steeringparameters = '' self.options = None self.optionsdict = {} self.OptionsDictStr = '' self.GenLevelCutDictStr = '' self.genlevelcuts = {} self.willCut = False self.useGridFiles = False def obtainProcessList(self): """Internal function Get the process list from storage if whizard.in was not provided :return: S_OK(), S_ERROR() """ res = self.ops.getValue("/ProcessList/Location", "") if not res: return S_ERROR("No process list found") processlistloc = res if not os.path.exists(os.path.basename(processlistloc)): res = self.datMan.getFile(processlistloc) if not res['OK']: LOG.error('Could not get processlist: %s' % res['Message']) return res self.processlist = ProcessList(os.path.basename(processlistloc)) return S_OK() def applicationSpecificInputs(self): """Resolve module input :return: S_OK() """ self.parameters['ENERGY'] = self.energy if not self.RandomSeed and self.jobID: self.RandomSeed = self.jobID if 'IS_PROD' in self.workflow_commons or 'IS_DBD_GEN_PROD' in self.workflow_commons: self.RandomSeed = int(str(int(self.workflow_commons["PRODUCTION_ID"])) + str(int(self.workflow_commons["JOB_ID"]))) self.parameters['SEED'] = self.RandomSeed self.parameters['NBEVTS'] = self.NumberOfEvents self.parameters['LUMI'] = self.Lumi ##EVER USED??? if 'SusyModel' in self.step_commons: self.susymodel = self.step_commons['SusyModel'] self.SteeringFile = os.path.basename(self.step_commons.get("InputFile", self.SteeringFile)) if self.SteeringFile == "whizard.in": os.rename(self.SteeringFile, "whizardnew.in") self.SteeringFile = "whizardnew.in" self.parameters['PROCESS'] = self.evttype listofparams = self.steeringparameters.split(";") for param in listofparams: if param.count("="): self.parameters[param.split("=")[0]] = param.split("=")[1] if self.OptionsDictStr: LOG.info("Will use whizard.in definition from WhizardOptions.") try: self.optionsdict = eval(self.OptionsDictStr) if 'integration_input' not in self.optionsdict: self.optionsdict['integration_input'] = {} if 'seed' not in self.optionsdict['integration_input']: self.optionsdict['integration_input']['seed'] = int(self.RandomSeed) if 'process_input' in self.optionsdict: if 'sqrts' in self.optionsdict['process_input']: self.energy = self.optionsdict['process_input']['sqrts'] except: return S_ERROR("Could not convert string to dictionary for optionsdict") if self.GenLevelCutDictStr: LOG.info("Found generator level cuts") try: self.genlevelcuts = eval(self.GenLevelCutDictStr) except: return S_ERROR("Could not convert the generator level cuts back to dictionary") if not len(self.SteeringFile) and not self.optionsdict: self.getProcessInFile = True if "IS_PROD" in self.workflow_commons: if self.workflow_commons["IS_PROD"] and not self.willCut: #self.OutputFile = getProdFilename(self.OutputFile,int(self.workflow_commons["PRODUCTION_ID"]), # int(self.workflow_commons["JOB_ID"])) if 'ProductionOutputData' in self.workflow_commons: outputlist = self.workflow_commons['ProductionOutputData'].split(";") for obj in outputlist: if obj.lower().count("_gen_"): self.OutputFile = os.path.basename(obj) break else: #This is because most likely there is stdhepcut running after self.OutputFile = "willcut.stdhep" #getProdFilename(self.OutputFile,int(self.workflow_commons["PRODUCTION_ID"]), # int(self.workflow_commons["JOB_ID"])) if "IS_DBD_GEN_PROD" in self.workflow_commons and self.workflow_commons["IS_DBD_GEN_PROD"]: #self.OutputFile = getProdFilename(self.OutputFile,int(self.workflow_commons["PRODUCTION_ID"]), # int(self.workflow_commons["JOB_ID"])) if 'ProductionOutputData' in self.workflow_commons: outputlist = self.workflow_commons['ProductionOutputData'].split(";") for obj in outputlist: self.OutputFile = os.path.basename(obj) break else: self.OutputFile = getProdFilename(self.OutputFile, int(self.workflow_commons["PRODUCTION_ID"]), int(self.workflow_commons["JOB_ID"])) return S_OK() def runIt(self): """ Called by Agent Executes the following - resolve input variables - resolve installation location - resolve dependencies location (beam_spectra) - get processlist if needed - define output file name - prepare whizard.in - make magic :return: S_OK(), S_ERROR() """ self.result = S_OK() if not self.platform: self.result = S_ERROR( 'No ILC platform selected' ) elif not self.applicationLog: self.result = S_ERROR( 'No Log file provided' ) if not self.result['OK']: LOG.error("Failed to resolve input parameters:", self.result["Message"]) return self.result if not self.workflowStatus['OK'] or not self.stepStatus['OK']: LOG.verbose('Workflow status = %s, step status = %s' % (self.workflowStatus['OK'], self.stepStatus['OK'])) return S_OK('Whizard should not proceed as previous step did not end properly') #if self.debug: # self.excludeAllButEventString = False res = getSoftwareFolder(self.platform, self.applicationName, self.applicationVersion) if not res['OK']: LOG.error("Failed getting software folder", res['Message']) self.setApplicationStatus('Failed finding software') return res mySoftDir = res['Value'] ###Remove libc removeLibc(mySoftDir + "/lib") ##Need to fetch the new LD_LIBRARY_PATH new_ld_lib_path = getNewLDLibs(self.platform, self.applicationName, self.applicationVersion) #Don't forget to prepend the application's libs new_ld_lib_path = mySoftDir + "/lib:" + new_ld_lib_path ### Resolve dependencies (look for beam_spectra) deps = resolveDeps(self.platform, self.applicationName, self.applicationVersion) path_to_beam_spectra = "" path_to_gridfiles = "" for dep in deps: res = getSoftwareFolder(self.platform, dep[ "app" ], dep['version']) if not res['OK']: LOG.error("Failed getting software folder", res['Message']) self.setApplicationStatus('Failed finding software') return res depfolder = res['Value'] if dep["app"] == "beam_spectra": path_to_beam_spectra = depfolder elif dep["app"] == "gridfiles": path_to_gridfiles = depfolder ##Env variables needed to run whizard: avoids hard coded locations os.environ['LUMI_LINKER'] = path_to_beam_spectra + "/lumi_linker_000" os.environ['PHOTONS_B1'] = path_to_beam_spectra + "/photons_beam1_linker_000" os.environ['PHOTONS_B2'] = path_to_beam_spectra + "/photons_beam2_linker_000" os.environ['EBEAM'] = path_to_beam_spectra + "/ebeam_in_linker_000" os.environ['PBEAM'] = path_to_beam_spectra + "/pbeam_in_linker_000" os.environ['LUMI_EE_LINKER'] = path_to_beam_spectra + "/lumi_ee_linker_000" os.environ['LUMI_EG_LINKER'] = path_to_beam_spectra + "/lumi_eg_linker_000" os.environ['LUMI_GE_LINKER'] = path_to_beam_spectra + "/lumi_ge_linker_000" os.environ['LUMI_GG_LINKER'] = path_to_beam_spectra + "/lumi_gg_linker_000" list_of_gridfiles = [] if path_to_gridfiles and self.useGridFiles: tmp_list_of_gridfiles = [os.path.join(path_to_gridfiles, item) for item in os.listdir(path_to_gridfiles)] gridfilesfound = False for path in tmp_list_of_gridfiles: if os.path.isdir(path) and path.count(str(self.energy)): #Here look for a sub directory for the energy related grid files list_of_gridfiles = [os.path.join(path, item) for item in os.listdir(path)] gridfilesfound = True LOG.info('Found grid files specific for energy %s' % self.energy) break if not gridfilesfound: LOG.info("Will use generic grid files found, hope the energy is set right") list_of_gridfiles = [item for item in glob.glob(os.path.join(path_to_gridfiles, "*.grb")) + glob.glob(os.path.join(path_to_gridfiles, "*.grc"))] template = False if self.SteeringFile.count("template"): template = True ## Get from process file the proper whizard.in file if self.getProcessInFile: whizardin = "" res = self.obtainProcessList() if not res['OK']: LOG.error("Could not obtain process list") self.setApplicationStatus('Failed getting processlist') return res whizardin = self.processlist.getInFile(self.evttype) if not whizardin: LOG.error("Whizard input file was not found in process list, cannot proceed") self.setApplicationStatus('Whizard input file was not found') return S_ERROR("Error while resolving whizard input file") if whizardin.count("template"): template = True try: shutil.copy("%s/%s" % (mySoftDir, whizardin), "./whizardnew.in") self.SteeringFile = "whizardnew.in" except EnvironmentError: LOG.error("Could not copy %s from %s" % (whizardin, mySoftDir)) self.setApplicationStatus('Failed getting whizard.in file') return S_ERROR("Failed to obtain %s" % whizardin) ##Check existence of Les Houches input file leshouchesfiles = '' if not os.path.exists("LesHouches.msugra_1.in"): if self.susymodel: if self.susymodel == 1: if os.path.exists("%s/LesHouches_slsqhh.msugra_1.in" % (mySoftDir)): leshouchesfiles = "%s/LesHouches_slsqhh.msugra_1.in" % (mySoftDir) if self.susymodel == 2: if os.path.exists("%s/LesHouches_chne.msugra_1.in" % (mySoftDir)): leshouchesfiles = "%s/LesHouches_chne.msugra_1.in" % (mySoftDir) if self.Model: if self.genmodel.hasModel(self.Model)['OK']: if self.genmodel.getFile(self.Model)['OK']: if os.path.exists("%s/%s" % (mySoftDir, self.genmodel.getFile(self.Model)['Value'])): leshouchesfiles = "%s/%s" % (mySoftDir, self.genmodel.getFile(self.Model)['Value']) else: LOG.error("Request LesHouches file is missing, cannot proceed") self.setApplicationStatus("LesHouches file missing") return S_ERROR("The LesHouches file was not found. Probably you are using a wrong version of whizard.") else: LOG.warn("No file found attached to model %s" % self.Model) else: LOG.error("Model undefined:", self.Model) self.setApplicationStatus("Model undefined") return S_ERROR("No Model %s defined" % self.Model) else: leshouchesfiles = "LesHouches.msugra_1.in" outputfilename = self.evttype if self.optionsdict: LOG.info("Using: %s" % self.optionsdict) self.options = WhizardOptions(self.Model) res = self.options.changeAndReturn(self.optionsdict) if not res['OK']: return res res = self.options.toWhizardDotIn("whizard.in") elif not template: res = prepareWhizardFile(self.SteeringFile, outputfilename, self.energy, self.RandomSeed, self.NumberOfEvents, self.Lumi, "whizard.in") else: res = prepareWhizardFileTemplate(self.SteeringFile, outputfilename, self.parameters, "whizard.in") if not res['OK']: LOG.error('Something went wrong with input file generation') self.setApplicationStatus('Whizard: something went wrong with input file generation') return S_ERROR('Something went wrong with whizard.in file generation') foundproceesinwhizardin = res['Value'] scriptName = 'Whizard_%s_Run_%s.sh' % (self.applicationVersion, self.STEP_NUMBER) if os.path.exists(scriptName): os.remove(scriptName) script = open(scriptName, 'w') script.write('#!/bin/sh \n') script.write('#####################################################################\n') script.write('# Dynamically generated script to run a production or analysis job. #\n') script.write('#####################################################################\n') script.write('declare -x PATH=%s:$PATH\n' % mySoftDir) script.write('declare -x LD_LIBRARY_PATH=%s\n' % new_ld_lib_path) script.write('env | sort >> localEnv.log\n') script.write('echo =============================\n') script.write('echo Printing content of whizard.in \n') script.write('cat whizard.in\n') script.write('echo =============================\n') script.write('cp %s/whizard.mdl ./\n' % mySoftDir) if leshouchesfiles: if not leshouchesfiles == 'LesHouches.msugra_1.in': script.write('cp %s ./LesHouches.msugra_1.in\n' % (leshouchesfiles)) script.write('ln -s LesHouches.msugra_1.in fort.71\n') if len(list_of_gridfiles): for gridfile in list_of_gridfiles: script.write('cp %s ./\n' % (gridfile)) script.write('cp %s/whizard.prc ./\n' % mySoftDir) if self.genlevelcuts: res = self.makeWhizardDotCut1() if not res['OK']: script.close() LOG.error("Could not create the cut1 file") return S_ERROR("Could not create the cut1 file") script.write('echo =============================\n') script.write('echo Printing content of whizard.prc \n') script.write('cat whizard.prc\n') script.write('echo =============================\n') extracmd = "" if not self.debug: extracmd = "2>/dev/null" comm = "" if foundproceesinwhizardin: comm = 'whizard --simulation_input \'write_events_file = \"%s\"\'' % (outputfilename) else: comm = 'whizard --process_input \'process_id =\"%s\"\' --simulation_input \'write_events_file = \"%s\"\' ' % (self.evttype, outputfilename) comm = "%s %s %s\n" % (comm, self.extraCLIarguments, extracmd) LOG.info("Will run %s" % comm) script.write(comm) script.write('declare -x appstatus=$?\n') script.write('exit $appstatus\n') script.close() if os.path.exists(self.applicationLog): os.remove(self.applicationLog) os.chmod(scriptName, 0o755) comm = 'sh -c "./%s"' % (scriptName) self.setApplicationStatus('Whizard %s step %s' %(self.applicationVersion, self.STEP_NUMBER)) self.stdError = '' self.result = shellCall(0, comm, callbackFunction = self.redirectLogOutput, bufferLimit=209715200) #self.result = {'OK':True,'Value':(0,'Disabled Execution','')} if not self.result['OK']: LOG.error("Failed with error %s" % self.result['Message']) if not os.path.exists(self.applicationLog): LOG.error("Something went terribly wrong, the log file is not present") self.setApplicationStatus('%s failed terribly, you are doomed!' % (self.applicationName)) if not self.ignoreapperrors: return S_ERROR('%s did not produce the expected log' % (self.applicationName)) lumi = '' message = "" success = False ###Analyse log file with open(self.applicationLog) as logfile: for line in logfile: if line.count('! Event sample corresponds to luminosity'): elems = line.split() lumi = elems[-1] if line.count("*** Fatal error:"): status = 1 message = line break elif line.count("PYSTOP"): status = 1 message = line break elif line.count("No matrix element available"): status = 1 message = line break elif line.count("Floating point exception"): status = 1 message = line break elif line.count("Event generation finished."): success = True else: status = 0 if success: status = 0 else: status = 1 LOG.info('The sample generated has an equivalent luminosity of %s' % lumi) if lumi: self.workflow_commons['Luminosity'] = float(lumi) else: status = 1 ##Now care for the cross sections info = {} res = self.options.getAsDict() if os.path.exists("whizard.out") and res['OK']: full_opts_dict = res['Value'] processes = full_opts_dict['process_input']['process_id'].split() info = {} info['xsection'] = {} processes.append('sum') with open("whizard.out", "r") as inf: for line in inf: line = line.rstrip() for process in processes: if not process: continue if line.count(" %s " % process): info['xsection'][process] = {} line = line.lstrip() crosssection = line.split()[1] err_crosssection = line.split()[2] frac = line.split()[4] info['xsection'][process]['xsection'] = float(crosssection) info['xsection'][process]['err_xsection'] = float(err_crosssection) info['xsection'][process]['fraction'] = float(frac) if info: if 'Info' not in self.workflow_commons: self.workflow_commons['Info'] = info else: self.workflow_commons['Info'].update(info) LOG.info("Status after the application execution is %s" % str(status)) messageout = 'Whizard %s Successful' % (self.applicationVersion) failed = False if status != 0: LOG.error("Whizard execution completed with errors:") failed = True else: LOG.info("Whizard execution completed successfully") ###Deal with output file if len(self.OutputFile): if os.path.exists(outputfilename + ".001.stdhep"): LOG.notice("Looking for output files") ofnames = glob.glob(outputfilename+'*.stdhep') if len(ofnames) > 1: basename = self.OutputFile.split(".stdhep")[0] i = 0 for of in ofnames: i += 1 name = basename + "_" + str(i) + ".stdhep" os.rename(of, name) else: os.rename(outputfilename + ".001.stdhep", self.OutputFile) else: LOG.error("Whizard execution did not produce a stdhep file") self.setApplicationStatus('Whizard %s Failed to produce STDHEP file' % (self.applicationVersion)) messageout = 'Whizard Failed to produce STDHEP file' if not self.ignoreapperrors: return S_ERROR(messageout) if failed is True: LOG.error("==================================\n StdError:\n") LOG.error(message) self.setApplicationStatus('%s Exited With Status %s' % (self.applicationName, status)) LOG.error('Whizard Exited With Status %s' % (status)) messageout = 'Whizard Exited With Status %s' % (status) if not self.ignoreapperrors: return S_ERROR(messageout) else: self.setApplicationStatus(messageout) return S_OK( { "OutputFile": self.OutputFile } ) def makeWhizardDotCut1(self): """ When users need whizard cuts, this is called to prepare the file :return: S_OK() """ cutf = open("whizard.cut1","w") for key, values in self.genlevelcuts.items(): cutf.write("process %s\n" % key) for val in values: cutf.write(" %s\n" % val) cutf.close() return S_OK()
class WhizardAnalysis(ModuleBase): """ Specific Module to run a Whizard job. """ def __init__(self): super(WhizardAnalysis, self).__init__() self.enable = True self.STEP_NUMBER = '' self.debug = True self.log = gLogger.getSubLogger("WhizardAnalysis") self.SteeringFile = '' self.OutputFile = '' self.NumberOfEvents = 1 self.Lumi = 0 self.applicationName = 'whizard' self.evttype = "" self.RandomSeed = 0 self.getProcessInFile = False self.datMan = DataManager() self.processlist = None self.parameters = {} self.susymodel = 0 self.Model = '' self.genmodel = GeneratorModels() self.eventstring = [ '! ', 'Fatal error:', 'PYSTOP', 'No matrix element available', 'Floating point exception', 'Event generation finished.', " n_events", "luminosity", " sum " ] self.excludeAllButEventString = False self.steeringparameters = '' self.options = None self.optionsdict = {} self.OptionsDictStr = '' self.GenLevelCutDictStr = '' self.genlevelcuts = {} self.willCut = False self.useGridFiles = False def obtainProcessList(self): """Internal function Get the process list from storage if whizard.in was not provided :return: S_OK(), S_ERROR() """ res = self.ops.getValue("/ProcessList/Location", "") if not res: return S_ERROR("No process list found") processlistloc = res if not os.path.exists(os.path.basename(processlistloc)): res = self.datMan.getFile(processlistloc) if not res['OK']: self.log.error('Could not get processlist: %s' % res['Message']) return res self.processlist = ProcessList(os.path.basename(processlistloc)) return S_OK() def applicationSpecificInputs(self): """Resolve module input :return: S_OK() """ self.parameters['ENERGY'] = self.energy if not self.RandomSeed and self.jobID: self.RandomSeed = self.jobID if 'IS_PROD' in self.workflow_commons or 'IS_DBD_GEN_PROD' in self.workflow_commons: self.RandomSeed = int( str(int(self.workflow_commons["PRODUCTION_ID"])) + str(int(self.workflow_commons["JOB_ID"]))) self.parameters['SEED'] = self.RandomSeed self.parameters['NBEVTS'] = self.NumberOfEvents self.parameters['LUMI'] = self.Lumi ##EVER USED??? if 'SusyModel' in self.step_commons: self.susymodel = self.step_commons['SusyModel'] self.SteeringFile = os.path.basename( self.step_commons.get("InputFile", self.SteeringFile)) if self.SteeringFile == "whizard.in": os.rename(self.SteeringFile, "whizardnew.in") self.SteeringFile = "whizardnew.in" self.parameters['PROCESS'] = self.evttype listofparams = self.steeringparameters.split(";") for param in listofparams: if param.count("="): self.parameters[param.split("=")[0]] = param.split("=")[1] if self.OptionsDictStr: self.log.info( "Will use whizard.in definition from WhizardOptions.") try: self.optionsdict = eval(self.OptionsDictStr) if 'integration_input' not in self.optionsdict: self.optionsdict['integration_input'] = {} if 'seed' not in self.optionsdict['integration_input']: self.optionsdict['integration_input']['seed'] = int( self.RandomSeed) if 'process_input' in self.optionsdict: if 'sqrts' in self.optionsdict['process_input']: self.energy = self.optionsdict['process_input'][ 'sqrts'] except: return S_ERROR( "Could not convert string to dictionary for optionsdict") if self.GenLevelCutDictStr: self.log.info("Found generator level cuts") try: self.genlevelcuts = eval(self.GenLevelCutDictStr) except: return S_ERROR( "Could not convert the generator level cuts back to dictionary" ) if not len(self.SteeringFile) and not self.optionsdict: self.getProcessInFile = True if "IS_PROD" in self.workflow_commons: if self.workflow_commons["IS_PROD"] and not self.willCut: #self.OutputFile = getProdFilename(self.OutputFile,int(self.workflow_commons["PRODUCTION_ID"]), # int(self.workflow_commons["JOB_ID"])) if 'ProductionOutputData' in self.workflow_commons: outputlist = self.workflow_commons[ 'ProductionOutputData'].split(";") for obj in outputlist: if obj.lower().count("_gen_"): self.OutputFile = os.path.basename(obj) break else: #This is because most likely there is stdhepcut running after self.OutputFile = "willcut.stdhep" #getProdFilename(self.OutputFile,int(self.workflow_commons["PRODUCTION_ID"]), # int(self.workflow_commons["JOB_ID"])) if "IS_DBD_GEN_PROD" in self.workflow_commons and self.workflow_commons[ "IS_DBD_GEN_PROD"]: #self.OutputFile = getProdFilename(self.OutputFile,int(self.workflow_commons["PRODUCTION_ID"]), # int(self.workflow_commons["JOB_ID"])) if 'ProductionOutputData' in self.workflow_commons: outputlist = self.workflow_commons[ 'ProductionOutputData'].split(";") for obj in outputlist: self.OutputFile = os.path.basename(obj) break else: self.OutputFile = getProdFilename( self.OutputFile, int(self.workflow_commons["PRODUCTION_ID"]), int(self.workflow_commons["JOB_ID"])) return S_OK() def runIt(self): """ Called by Agent Executes the following - resolve input variables - resolve installation location - resolve dependencies location (beam_spectra) - get processlist if needed - define output file name - prepare whizard.in - make magic :return: S_OK(), S_ERROR() """ self.result = S_OK() if not self.platform: self.result = S_ERROR('No ILC platform selected') elif not self.applicationLog: self.result = S_ERROR('No Log file provided') if not self.result['OK']: self.log.error("Failed to resolve input parameters:", self.result["Message"]) return self.result if not self.workflowStatus['OK'] or not self.stepStatus['OK']: self.log.verbose( 'Workflow status = %s, step status = %s' % (self.workflowStatus['OK'], self.stepStatus['OK'])) return S_OK( 'Whizard should not proceed as previous step did not end properly' ) #if self.debug: # self.excludeAllButEventString = False res = getSoftwareFolder(self.platform, self.applicationName, self.applicationVersion) if not res['OK']: self.log.error("Failed getting software folder", res['Message']) self.setApplicationStatus('Failed finding software') return res mySoftDir = res['Value'] ###Remove libc removeLibc(mySoftDir + "/lib") ##Need to fetch the new LD_LIBRARY_PATH new_ld_lib_path = getNewLDLibs(self.platform, self.applicationName, self.applicationVersion) #Don't forget to prepend the application's libs new_ld_lib_path = mySoftDir + "/lib:" + new_ld_lib_path ### Resolve dependencies (look for beam_spectra) deps = resolveDeps(self.platform, self.applicationName, self.applicationVersion) path_to_beam_spectra = "" path_to_gridfiles = "" for dep in deps: res = getSoftwareFolder(self.platform, dep["app"], dep['version']) if not res['OK']: self.log.error("Failed getting software folder", res['Message']) self.setApplicationStatus('Failed finding software') return res depfolder = res['Value'] if dep["app"] == "beam_spectra": path_to_beam_spectra = depfolder elif dep["app"] == "gridfiles": path_to_gridfiles = depfolder ##Env variables needed to run whizard: avoids hard coded locations os.environ['LUMI_LINKER'] = path_to_beam_spectra + "/lumi_linker_000" os.environ[ 'PHOTONS_B1'] = path_to_beam_spectra + "/photons_beam1_linker_000" os.environ[ 'PHOTONS_B2'] = path_to_beam_spectra + "/photons_beam2_linker_000" os.environ['EBEAM'] = path_to_beam_spectra + "/ebeam_in_linker_000" os.environ['PBEAM'] = path_to_beam_spectra + "/pbeam_in_linker_000" os.environ[ 'LUMI_EE_LINKER'] = path_to_beam_spectra + "/lumi_ee_linker_000" os.environ[ 'LUMI_EG_LINKER'] = path_to_beam_spectra + "/lumi_eg_linker_000" os.environ[ 'LUMI_GE_LINKER'] = path_to_beam_spectra + "/lumi_ge_linker_000" os.environ[ 'LUMI_GG_LINKER'] = path_to_beam_spectra + "/lumi_gg_linker_000" list_of_gridfiles = [] if path_to_gridfiles and self.useGridFiles: tmp_list_of_gridfiles = [ os.path.join(path_to_gridfiles, item) for item in os.listdir(path_to_gridfiles) ] gridfilesfound = False for path in tmp_list_of_gridfiles: if os.path.isdir(path) and path.count(str(self.energy)): #Here look for a sub directory for the energy related grid files list_of_gridfiles = [ os.path.join(path, item) for item in os.listdir(path) ] gridfilesfound = True self.log.info('Found grid files specific for energy %s' % self.energy) break if not gridfilesfound: self.log.info( "Will use generic grid files found, hope the energy is set right" ) list_of_gridfiles = [ item for item in glob.glob(os.path.join(path_to_gridfiles, "*.grb")) + glob.glob(os.path.join(path_to_gridfiles, "*.grc")) ] template = False if self.SteeringFile.count("template"): template = True ## Get from process file the proper whizard.in file if self.getProcessInFile: whizardin = "" res = self.obtainProcessList() if not res['OK']: self.log.error("Could not obtain process list") self.setApplicationStatus('Failed getting processlist') return res whizardin = self.processlist.getInFile(self.evttype) if not whizardin: self.log.error( "Whizard input file was not found in process list, cannot proceed" ) self.setApplicationStatus('Whizard input file was not found') return S_ERROR("Error while resolving whizard input file") if whizardin.count("template"): template = True try: shutil.copy("%s/%s" % (mySoftDir, whizardin), "./whizardnew.in") self.SteeringFile = "whizardnew.in" except EnvironmentError: self.log.error("Could not copy %s from %s" % (whizardin, mySoftDir)) self.setApplicationStatus('Failed getting whizard.in file') return S_ERROR("Failed to obtain %s" % whizardin) ##Check existence of Les Houches input file leshouchesfiles = '' if not os.path.exists("LesHouches.msugra_1.in"): if self.susymodel: if self.susymodel == 1: if os.path.exists("%s/LesHouches_slsqhh.msugra_1.in" % (mySoftDir)): leshouchesfiles = "%s/LesHouches_slsqhh.msugra_1.in" % ( mySoftDir) if self.susymodel == 2: if os.path.exists("%s/LesHouches_chne.msugra_1.in" % (mySoftDir)): leshouchesfiles = "%s/LesHouches_chne.msugra_1.in" % ( mySoftDir) if self.Model: if self.genmodel.hasModel(self.Model)['OK']: if self.genmodel.getFile(self.Model)['OK']: if os.path.exists( "%s/%s" % (mySoftDir, self.genmodel.getFile( self.Model)['Value'])): leshouchesfiles = "%s/%s" % ( mySoftDir, self.genmodel.getFile( self.Model)['Value']) else: self.log.error( "Request LesHouches file is missing, cannot proceed" ) self.setApplicationStatus( "LesHouches file missing") return S_ERROR( "The LesHouches file was not found. Probably you are using a wrong version of whizard." ) else: self.log.warn("No file found attached to model %s" % self.Model) else: self.log.error("Model undefined:", self.Model) self.setApplicationStatus("Model undefined") return S_ERROR("No Model %s defined" % self.Model) else: leshouchesfiles = "LesHouches.msugra_1.in" outputfilename = self.evttype if self.optionsdict: self.log.info("Using: %s" % self.optionsdict) self.options = WhizardOptions(self.Model) res = self.options.changeAndReturn(self.optionsdict) if not res['OK']: return res res = self.options.toWhizardDotIn("whizard.in") elif not template: res = prepareWhizardFile(self.SteeringFile, outputfilename, self.energy, self.RandomSeed, self.NumberOfEvents, self.Lumi, "whizard.in") else: res = prepareWhizardFileTemplate(self.SteeringFile, outputfilename, self.parameters, "whizard.in") if not res['OK']: self.log.error('Something went wrong with input file generation') self.setApplicationStatus( 'Whizard: something went wrong with input file generation') return S_ERROR( 'Something went wrong with whizard.in file generation') foundproceesinwhizardin = res['Value'] scriptName = 'Whizard_%s_Run_%s.sh' % (self.applicationVersion, self.STEP_NUMBER) if os.path.exists(scriptName): os.remove(scriptName) script = open(scriptName, 'w') script.write('#!/bin/sh \n') script.write( '#####################################################################\n' ) script.write( '# Dynamically generated script to run a production or analysis job. #\n' ) script.write( '#####################################################################\n' ) script.write('declare -x PATH=%s:$PATH\n' % mySoftDir) script.write('declare -x LD_LIBRARY_PATH=%s\n' % new_ld_lib_path) script.write('env | sort >> localEnv.log\n') script.write('echo =============================\n') script.write('echo Printing content of whizard.in \n') script.write('cat whizard.in\n') script.write('echo =============================\n') script.write('cp %s/whizard.mdl ./\n' % mySoftDir) if leshouchesfiles: if not leshouchesfiles == 'LesHouches.msugra_1.in': script.write('cp %s ./LesHouches.msugra_1.in\n' % (leshouchesfiles)) script.write('ln -s LesHouches.msugra_1.in fort.71\n') if len(list_of_gridfiles): for gridfile in list_of_gridfiles: script.write('cp %s ./\n' % (gridfile)) script.write('cp %s/whizard.prc ./\n' % mySoftDir) if self.genlevelcuts: res = self.makeWhizardDotCut1() if not res['OK']: script.close() self.log.error("Could not create the cut1 file") return S_ERROR("Could not create the cut1 file") script.write('echo =============================\n') script.write('echo Printing content of whizard.prc \n') script.write('cat whizard.prc\n') script.write('echo =============================\n') extracmd = "" if not self.debug: extracmd = "2>/dev/null" comm = "" if foundproceesinwhizardin: comm = 'whizard --simulation_input \'write_events_file = \"%s\"\'' % ( outputfilename) else: comm = 'whizard --process_input \'process_id =\"%s\"\' --simulation_input \'write_events_file = \"%s\"\' ' % ( self.evttype, outputfilename) comm = "%s %s %s\n" % (comm, self.extraCLIarguments, extracmd) self.log.info("Will run %s" % comm) script.write(comm) script.write('declare -x appstatus=$?\n') script.write('exit $appstatus\n') script.close() if os.path.exists(self.applicationLog): os.remove(self.applicationLog) os.chmod(scriptName, 0755) comm = 'sh -c "./%s"' % (scriptName) self.setApplicationStatus('Whizard %s step %s' % (self.applicationVersion, self.STEP_NUMBER)) self.stdError = '' self.result = shellCall(0, comm, callbackFunction=self.redirectLogOutput, bufferLimit=209715200) #self.result = {'OK':True,'Value':(0,'Disabled Execution','')} if not self.result['OK']: self.log.error("Failed with error %s" % self.result['Message']) if not os.path.exists(self.applicationLog): self.log.error( "Something went terribly wrong, the log file is not present") self.setApplicationStatus('%s failed terribly, you are doomed!' % (self.applicationName)) if not self.ignoreapperrors: return S_ERROR('%s did not produce the expected log' % (self.applicationName)) lumi = '' message = "" success = False ###Analyse log file with open(self.applicationLog) as logfile: for line in logfile: if line.count('! Event sample corresponds to luminosity'): elems = line.split() lumi = elems[-1] if line.count("*** Fatal error:"): status = 1 message = line break elif line.count("PYSTOP"): status = 1 message = line break elif line.count("No matrix element available"): status = 1 message = line break elif line.count("Floating point exception"): status = 1 message = line break elif line.count("Event generation finished."): success = True else: status = 0 if success: status = 0 else: status = 1 self.log.info( 'The sample generated has an equivalent luminosity of %s' % lumi) if lumi: self.workflow_commons['Luminosity'] = float(lumi) else: status = 1 ##Now care for the cross sections info = {} res = self.options.getAsDict() if os.path.exists("whizard.out") and res['OK']: full_opts_dict = res['Value'] processes = full_opts_dict['process_input']['process_id'].split() info = {} info['xsection'] = {} processes.append('sum') with open("whizard.out", "r") as inf: for line in inf: line = line.rstrip() for process in processes: if not process: continue if line.count(" %s " % process): info['xsection'][process] = {} line = line.lstrip() crosssection = line.split()[1] err_crosssection = line.split()[2] frac = line.split()[4] info['xsection'][process]['xsection'] = float( crosssection) info['xsection'][process]['err_xsection'] = float( err_crosssection) info['xsection'][process]['fraction'] = float(frac) if info: if 'Info' not in self.workflow_commons: self.workflow_commons['Info'] = info else: self.workflow_commons['Info'].update(info) self.log.info("Status after the application execution is %s" % str(status)) messageout = 'Whizard %s Successful' % (self.applicationVersion) failed = False if status != 0: self.log.error("Whizard execution completed with errors:") failed = True else: self.log.info("Whizard execution completed successfully") ###Deal with output file if len(self.OutputFile): if os.path.exists(outputfilename + ".001.stdhep"): self.log.notice("Looking for output files") ofnames = glob.glob(outputfilename + '*.stdhep') if len(ofnames) > 1: basename = self.OutputFile.split(".stdhep")[0] i = 0 for of in ofnames: i += 1 name = basename + "_" + str(i) + ".stdhep" os.rename(of, name) else: os.rename(outputfilename + ".001.stdhep", self.OutputFile) else: self.log.error( "Whizard execution did not produce a stdhep file") self.setApplicationStatus( 'Whizard %s Failed to produce STDHEP file' % (self.applicationVersion)) messageout = 'Whizard Failed to produce STDHEP file' if not self.ignoreapperrors: return S_ERROR(messageout) if failed is True: self.log.error("==================================\n StdError:\n") self.log.error(message) self.setApplicationStatus('%s Exited With Status %s' % (self.applicationName, status)) self.log.error('Whizard Exited With Status %s' % (status)) messageout = 'Whizard Exited With Status %s' % (status) if not self.ignoreapperrors: return S_ERROR(messageout) else: self.setApplicationStatus(messageout) return S_OK({"OutputFile": self.OutputFile}) def makeWhizardDotCut1(self): """ When users need whizard cuts, this is called to prepare the file :return: S_OK() """ cutf = open("whizard.cut1", "w") for key, values in self.genlevelcuts.items(): cutf.write("process %s\n" % key) for val in values: cutf.write(" %s\n" % val) cutf.close() return S_OK()
class Whizard(LCApplication): """ Runs whizard to generate a given event type Usage: >>> wh = Whizard(dirac.getProcessList()) >>> wh.setEvtType("ee_h_mumu") >>> wh.setEnergy(500) >>> wh.setNumberOfEvents(1000) >>> wh.setModel("sm") use :func:`setExtraArguments` to overwrite the content of the whizard.in in case you use something not standard (parameter scan for exmple) """ def __init__(self, processlist = None, paramdict = None): self.parameterDict = {} self.model = 'sm' self.randomSeed = 0 self.luminosity = 0 self.jobIndex = '' self._optionsdictstr = '' self.fullParameterDict = {} self.generatorLevelCuts = {} self._genlevelcutsstr = '' self._leshouchesfiles = None self._generatormodels = GeneratorModels() self.eventType = '' self.globalEventType = '' self.useGridFiles = False self._allowedparams = ['PNAME1', 'PNAME2', 'POLAB1', 'POLAB2', 'USERB1', 'USERB2', 'ISRB1', 'ISRB2', 'EPAB1', 'EPAB2', 'RECOIL', 'INITIALS', 'USERSPECTRUM'] self._wo = None self.parameters = [] self._processlist = None if processlist: self._processlist = processlist super(Whizard, self).__init__( paramdict ) ##Those 4 need to come after default constructor self._modulename = 'WhizardAnalysis' self._moduledescription = 'Module to run WHIZARD' self.appname = 'whizard' self.datatype = 'gen' self._paramsToExclude.extend( [ '_optionsdictstr', '_genlevelcutsstr', '_leshouchesfiles', '_generatormodels', '_allowedparams', '_wo','_processlist' ] ) def getPDict(self): """ Provide predefined parameter dictionary """ return getDict() def setEvtType(self, evttype): """ Define process. If the process given is not found, when calling :func:`UserJob.append() <ILCDIRAC.Interfaces.API.NewInterface.UserJob.UserJob.append>` a full list is printed. :param string evttype: Process to generate """ self._checkArgs( { 'evttype' : types.StringTypes } ) if self.addedtojob: self._log.error("Cannot modify this attribute once application has been added to Job") return S_ERROR("Cannot modify") self.eventType = evttype def setGlobalEvtType(self, globalname): """ When producing multiple process in one job, it is needed to define this for the output file name. It's mandatory to use the :any:`setFullParameterDict` method when using this. """ self._checkArgs( { 'globalname' : types.StringTypes } ) self.globalEventType = globalname def setLuminosity(self, lumi): """ Optional: Define luminosity to generate :param float lumi: Luminosity to generate. Not available if cross section is not known a priori. Use with care. """ self._checkArgs( { 'lumi' : types.FloatType } ) self.luminosity = lumi def setRandomSeed(self, randomSeed): """ Optional: Define random seed to use. Default is Job ID. :param int randomSeed: Seed to use during integration and generation. """ self._checkArgs( { 'randomSeed' : types.IntType } ) self.randomSeed = randomSeed def setParameterDict(self, paramdict): """ Parameters for Whizard steering files :param dict paramdict: Dictionary of parameters for the whizard templates. Most parameters are set on the fly. """ self._checkArgs( { 'paramdict' : types.DictType } ) self.parameterDict = paramdict def setGeneratorLevelCuts(self, cutsdict): """ Define generator level cuts (to be put in whizard.cut1) Refer to http://whizard.hepforge.org/manual_w1/manual005.html#toc12 for details about how to set cuts. >>> wh.setGeneratorLevelCuts({'e1e1_o':["cut M of 3 within 10 99999","cut E of 3 within 5 99999"]}) :param dict cutsdict: Dictionary of cuts """ self._checkArgs( { 'cutsdict' : types.DictType } ) self.generatorLevelCuts = cutsdict def setFullParameterDict(self, pdict): """ Parameters for Whizard steering files, better than above as much more complete (cannot be more complete) >>> pdict = {} >>> pdict['process_input'] = {} >>> #processes below are not those of the templates, but those of the whizard.prc >>> pdict['process_input']['process_id']='h_n1n1' >>> pdict['process_input']['sqrts'] = 3000. >>> pdict['simulation_input'] = {} >>> pdict['simulation_input']['n_events'] = 100 >>> pdict['beam_input_1'] = {} >>> pdict['beam_input_1']['polarization']='1.0 0.0' >>> pdict['beam_input_1']['USER_spectrum_mode'] = 11 >>> pdict['beam_input_2'] = {} >>> pdict['beam_input_2']['polarization']='0.0 1.0' >>> pdict['beam_input_2']['USER_spectrum_mode'] = -11 >>> wh.setFullParameterDict(pdict) The first key corresponds to the sections of the whizard.in, while the second corresponds to the possible parameters. All keys/values can be found in the WHIZARD documentation: http://whizard.hepforge.org/manual_w1/manual005.html#toc11 :param dict pdict: Dictionnary of parameters """ self._checkArgs( { 'pdict' : types.DictType } ) self.fullParameterDict = pdict #self._wo.changeAndReturn(dict) def setModel(self, model): """ Optional: Define Model :param string model: Model to use for generation. Predefined list available in the :mod:`GeneratorModels<ILCDIRAC.Core.Utilities.GeneratorModels.GeneratorModels>` class. """ self._checkArgs( { 'model' : types.StringTypes } ) self.model = model def willCut(self): """ You need this if you plan on cutting using :mod:`StdhepCut <ILCDIRAC.Interfaces.API.NewInterface.Applications.StdhepCut.StdhepCut>` """ self.willBeCut = True def usingGridFiles(self): """ Call this if you want to use the grid files that come with the Whizard version used. Beware: Depends on the energy and generator cuts, use it if you know what you are doing. """ self.useGridFiles = True def setJobIndex(self, index): """ Optional: Define Job Index. Added in the file name between the event type and the extension. :param string index: Index to use for generation """ self._checkArgs( { 'index' : types.StringTypes } ) self.jobIndex = index def dumpWhizardDotIn(self, fname = 'whizard.in'): """ Dump the content of the whizard.in file requested for this application :param string fname: filename in which whizard.in is written """ if self.addedtojob: self._wo.toWhizardDotIn(fname) else: self._reportError("Can't dump the whizard.in as there can be further changes") def _checkConsistency(self): """ Check the consistency, called from Application """ self._wo = WhizardOptions(self.model) if not self.fullParameterDict: if not self.energy : return S_ERROR('Energy not set') if not self.numberOfEvents : return S_ERROR('Number of events not set!') if not self.eventType: return S_ERROR("Process not defined") else: res = self._wo.checkFields(self.fullParameterDict) if not res['OK']: return res self._wo.changeAndReturn(self.fullParameterDict) res = self._wo.getValue("process_input/process_id") if not len(res['Value']): if self.eventType: if not 'process_input' in self.fullParameterDict: self.fullParameterDict['process_input'] = {} self.fullParameterDict['process_input']['process_id'] = self.eventType else: return S_ERROR("Event type not specified") self.eventType = res['Value'] res = self._wo.getValue("process_input/sqrts") if type(res['Value']) == type(3) or type(res['Value']) == type(3.): energy = res['Value'] else: energy = eval(res['Value']) if not energy: if self.energy: if not 'process_input' in self.fullParameterDict: self.fullParameterDict['process_input'] = {} self.fullParameterDict['process_input']['sqrts'] = self.energy energy = self.energy else: return S_ERROR("Energy set to 0") self.energy = energy res = self._wo.getValue("simulation_input/n_events") if type(res['Value']) == type(3) or type(res['Value']) == type(3.): numberOfEvents = res['Value'] else: numberOfEvents = eval(res['Value']) if not numberOfEvents: if self.numberOfEvents: if not 'simulation_input' in self.fullParameterDict: self.fullParameterDict['simulation_input'] = {} self.fullParameterDict['simulation_input']['n_events'] = self.numberOfEvents numberOfEvents = self.numberOfEvents else: return S_ERROR("Number of events set to 0") self.numberOfEvents = numberOfEvents if not self._processlist: return S_ERROR("Process list was not given") if self.generatorLevelCuts: for process in self.generatorLevelCuts.keys(): if not process in self.eventType.split(): self._log.info("You want to cut on %s but that process is not to be generated" % process) for values in self.generatorLevelCuts.values(): if not type(values) == types.ListType: return S_ERROR('Type of %s is not a list, cannot proceed' % values) self._genlevelcutsstr = str(self.generatorLevelCuts) if self.eventType: processes = self.eventType.split() if len(processes) > 1 and not self.globalEventType: return S_ERROR("Global name MUST be defined when producing multiple processes in one job") elif self.globalEventType: self.eventType = self.globalEventType for process in processes: if not self._processlist.existsProcess(process)['Value']: self._log.notice("Available processes are:") self._processlist.printProcesses() return S_ERROR('Process %s does not exists'%process) else: cspath = self._processlist.getCSPath(process) whiz_file = os.path.basename(cspath) version = whiz_file.replace(".tar.gz","").replace(".tgz","").replace("whizard","") if self.version: if self.version != version: return S_ERROR("All processes to consider are not available in the same WHIZARD version") else: self.version = version self._log.info("Found the process %s in whizard %s"%(process, self.version)) if not self.version: return S_ERROR('No version found') if self.model: if not self._generatormodels.hasModel(self.model)['OK']: return S_ERROR("Unknown model %s" % self.model) if self.outputFile: if self.outputFile.count("/"): return S_ERROR("The OutputFile name is a file name, not a path. Remove any / in there") if not self.outputFile and self._jobtype == 'User': self.outputFile = self.eventType if self.jobIndex : self.outputFile += "_" + self.jobIndex self.outputFile += "_gen.stdhep" if not self._jobtype == 'User': if not self.willBeCut: self._listofoutput.append({"outputFile":"@{OutputFile}", "outputPath":"@{OutputPath}", "outputDataSE":'@{OutputSE}'}) self.prodparameters['nbevts'] = self.numberOfEvents self.prodparameters['Process'] = self.eventType self.prodparameters['model'] = self.model self.prodparameters['Energy'] = self.energy self.prodparameters['whizardparams'] = self.fullParameterDict self.prodparameters['gencuts'] = self.generatorLevelCuts self.prodparameters['gridfiles'] = self.useGridFiles if not self.fullParameterDict and self.parameterDict: for key in self.parameterDict.keys(): if not key in self._allowedparams: return S_ERROR("Unknown parameter %s"%key) self.setParameter( 'PNAME1', 'e1', "Assuming incoming beam 1 to be electrons" ) self.setParameter( 'PNAME2', 'E1', "Assuming incoming beam 2 to be positrons" ) self.setParameter( 'POLAB1', '0.0 0.0', "Assuming no polarization for beam 1" ) self.setParameter( 'POLAB2', '0.0 0.0', "Assuming no polarization for beam 2" ) self.setParameter( 'USERB1', 'T', "Will put beam spectrum to True for beam 1" ) self.setParameter( 'USERB2', 'T', "Will put beam spectrum to True for beam 2" ) self.setParameter( 'ISRB1', 'T', "Will put ISR to True for beam 1" ) self.setParameter( 'ISRB2', 'T', "Will put ISR to True for beam 2" ) self.setParameter( 'EPAB1', 'F', "Will put EPA to False for beam 1" ) self.setParameter( 'EPAB2', 'F', "Will put EPA to False for beam 2" ) self.setParameter( 'RECOIL', 'F', "Will set Beam_recoil to False" ) self.setParameter( 'INITIALS', 'F', "Will set keep_initials to False" ) self.setParameter( 'USERSPECTRUM', '11', "Will set USER_spectrum_on to +-11" ) self.parameters = ";".join( self.parameters ) elif self.fullParameterDict: self._optionsdictstr = str(self.fullParameterDict) return S_OK() def _applicationModule(self): md1 = self._createModuleDefinition() md1.addParameter(Parameter("evttype", "", "string", "", "", False, False, "Process to generate")) md1.addParameter(Parameter("RandomSeed", 0, "int", "", "", False, False, "Random seed for the generator")) md1.addParameter(Parameter("Lumi", 0, "float", "", "", False, False, "Luminosity of beam")) md1.addParameter(Parameter("Model", "", "string", "", "", False, False, "Model for generation")) md1.addParameter(Parameter("SteeringFile", "", "string", "", "", False, False, "Steering file")) md1.addParameter(Parameter("steeringparameters", "", "string", "", "", False, False, "Specific steering parameters")) md1.addParameter(Parameter("OptionsDictStr", "", "string", "", "", False, False, "Options dict to create full whizard.in on the fly")) md1.addParameter(Parameter("GenLevelCutDictStr", "", "string", "", "", False, False, "Generator level cuts to put in whizard.cut1")) md1.addParameter(Parameter("willCut", False, "bool", "", "", False, False, "Will cut after")) md1.addParameter(Parameter("useGridFiles", True, "bool", "", "", False, False, "Will use grid files")) md1.addParameter(Parameter("debug", False, "bool", "", "", False, False, "debug mode")) return md1 def _applicationModuleValues(self, moduleinstance): moduleinstance.setValue("evttype", self.eventType) moduleinstance.setValue("RandomSeed", self.randomSeed) moduleinstance.setValue("Lumi", self.luminosity) moduleinstance.setValue("Model", self.model) moduleinstance.setValue("SteeringFile", self.steeringFile) moduleinstance.setValue("steeringparameters", self.parameters) moduleinstance.setValue("OptionsDictStr", self._optionsdictstr) moduleinstance.setValue("GenLevelCutDictStr", self._genlevelcutsstr) moduleinstance.setValue("willCut", self.willBeCut) moduleinstance.setValue("useGridFiles", self.useGridFiles) moduleinstance.setValue("debug", self.debug) def _userjobmodules(self, stepdefinition): res1 = self._setApplicationModuleAndParameters(stepdefinition) res2 = self._setUserJobFinalization(stepdefinition) if not res1["OK"] or not res2["OK"] : return S_ERROR('userjobmodules failed') return S_OK() def _prodjobmodules(self, stepdefinition): res1 = self._setApplicationModuleAndParameters(stepdefinition) res2 = self._setOutputComputeDataList(stepdefinition) if not res1["OK"] or not res2["OK"] : return S_ERROR('prodjobmodules failed') return S_OK() def setParameter(self, parameter, defaultValue, docString): if not parameter in self.parameterDict: self._log.info(docString) self.parameters.append( "%s=%s" % (parameter, defaultValue) ) else: self.parameters.append( "%s=%s" % (parameter, self.parameterDict[parameter]) )
class Whizard(LCApplication): """ Runs whizard to generate a given event type Usage: >>> wh = Whizard(dirac.getProcessList()) >>> wh.setEvtType("ee_h_mumu") >>> wh.setEnergy(500) >>> wh.setNumberOfEvents(1000) >>> wh.setModel("sm") use :func:`setExtraArguments` to overwrite the content of the whizard.in in case you use something not standard (parameter scan for exmple) """ def __init__(self, processlist=None, paramdict=None): self.parameterDict = {} self.model = 'sm' self.randomSeed = 0 self.luminosity = 0 self.jobIndex = '' self._optionsdictstr = '' self.fullParameterDict = {} self.generatorLevelCuts = {} self._genlevelcutsstr = '' self._leshouchesfiles = None self._generatormodels = GeneratorModels() self.eventType = '' self.globalEventType = '' self.useGridFiles = False self._allowedparams = [ 'PNAME1', 'PNAME2', 'POLAB1', 'POLAB2', 'USERB1', 'USERB2', 'ISRB1', 'ISRB2', 'EPAB1', 'EPAB2', 'RECOIL', 'INITIALS', 'USERSPECTRUM' ] self._wo = None self.parameters = [] self._processlist = None if processlist: self._processlist = processlist super(Whizard, self).__init__(paramdict) ##Those 4 need to come after default constructor self._modulename = 'WhizardAnalysis' self._moduledescription = 'Module to run WHIZARD' self.appname = 'whizard' self.datatype = 'gen' self._paramsToExclude.extend([ '_optionsdictstr', '_genlevelcutsstr', '_leshouchesfiles', '_generatormodels', '_allowedparams', '_wo', '_processlist' ]) def getPDict(self): """ Provide predefined parameter dictionary """ return getDict() def setEvtType(self, evttype): """ Define process. If the process given is not found, when calling :func:`UserJob.append() <ILCDIRAC.Interfaces.API.NewInterface.UserJob.UserJob.append>` a full list is printed. :param string evttype: Process to generate """ self._checkArgs({'evttype': types.StringTypes}) if self.addedtojob: self._log.error( "Cannot modify this attribute once application has been added to Job" ) return S_ERROR("Cannot modify") self.eventType = evttype def setGlobalEvtType(self, globalname): """ When producing multiple process in one job, it is needed to define this for the output file name. It's mandatory to use the :any:`setFullParameterDict` method when using this. """ self._checkArgs({'globalname': types.StringTypes}) self.globalEventType = globalname def setLuminosity(self, lumi): """ Optional: Define luminosity to generate :param float lumi: Luminosity to generate. Not available if cross section is not known a priori. Use with care. """ self._checkArgs({'lumi': types.FloatType}) self.luminosity = lumi def setRandomSeed(self, randomSeed): """ Optional: Define random seed to use. Default is Job ID. :param int randomSeed: Seed to use during integration and generation. """ self._checkArgs({'randomSeed': types.IntType}) self.randomSeed = randomSeed def setParameterDict(self, paramdict): """ Parameters for Whizard steering files :param dict paramdict: Dictionary of parameters for the whizard templates. Most parameters are set on the fly. """ self._checkArgs({'paramdict': types.DictType}) self.parameterDict = paramdict def setGeneratorLevelCuts(self, cutsdict): """ Define generator level cuts (to be put in whizard.cut1) Refer to http://whizard.hepforge.org/manual_w1/manual005.html#toc12 for details about how to set cuts. >>> wh.setGeneratorLevelCuts({'e1e1_o':["cut M of 3 within 10 99999","cut E of 3 within 5 99999"]}) :param dict cutsdict: Dictionary of cuts """ self._checkArgs({'cutsdict': types.DictType}) self.generatorLevelCuts = cutsdict def setFullParameterDict(self, pdict): """ Parameters for Whizard steering files, better than above as much more complete (cannot be more complete) >>> pdict = {} >>> pdict['process_input'] = {} >>> #processes below are not those of the templates, but those of the whizard.prc >>> pdict['process_input']['process_id']='h_n1n1' >>> pdict['process_input']['sqrts'] = 3000. >>> pdict['simulation_input'] = {} >>> pdict['simulation_input']['n_events'] = 100 >>> pdict['beam_input_1'] = {} >>> pdict['beam_input_1']['polarization']='1.0 0.0' >>> pdict['beam_input_1']['USER_spectrum_mode'] = 11 >>> pdict['beam_input_2'] = {} >>> pdict['beam_input_2']['polarization']='0.0 1.0' >>> pdict['beam_input_2']['USER_spectrum_mode'] = -11 >>> wh.setFullParameterDict(pdict) The first key corresponds to the sections of the whizard.in, while the second corresponds to the possible parameters. All keys/values can be found in the WHIZARD documentation: http://whizard.hepforge.org/manual_w1/manual005.html#toc11 :param dict pdict: Dictionnary of parameters """ self._checkArgs({'pdict': types.DictType}) self.fullParameterDict = pdict #self._wo.changeAndReturn(dict) def setModel(self, model): """ Optional: Define Model :param string model: Model to use for generation. Predefined list available in the :mod:`GeneratorModels<ILCDIRAC.Core.Utilities.GeneratorModels.GeneratorModels>` class. """ self._checkArgs({'model': types.StringTypes}) self.model = model def willCut(self): """ You need this if you plan on cutting using :mod:`StdhepCut <ILCDIRAC.Interfaces.API.NewInterface.Applications.StdhepCut.StdhepCut>` """ self.willBeCut = True def usingGridFiles(self): """ Call this if you want to use the grid files that come with the Whizard version used. Beware: Depends on the energy and generator cuts, use it if you know what you are doing. """ self.useGridFiles = True def setJobIndex(self, index): """ Optional: Define Job Index. Added in the file name between the event type and the extension. :param string index: Index to use for generation """ self._checkArgs({'index': types.StringTypes}) self.jobIndex = index def dumpWhizardDotIn(self, fname='whizard.in'): """ Dump the content of the whizard.in file requested for this application :param string fname: filename in which whizard.in is written """ if self.addedtojob: self._wo.toWhizardDotIn(fname) else: self._reportError( "Can't dump the whizard.in as there can be further changes") def _checkConsistency(self, job=None): """ Check the consistency, called from Application """ self._wo = WhizardOptions(self.model) if not self.fullParameterDict: if not self.energy: return S_ERROR('Energy not set') if not self.numberOfEvents: return S_ERROR('Number of events not set!') if not self.eventType: return S_ERROR("Process not defined") else: res = self._wo.checkFields(self.fullParameterDict) if not res['OK']: return res self._wo.changeAndReturn(self.fullParameterDict) res = self._wo.getValue("process_input/process_id") if not len(res['Value']): if self.eventType: if 'process_input' not in self.fullParameterDict: self.fullParameterDict['process_input'] = {} self.fullParameterDict['process_input'][ 'process_id'] = self.eventType else: return S_ERROR("Event type not specified") self.eventType = res['Value'] res = self._wo.getValue("process_input/sqrts") if isinstance(res['Value'], (int, long, float)): energy = res['Value'] else: energy = eval(res['Value']) if not energy: if self.energy: if 'process_input' not in self.fullParameterDict: self.fullParameterDict['process_input'] = {} self.fullParameterDict['process_input'][ 'sqrts'] = self.energy energy = self.energy else: return S_ERROR("Energy set to 0") self.energy = energy res = self._wo.getValue("simulation_input/n_events") if isinstance(res['Value'], (int, long, float)): numberOfEvents = res['Value'] else: numberOfEvents = eval(res['Value']) if not numberOfEvents: if self.numberOfEvents: if 'simulation_input' not in self.fullParameterDict: self.fullParameterDict['simulation_input'] = {} self.fullParameterDict['simulation_input'][ 'n_events'] = self.numberOfEvents numberOfEvents = self.numberOfEvents else: return S_ERROR("Number of events set to 0") self.numberOfEvents = numberOfEvents if not self._processlist: return S_ERROR("Process list was not given") if self.generatorLevelCuts: for process in self.generatorLevelCuts.keys(): if process not in self.eventType.split(): self._log.info( "You want to cut on %s but that process is not to be generated" % process) for values in self.generatorLevelCuts.values(): if not isinstance(values, list): return S_ERROR('Type of %s is not a list, cannot proceed' % values) self._genlevelcutsstr = str(self.generatorLevelCuts) if self.eventType: processes = self.eventType.split() if len(processes) > 1 and not self.globalEventType: return S_ERROR( "Global name MUST be defined when producing multiple processes in one job" ) elif self.globalEventType: self.eventType = self.globalEventType for process in processes: if not self._processlist.existsProcess(process)['Value']: self._log.notice("Available processes are:") self._processlist.printProcesses() return S_ERROR('Process %s does not exists' % process) else: cspath = self._processlist.getCSPath(process) whiz_file = os.path.basename(cspath) version = whiz_file.replace(".tar.gz", "").replace( ".tgz", "").replace("whizard", "") if self.version: if self.version != version: return S_ERROR( "All processes to consider are not available in the same WHIZARD version" ) else: self.version = version self._log.info("Found the process %s in whizard %s" % (process, self.version)) if not self.version: return S_ERROR('No version found') if self.model: if not self._generatormodels.hasModel(self.model)['OK']: return S_ERROR("Unknown model %s" % self.model) if self.outputFile: if self.outputFile.count("/"): return S_ERROR( "The OutputFile name is a file name, not a path. Remove any / in there" ) if not self.outputFile and self._jobtype == 'User': self.outputFile = self.eventType if self.jobIndex: self.outputFile += "_" + self.jobIndex self.outputFile += "_gen.stdhep" if self._jobtype != 'User': if not self.willBeCut: self._listofoutput.append({ "outputFile": "@{OutputFile}", "outputPath": "@{OutputPath}", "outputDataSE": '@{OutputSE}' }) self.prodparameters['nbevts'] = self.numberOfEvents self.prodparameters['Process'] = self.eventType self.prodparameters['model'] = self.model self.prodparameters['Energy'] = self.energy self.prodparameters['whizardparams'] = self.fullParameterDict self.prodparameters['gencuts'] = self.generatorLevelCuts self.prodparameters['gridfiles'] = self.useGridFiles if not self.fullParameterDict and self.parameterDict: for key in self.parameterDict.keys(): if key not in self._allowedparams: return S_ERROR("Unknown parameter %s" % key) self.setParameter('PNAME1', 'e1', "Assuming incoming beam 1 to be electrons") self.setParameter('PNAME2', 'E1', "Assuming incoming beam 2 to be positrons") self.setParameter('POLAB1', '0.0 0.0', "Assuming no polarization for beam 1") self.setParameter('POLAB2', '0.0 0.0', "Assuming no polarization for beam 2") self.setParameter('USERB1', 'T', "Will put beam spectrum to True for beam 1") self.setParameter('USERB2', 'T', "Will put beam spectrum to True for beam 2") self.setParameter('ISRB1', 'T', "Will put ISR to True for beam 1") self.setParameter('ISRB2', 'T', "Will put ISR to True for beam 2") self.setParameter('EPAB1', 'F', "Will put EPA to False for beam 1") self.setParameter('EPAB2', 'F', "Will put EPA to False for beam 2") self.setParameter('RECOIL', 'F', "Will set Beam_recoil to False") self.setParameter('INITIALS', 'F', "Will set keep_initials to False") self.setParameter('USERSPECTRUM', '11', "Will set USER_spectrum_on to +-11") self.parameters = ";".join(self.parameters) elif self.fullParameterDict: self._optionsdictstr = str(self.fullParameterDict) return S_OK() def _applicationModule(self): md1 = self._createModuleDefinition() md1.addParameter( Parameter("evttype", "", "string", "", "", False, False, "Process to generate")) md1.addParameter( Parameter("RandomSeed", 0, "int", "", "", False, False, "Random seed for the generator")) md1.addParameter( Parameter("Lumi", 0, "float", "", "", False, False, "Luminosity of beam")) md1.addParameter( Parameter("Model", "", "string", "", "", False, False, "Model for generation")) md1.addParameter( Parameter("SteeringFile", "", "string", "", "", False, False, "Steering file")) md1.addParameter( Parameter("steeringparameters", "", "string", "", "", False, False, "Specific steering parameters")) md1.addParameter( Parameter("OptionsDictStr", "", "string", "", "", False, False, "Options dict to create full whizard.in on the fly")) md1.addParameter( Parameter("GenLevelCutDictStr", "", "string", "", "", False, False, "Generator level cuts to put in whizard.cut1")) md1.addParameter( Parameter("willCut", False, "bool", "", "", False, False, "Will cut after")) md1.addParameter( Parameter("useGridFiles", True, "bool", "", "", False, False, "Will use grid files")) md1.addParameter( Parameter("debug", False, "bool", "", "", False, False, "debug mode")) return md1 def _applicationModuleValues(self, moduleinstance): moduleinstance.setValue("evttype", self.eventType) moduleinstance.setValue("RandomSeed", self.randomSeed) moduleinstance.setValue("Lumi", self.luminosity) moduleinstance.setValue("Model", self.model) moduleinstance.setValue("SteeringFile", self.steeringFile) moduleinstance.setValue("steeringparameters", self.parameters) moduleinstance.setValue("OptionsDictStr", self._optionsdictstr) moduleinstance.setValue("GenLevelCutDictStr", self._genlevelcutsstr) moduleinstance.setValue("willCut", self.willBeCut) moduleinstance.setValue("useGridFiles", self.useGridFiles) moduleinstance.setValue("debug", self.debug) def _userjobmodules(self, stepdefinition): res1 = self._setApplicationModuleAndParameters(stepdefinition) res2 = self._setUserJobFinalization(stepdefinition) if not res1["OK"] or not res2["OK"]: return S_ERROR('userjobmodules failed') return S_OK() def _prodjobmodules(self, stepdefinition): res1 = self._setApplicationModuleAndParameters(stepdefinition) res2 = self._setOutputComputeDataList(stepdefinition) if not res1["OK"] or not res2["OK"]: return S_ERROR('prodjobmodules failed') return S_OK() def setParameter(self, parameter, defaultValue, docString): if parameter not in self.parameterDict: self._log.info(docString) self.parameters.append("%s=%s" % (parameter, defaultValue)) else: self.parameters.append("%s=%s" % (parameter, self.parameterDict[parameter]))