Exemplo n.º 1
0
 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
Exemplo n.º 2
0
 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
Exemplo n.º 3
0
  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' ] )
Exemplo n.º 4
0
    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'
        ])
Exemplo n.º 5
0
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()
Exemplo n.º 6
0
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]) )
Exemplo n.º 7
0
  def __init__(self, model = "sm"):
    """
    :param string model: physics model to be used by whizard, default "sm"
    """

    self.genmodel = GeneratorModels()
    self.paramdict = {}
    modelparams = self.modelParams(model)
    self.whizardxml = fromstring("""<whizard>
<process_input>
<process_id type="string" value="">
<!-- Process tag(s) as defined in whizard.prc. It should contain the list of processes to activate, separated by commas or blanks, enclosed in quotes. -->
</process_id>
<cm_frame type="T/F" value="T">
<!-- if true, the c.m. frame is the lab frame, the beams are in +/- z directions, and the total c.m. energy is given by sqrts. If false, the beam energies and directions must be specified below in the blocks beam_input. -->
</cm_frame>
<sqrts type="float" value="3000">
<!-- If this number is greater than the sum of the incoming particle masses, it specifies the c.m. energy of the initial state in GeV. Applies only if cm_frame is true, and is ignored for decay processes. -->
</sqrts>
<luminosity type="float" value="0">
<!-- Integrated luminosity in fb-1 -->
</luminosity>
<polarized_beams type="T/F" value="T">
<!-- If true, the helicity content of the beams must be specified below in the blocks beam_input. -->
</polarized_beams>
<structured_beams type="T/F" value="T">
<!-- If true, the nature of the incoming beams must be specified below in the blocks beam_input. -->
</structured_beams>
<beam_recoil type="T/F" value="F">
<!-- If true, and if structure functions (e.g., ISR) are selected, the recoil of the partons against the beam remnant (e.g., the emitted photons) is taken into account. The pT distribution is computed within the approximation valid for the emission, hence it will be accurate at low pT. -->
</beam_recoil>
<recoil_conserve_momentum type="T/F" value="F">
<!-- Applies only if beam_recoil is set: if true, keep momentum balance between parton and recoil momenta at the expense of energy balance. If false, keep energy balance at the expense of momentum balance. -->
</recoil_conserve_momentum>
<filename type="string" value="whizard">
<!-- Base filename (w/o extension) to be used for all input/output files instead of the string "whizard". -->
</filename>
<directory type="string" value="">
<!-- Working directory for all further reading/writing of files. -->
</directory>
<input_file type="string" value="">
<!-- If nonempty, read the specified input file after the current one. The extension .in will be appended to the filename. -->
</input_file>
<input_slha_format type="T/F" value="F">
<!-- If true, assume that the next input file is in SUSY Les Houches Accord format (see Sec. 4.4.7). If false, determine the format from the first line. -->
</input_slha_format>
</process_input>
<integration_input>
<calls type="floatarray" value="1 50000 10 50000 1 1500000">
<!-- Array describing the number of iterations and number of calls per integration pass. Default values depend on the selected process. See below in subsection 4.6 for details. -->
</calls>
<seed type="integer" value="">
<!-- Random number generator seed (integer). When omitted, the time counter will be used, resulting in a different value each run. -->
</seed>
<reset_seed_each_process type="T/F" value="F">
<!-- Reset the random number generator seed to seed not just once, but each time a process is integrated. This is useful for comparing matrix elements which should be identical, but, e.g., have been generated by different programs. -->
</reset_seed_each_process>
<accuracy_goal type="float" value="0">
<!-- Goal for the accuracy estimate (6th column in the output). When this goal is reached and the efficiency goal is either also reached or unset, further grid adaptation iterations will be skipped (Sec. 4.9). -->
</accuracy_goal>
<efficiency_goal type="float" value="100">
<!-- Goal for the reweighting efficiency estimate (7th column in the output). When this goal is reached and the accuracy goal is either also reached or unset, further grid adaptation iterations will be skipped (Sec. 4.9). -->
</efficiency_goal>
<time_limit_adaptation type="integer" value="0">
<!-- If nonzero, grid adaptation for the current process will be stopped after the specified number of minutes, and the final integration pass started (Sec. 4.9). -->
</time_limit_adaptation>
<stratified type="T/F" value="T">
<!-- Use stratified (T) / importance (F) sampling. -->
</stratified>
<use_efficiency type="T/F" value="F">
<!-- Use efficiency (T) / accuracy (F) as the criterion for adapting the channel weights. -->
</use_efficiency>
<weights_power type="float" value="0.25">
<!-- Power used for adapting the channel weights. Lower value means slower adaptation (to suppress fluctuations). -->
</weights_power>
<min_bins type="integer" value="3">
<!-- Minimal number of bins per integration dimension. -->
</min_bins>
<max_bins type="integer" value="20">
<!-- Maximal number of bins per integration dimension. This number will be used as long as there are enough sampling points, otherwise the number of bins will be decreased. -->
</max_bins>
<min_calls_per_bin type="integer" value="10">
<!-- Minimal number of points per bin, integration dimension, and integration channel. If this limit cannot be satisfied, the total number of points will be increased. -->
</min_calls_per_bin>
<min_calls_per_channel type="integer" value="0">
<!-- All integration channel will get at least (approximately) this number of points. Prevents channels from being dropped during adaptation. -->
</min_calls_per_channel>
<write_grids type="T/F" value="T">
<!-- Write grids to files whizard.grb (best grid) and whizard.grc (current grid), to be reused later. -->
</write_grids>
<write_grids_raw type="T/F" value="F">
<!-- Use binary format for writing grids. Saves memory at the expense of portability. -->
</write_grids_raw>
<write_grids_file type="string" value="">
<!-- If nonempty, use the specified filename for writing grids instead of the default. The file extensions are appended to string. -->
</write_grids_file>
<write_all_grids type="T/F" value="F">
<!-- Write, in addition, after each iteration the current grid to file whizard.grXX, where XX is the iteration number. -->
</write_all_grids>
<write_all_grids_file type="string" value="">
<!-- If nonempty, use the specified filename for writing the extra grids instead of the default. The file extensions are appended to string. -->
</write_all_grids_file>
<read_grids type="T/F" value="F">
<!-- Read existing grids whizard.grb and whizard.grc if they have been written by a previous run. This avoids the time-consuming adaptation step. Makes sense only if no physical parameters have been changed. -->
</read_grids>
<read_grids_raw type="T/F" value="F">
<!-- If true, search first for binary grid files, then for ASCII grids. If false, do search first for ASCII.. -->
</read_grids_raw>
<read_grids_force type="T/F" value="T">
<!-- Set this to T if you want to read the grids from file even if some parameters have changed. Use with care! This may result in a program crash if the grid structures are incompatible. -->
</read_grids_force>
<read_grids_file type="string" value="">
<!-- If nonempty, use the specified filename for reading grids instead of the default. The file extensions are appended to string. -->
</read_grids_file>
<generate_phase_space type="T/F" value="T">
<!-- Generate a phase space configuration appropriate for the current process and write it to whizard.phx. -->
</generate_phase_space>
<read_model_file type="string" value="">
<!-- If nonempty, read vertex definitions for phase space setup from string.mdl instead of the default whizard.mdl. -->
</read_model_file>
<write_phase_space_file type="string" value="">
<!-- Write phase space configuration to string.phx instead of the default. -->
</write_phase_space_file>
<read_phase_space type="T/F" value="T">
<!-- Read phase space configuration from whizard.phs or a previously generated file whizard.phx if possible. -->
</read_phase_space>
<read_phase_space_file type="string" value="">
<!-- Read phase space configuration from string.phs or string.phx instead of the default. -->
</read_phase_space_file>
<phase_space_only type="T/F" value="F">
<!-- Stop the program after phase space generation. -->
</phase_space_only>
<use_equivalences type="T/F" value="T">
<!-- If true, use permutation symmetry when updating grids to improve the quality of the results. -->
</use_equivalences>
<azimuthal_dependence type="T/F" value="F">
<!-- If false, it is assumed that the scattering does not depend on the overall azimuthal angle. This will be automatically T if general beam polarization is switched on, therefore the user need only access this parameter in the case of azimuthal-dependent cuts. -->
</azimuthal_dependence>
<write_phase_space_channels_file type="string" value="">
<!-- Show phase space channels in string.ps instead of the default file whizard-channels.ps. Note that you need to call CHANNELS= string make -e channels in order to generate string.ps -->
</write_phase_space_channels_file>
<off_shell_lines type="integer" value="1">
<!-- Maximum number of off-shell-lines allowed for Feynman graphs which are initially taken into account for the phase space configuration. Log-enhanced (massless) propagators are not counted as off-shell. -->
</off_shell_lines>
<extra_off_shell_lines type="integer" value="1">
<!-- Use configurations with more off-shell lines, if they happen to be maximally resonant. -->
</extra_off_shell_lines>
<splitting_depth type="integer" value="1">
<!-- Up to this number of branchings, a (massless) propagator will be considered as log-enhanced and mapped like a photon propagator. -->
</splitting_depth>
<exchange_lines type="integer" value="3">
<!-- Up to this number of t-channel propagators, a multiperipheral graph will be taken into account. -->
</exchange_lines>
<show_deleted_channels type="T/F" value="F">
<!-- With extra_off_shell_lines, extra channels will be generated which are deleted if they do not contain enough resonances. With this flag, they are just commented out, so they could be manually activated. -->
</show_deleted_channels>
<single_off_shell_decays type="T/F" value="T">
<!-- Whether single-off-shell decays are relevant for the phase space configuration. -->
</single_off_shell_decays>
<double_off_shell_decays type="T/F" value="F">
<!-- Whether double-off-shell decays are relevant for the phase space configuration. -->
</double_off_shell_decays>
<single_off_shell_branchings type="T/F" value="T">
<!-- Whether single-off-shell branchings are relevant for the phase space configuration. -->
</single_off_shell_branchings>
<double_off_shell_branchings type="T/F" value="T">
<!-- Whether double-off-shell branchings are relevant for the phase space configuration. -->
</double_off_shell_branchings>
<massive_fsr type="T/F" value="T">
<!-- Whether the radiation of a massive particle in the final state is relevant for the phase space configuration. -->
</massive_fsr>
<threshold_mass type="float" value="-10">
<!-- A particle with a mass up to this value will be considered as massless for the purpose of phase-space setup. (But the true mass is taken into account when the particle appears as a resonant intermediate state.) -->
</threshold_mass>
<threshold_mass_t type="float" value="-10">
<!-- A particle with a mass up to this value will be considered as massless for the purpose of phase-space setup, when it appears as a t-channel propagator. -->
</threshold_mass_t>
<!-- <initial_decays_fatal type="T/F" value="T"> -->
<!-- As the phase space maps cannot describe on-shell decays of beam particles properly, WHIZARD normally gives a fatal error when such configurations are encountered. This option changes this to a warning at the price of a potentially screwed phase space setup. -->
<!-- </initial_decays_fatal> -->
<default_jet_cut type="float" value="10">
<!-- The default invariant mass cut in GeV applied to pairs of massless colored particles. -->
</default_jet_cut>
<default_mass_cut type="float" value="4">
<!-- The default invariant mass cut in GeV applied to pair production of massless colorless charged particles and to photon emission. -->
</default_mass_cut>
<default_energy_cut type="float" value="10">
<!-- The default energy cut in GeV applied to photon and gluon emission. -->
</default_energy_cut>
<default_q_cut type="float" value="4">
<!-- The default Q cut in GeV applied to photon and gluon exchange. -->
</default_q_cut>
<write_default_cuts_file type="string" value="">
<!-- If nonempty, write the list of default cuts to this file (augmented by the file extension) instead of the default. Note that the settings in this file are overwritten by a user-defined cut configuration, if present. -->
</write_default_cuts_file>
<read_cuts_file type="string" value="">
<!-- Look for user-defined cut configurations in string.cut1 instead of whizard.cut1. -->
</read_cuts_file>
<user_cut_mode type="integer" value="0">
<!-- Set this nonzero to activate a user-defined cut function (Sec. 5.4). -->
</user_cut_mode>
<user_weight_mode type="integer" value="0">
<!-- Set this nonzero to activate a user-defined weight function (Sec. 5.5). -->
</user_weight_mode>
</integration_input>
<simulation_input>
<n_events type="integer" value="0">
<!-- Number of (unweighted) events to generate at least, irrespective of the luminosity setting. -->
</n_events>
<n_calls type="integer" value="0">
<!-- Number of matrix-element calls (weighted events) to execute at least, irrespective of the luminosity setting. -->
</n_calls>
<n_events_warmup type="integer" value="0">
<!-- Number of extra warmup events (see below, Sec. 4.7). -->
</n_events_warmup>
<unweighted type="T/F" value="T">
<!-- Reweight events to generate an unweighted event sample. -->
</unweighted>
<normalize_weight type="T/F" value="T">
<!-- If true, normalize the event weight to unity. If false, normalize to the total cross section. -->
</normalize_weight>
<write_weights type="T/F" value="F">
<!-- If unweighted=F, write weight distribution data to whizard.wgt. -->
</write_weights>
<write_weights_file type="string" value="">
<!-- Write weight distribution to string.wgt instead. -->
</write_weights_file>
<safety_factor type="float" value="1">
<!-- Multiply the estimate for the highest weight by this factor before starting event generation. -->
</safety_factor>
<write_events type="T/F" value="T">
<!-- Write generated events to file whizard.evt to be used by an external analysis package. -->
</write_events>
<write_events_format type="integer" value="20">
<!-- The format to be used for writing events, where the file extension depends on the format (.evt for format = 1, see Sec. 4.7). -->
</write_events_format>
<write_events_file type="string" value="">
<!-- If nonempty, use string as filename for writing events, where the file extension will be appended. -->
</write_events_file>
<events_per_file type="integer" value="5000000">
<!-- If positive, begin a new event file once the number of entries exceeds this number. The event file counter is appended to each event file name, separated with a dot (before the file extension). This feature applies only to non-binary event formats. -->
</events_per_file>
<bytes_per_file type="integer" value="0">
<!-- If positive, begin a new event file once the number of bytes in the file exceeds this number. The event file counter is appended to each event file name, separated with a dot (before the file extension). This feature applies only to non-binary event formats. See Sec. 4.7.1. -->
</bytes_per_file>
<min_file_count type="integer" value="1">
<!-- If event files are split, use this index for the first event file. Increase the counter by one for each successive event file. -->
</min_file_count>
<max_file_count type="integer" value="999">
<!-- Limit for the event file counter; if this limit is exceeded, event generation is terminated. (For weighted events only, this is an error condition since the event sample must be complete for being usable.) -->
</max_file_count>
<write_events_raw type="T/F" value="F">
<!-- Write events to whizard.evx in condensed binary format, so they can be internally reused in another run. -->
</write_events_raw>
<write_events_raw_file type="string" value="">
<!-- Write raw events to string.evx instead. -->
</write_events_raw_file>
<read_events type="T/F" value="F">
<!-- Read events from file whizard.evx (raw format) instead of generating them. This is equivalent to read_events_raw. -->
</read_events>
<read_events_force type="T/F" value="T">
<!-- This was intended to force WHIZARD to read in events from file even if some parameters have changed. However, the MD5 checksum implemented to check for parameter changes has some deficiencies. Hence, we always enforce to read in events, because this feature could otherwise not be used at all. Use with great care! (Note that this problem has been solved in WHIZARD 2.) -->
</read_events_force>
<read_events_raw_file type="string" value="">
<!-- Read raw events from string.evx instead. -->
</read_events_raw_file>
<keep_beam_remnants type="T/F" value="T">
<!-- Keep the beam remnants in the event record when applying structure functions. See Sec. 4.4.8. -->
</keep_beam_remnants>
<keep_initials type="T/F" value="T">
<!-- Keep the beam particles and the partons which initiate the hard scattering in the event record. See Sec. 4.4.8. -->
</keep_initials>
<guess_color_flow type="T/F" value="F">
<!-- Infer the color flow for hadronization from the particle ordering, if it is nontrivial and not available directly. -->
</guess_color_flow>
<recalculate type="T/F" value="F">
<!-- Recalculate the matrix element value for each event of a previously generated sample. Setting this flag automatically turns on reading grids and events from file. -->
</recalculate>
<fragment type="T/F" value="T">
<!-- Fragment the events depending on the value of fragmentation_method (see Sec. 4.8). -->
</fragment>
<fragmentation_method type="integer" value="3">
<!-- Method used for fragmentation if fragment is true: 0=no fragmentation; 1=JETSET; 2=PYTHIA; 3=user. -->
</fragmentation_method>
<user_fragmentation_mode type="integer" value="0">
<!-- When user-defined fragmentation routines are called, this parameter may select different modes. -->
</user_fragmentation_mode>
<pythia_parameters type="string" value="PMAS(25,1)=120.; PMAS(25,2)=0.3605E-02; MSTU(22)=20 ;MSTJ(28)=2 ;PARJ(21)=0.40000;PARJ(41)=0.11000; PARJ(42)=0.52000; PARJ(81)=0.25000; PARJ(82)=1.90000; MSTJ(11)=3; PARJ(54)=-0.03100; PARJ(55)=-0.00200;PARJ(1)=0.08500; PARJ(3)=0.45000; PARJ(4)=0.02500; PARJ(2)=0.31000; PARJ(11)=0.60000; PARJ(12)=0.40000; PARJ(13)=0.72000;PARJ(14)=0.43000; PARJ(15)=0.08000; PARJ(16)=0.08000; PARJ(17)=0.17000; MSTP(3)=1;">
<!-- String to be given to PYTHIA's pygive call before starting event generation. This allows to modify PYTHIA/JETSET properties, set particle masses, etc. The string is also available within user-defined fragmentation routines and can there be abused for different purposes. -->
</pythia_parameters>
<pythia_processes type="string" value="">
<!-- PYTHIA background processes to be simulated in addition to the WHIZARD processes: A list of integers separated by blanks, enclosed in quotation marks. Refer to the PYTHIA manual for the list of processes. -->
</pythia_processes>
<shower type="T/F" value="F">
<!-- Switches the internal shower on or off. As a default it is off. Note that the shower only works with LHEF event format (foramt type 6). This shower is highly experimental. Mainly intended for testing purposes. -->
</shower>
<shower_nf type="integer" value="5">
<!-- Number of light flavors in the shower. -->
</shower_nf>
<shower_running_alpha_s type="T/F" value="F">
<!-- Whether to use a running strong coupling alpha_s or not in the shower. As a default it is fixed. -->
</shower_running_alpha_s>
<shower_alpha_s type="float" value="0.2">
<!-- The value of the strong coupling constant alpha_s as used by the internal shower. The default is 0.2. -->
</shower_alpha_s>
<shower_lambda type="float" value="0.29">
<!-- The value of the QCD scale Lambda_QCD as used by the internal shower. The default is 0.29 GeV. -->
</shower_lambda>
<shower_t_min type="float" value="1.0">
<!-- The infrared cutoff for the evolution parameter tmin as used by the internal shower. The default is 1 GeV. -->
</shower_t_min>
<shower_md type="float" value="0.330">
<!-- The constituent d quark mass md as used by the internal shower. The default is 0.330 GeV. -->
</shower_md>
<shower_mu type="float" value="0.330">
<!-- The constituent u quark mass mu as used by the internal shower. The default is 0.330 GeV. -->
</shower_mu>
<shower_ms type="float" value="0.500">
<!-- The constituent s quark mass ms as used by the internal shower. The default is 0.5 GeV. -->
</shower_ms>
<shower_mc type="float" value="1.5">
<!-- The constituent c quark mass mc as used by the internal shower. The default is 1.5 GeV. -->
</shower_mc>
<shower_mb type="float" value="4.8">
<!-- The constituent b quark mass mb as used by the internal shower. The default is 4.8 GeV.diagnostics_input -->
</shower_mb>
</simulation_input>
<diagnostics_input>
<chattiness type="integer" value="4">
<!-- How much information to show on screen: (0) only fatal errors, (1) and non-fatal errors, (2) and warnings, (3) and messages, (4) and results, (5) and debugging messages (if any). -->
</chattiness>
<catch_signals type="T/F" value="T">
<!-- If the compiler supports it, try to catch external signals such as SIGINT and SIGXCPU and exit gracefully, closing files first. -->
</catch_signals>
<time_limit type="integer" value="0"> -->
<!-- If nonzero, exit gracefully after the given number of minutes has passed. This is useful to prevent an external kill within a batch environment. -->
</time_limit>
<warn_empty_channel type="T/F" value="F">
<!-- Issue a warning whenever the integral within a phase space channel is zero. -->
</warn_empty_channel>
<screen_events type="T/F" value="F">
<!-- Whether to show generated events on screen. -->
</screen_events>
<screen_histograms type="T/F" value="F">
<!-- Whether to show histograms on screen. -->
</screen_histograms>
<screen_diagnostics type="T/F" value="F">
<!-- Whether to repeat the input parameters on screen. -->
</screen_diagnostics>
<show_pythia_banner type="T/F" value="T">
<!-- Whether to display the PYTHIA banner page if fragmentation is enabled. -->
</show_pythia_banner>
<show_pythia_initialization type="T/F" value="T">
<!-- Whether to display the PYTHIA initialization messages if fragmentation is enabled. -->
</show_pythia_initialization>
<show_pythia_statistics type="T/F" value="T">
<!-- Whether to display the PYTHIA statistics summary after event generation is completed. -->
</show_pythia_statistics>
<write_logfile type="T/F" value="T">
<!-- Whether to write the (process-specific) output file(s) whizard.XX.out. -->
</write_logfile>
<write_logfile_file type="string" value="">
<!-- Use this as the filename for the logfile. -->
</write_logfile_file>
<show_input type="T/F" value="T">
<!-- Whether to repeat the input parameters in the logfile. -->
</show_input>
<show_results type="T/F" value="T">
<!-- Whether to show the integration results in namelist format in the logfile. -->
</show_results>
<show_phase_space type="T/F" value="F">
<!-- Whether to show the phase space configuration in the logfile. -->
</show_phase_space>
<show_cuts type="T/F" value="T">
<!-- Whether to show the cut configuration in the logfile. -->
</show_cuts>
<show_histories type="T/F" value="F">
<!-- Whether to show the individual VAMP channel histories in the logfile. -->
</show_histories>
<show_history type="T/F" value="T">
<!-- Whether to show the overall VAMP history in the logfile. -->
</show_history>
<show_weights type="T/F" value="T">
<!-- Whether to show the weight adaptation in the logfile. -->
</show_weights>
<show_event type="T/F" value="F">
<!-- Whether to show the last event in the logfile. -->
</show_event>
<show_histograms type="T/F" value="F">
<!-- Whether to show histograms in the logfile. -->
</show_histograms>
<show_overflow type="T/F" value="F">
<!-- Whether to show events beyond the first or last bin in histogram listings. -->
</show_overflow>
<show_excess type="T/F" value="T">
<!-- Whether to show a summary of events with weight exceeding one. -->
</show_excess>
<read_analysis_file type="string" value="">
<!-- Use this (string.cut5) as the filename for the analysis setup instead of whizard.cut5 -->
</read_analysis_file>
<plot_width type="float" value="130">
<!-- The width in mm of the plots if online analysis is enabled. -->
</plot_width>
<plot_height type="float" value="90">
<!-- The height in mm of the plots if online analysis is enabled. -->
</plot_height>
<plot_excess type="T/F" value="T">
<!-- In the plots, display excess events in red. -->
</plot_excess>
<plot_history type="T/F" value="T">
<!-- If this is enabled, write a graphics driver file for displaying the integration history, i.e., the integral with error bars for each iteration. Use make history to generate the graphics file whizard-history.ps. -->
</plot_history>
<plot_grids_channels type="string" value="">
<!-- The string is a list of phase-space channels (integers) for which the bin distribution will be histogrammed. Use make grids to generate the graphics file whizard-grids.ps. -->
</plot_grids_channels>
<plot_grids_logscale type="float" value="10">
<!-- Use logarithmic scale for the grid plots if the bin width varies over more than this ratio. -->
</plot_grids_logscale>
<slha_rewrite_input type="T/F" value="T">
<!-- If SUSY Les Houches Accord data have been used, whether to repeat this input in the process-specific logfiles (including comments) or to rewrite it there using the data which have actually been used. -->
</slha_rewrite_input>
<slha_ignore_errors type="T/F" value="F">
<!-- If this is false, an error signaled in the SLHA input file (in the SPINFO or DCINFO block) will cause WHIZARD to stop before calculating anything. If true, such errors will be displayed, but the run continues. -->
</slha_ignore_errors>
</diagnostics_input>
%s
<beam_input_1>
<energy type="float" value="0">
<!-- If greater than the beam particle mass, this specifies the beam energy in the lab frame. Otherwise, the beam energy is set equal to the particle mass (fixed target). -->
</energy>
<angle type="float" value="0">
<!-- If direction is not set, this specifies a rotation of the beam axis in the lab frame around the positive y axis. (By default, the beam directions are along the positive/negative z axis, so a rotation by the angle pi/2 turns them into the positive/negative x axis.) If direction is set, this parameter is ignored. -->
</angle>
<direction type="floatarray" value="0 0 0">
<!-- If any component is nonzero, this vector explicitly specifies the direction of the given beam in the lab frame. -->
</direction>
<vector_polarization type="T/F" value="F">
<!-- If false (default), use the standard helicity basis (left-/right-handed). Set this flag if you need another basis, in particular transversal polarization. -->
</vector_polarization>
<polarization type="floatarray" value="0.0 0.0">
<!-- Fraction of left/right polarization (fermions, photons, gluons), resp. left/longitudinal/right polarization (massive vector bosons). If the vector polarization model is selected, the three numbers denote the polarization vector. -->
</polarization>
<particle_code type="integer" value="0">
<!-- PDG code of the incoming beam particle. -->
</particle_code>
<particle_name type="string" value="e1">
<!-- Name of the incoming beam particle. -->
</particle_name>
<USER_spectrum_on type="T/F" value="T">
<!-- Apply or not the user spectrum -->
</USER_spectrum_on>
<USER_spectrum_mode type="integer" value="11">
<!-- User spectrum -->
</USER_spectrum_mode>
<ISR_on type="T/F" value="T">
<!-- Whether to apply ISR (electron or positron beam). -->
</ISR_on>
<ISR_alpha type="float" value="0.0072993">
<!-- The value of alpha_QED to be used for the spectrum. -->
</ISR_alpha>
<ISR_m_in type="float" value="0.000511">
<!-- The mass of the incoming particle. -->
</ISR_m_in>
<ISR_Q_max type="float" value="sqrts">
<!-- The hard scale which cuts off photon radiation. -->
</ISR_Q_max>
<ISR_LLA_order type="0/1/2/3" value="3">
<!-- The order of the leading-logarithmic approximation. -->
</ISR_LLA_order>
<ISR_map type="T/F" value="T">
<!-- Whether to use a mapping of the singularity at x=1 when evaluating the structure function (recommended; note that switching this off might even lead to an uncaught arithmetic exception). -->
</ISR_map>
<EPA_on type="T/F" value="F">
<!-- Whether to use the EPA spectrum (photon beam). -->
</EPA_on>
<EPA_map type="T/F" value="T">
<!-- Whether to apply a mapping to improve convergence. -->
</EPA_map>
<EPA_alpha type="float" value="0.0072993">
<!-- The value of alpha_QED to be used for the spectrum. -->
</EPA_alpha>
<EPA_m_in type="float" value="0.000511">
<!-- The mass of the incoming beam particle. -->
</EPA_m_in>
<EPA_mX type="float" value="4">
<!-- The lower cutoff for the produced invariant mass. -->
</EPA_mX>
<EPA_Q_max type="float" value="4">
<!-- The upper cutoff on the virtuality of the photon (Qmax&gt;0). -->
</EPA_Q_max>
<EPA_x0 type="float" value="0">
<!-- The lower cutoff on the energy fraction of the incoming photon -->
</EPA_x0>
<EPA_x1 type="float" value="0">
<!-- The upper cutoff on the energy fraction of the incoming photon -->
</EPA_x1>
</beam_input_1>
<beam_input_2>
<energy type="float" value="0">
<!-- If greater than the beam particle mass, this specifies the beam energy in the lab frame. Otherwise, the beam energy is set equal to the particle mass (fixed target). -->
</energy>
<angle type="float" value="0">
<!-- If direction is not set, this specifies a rotation of the beam axis in the lab frame around the positive y axis. (By default, the beam directions are along the positive/negative z axis, so a rotation by the angle pi/2 turns them into the positive/negative x axis.) If direction is set, this parameter is ignored. -->
</angle>
<direction type="floatarray" value="0 0 0">
<!-- If any component is nonzero, this vector explicitly specifies the direction of the given beam in the lab frame. -->
</direction>
<vector_polarization type="T/F" value="F">
<!-- If false (default), use the standard helicity basis (left-/right-handed). Set this flag if you need another basis, in particular transversal polarization. -->
</vector_polarization>
<polarization type="floatarray" value="0.0 0.0">
<!-- Fraction of left/right polarization (fermions, photons, gluons), resp. left/longitudinal/right polarization (massive vector bosons). If the vector polarization model is selected, the three numbers denote the polarization vector. -->
</polarization>
<particle_code type="integer" value="0">
<!-- PDG code of the incoming beam particle. -->
</particle_code>
<particle_name type="string" value="E1">
<!-- Name of the incoming beam particle. -->
</particle_name>
<USER_spectrum_on type="T/F" value="T">
<!-- Apply or not the user spectrum -->
</USER_spectrum_on>
<USER_spectrum_mode type="integer" value="-11">
<!-- User spectrum -->
</USER_spectrum_mode>
<ISR_on type="T/F" value="T">
<!-- Whether to apply ISR (electron or positron beam). -->
</ISR_on>
<ISR_alpha type="float" value="0.0072993">
<!-- The value of alpha_QED to be used for the spectrum. -->
</ISR_alpha>
<ISR_m_in type="float" value="0.000511">
<!-- The mass of the incoming particle. -->
</ISR_m_in>
<ISR_Q_max type="float" value="sqrts">
<!-- The hard scale which cuts off photon radiation. -->
</ISR_Q_max>
<ISR_LLA_order type="0/1/2/3" value="3">
<!-- The order of the leading-logarithmic approximation. -->
</ISR_LLA_order>
<ISR_map type="T/F" value="T">
<!-- Whether to use a mapping of the singularity at x=1 when evaluating the structure function (recommended; note that switching this off might even lead to an uncaught arithmetic exception). -->
</ISR_map>
<EPA_on type="T/F" value="F">
<!-- Whether to use the EPA spectrum (photon beam). -->
</EPA_on>
<EPA_map type="T/F" value="T">
<!-- Whether to apply a mapping to improve convergence. -->
</EPA_map>
<EPA_alpha type="float" value="0.0072993">
<!-- The value of alpha_QED to be used for the spectrum. -->
</EPA_alpha>
<EPA_m_in type="float" value="0.000511">
<!-- The mass of the incoming beam particle. -->
</EPA_m_in>
<EPA_mX type="float" value="4">
<!-- The lower cutoff for the produced invariant mass. -->
</EPA_mX>
<EPA_Q_max type="float" value="4">
<!-- The upper cutoff on the virtuality of the photon (Qmax&gt;0). -->
</EPA_Q_max>
<EPA_x0 type="float" value="0">
<!-- The lower cutoff on the energy fraction of the incoming photon -->
</EPA_x0>
<EPA_x1 type="float" value="0">
<!-- The upper cutoff on the energy fraction of the incoming photon -->
</EPA_x1>
</beam_input_2>
</whizard>
"""%modelparams)
    self.getInputFiles(model)
Exemplo n.º 8
0
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()
Exemplo n.º 9
0
    def __init__(self, model="sm"):
        """
    :param string model: physics model to be used by whizard, default "sm"
    """

        self.genmodel = GeneratorModels()
        self.paramdict = {}
        modelparams = self.modelParams(model)
        self.whizardxml = fromstring("""<whizard>
<process_input>
<process_id type="string" value="">
<!-- Process tag(s) as defined in whizard.prc. It should contain the list of processes to activate, separated by commas or blanks, enclosed in quotes. -->
</process_id>
<cm_frame type="T/F" value="T">
<!-- if true, the c.m. frame is the lab frame, the beams are in +/- z directions, and the total c.m. energy is given by sqrts. If false, the beam energies and directions must be specified below in the blocks beam_input. -->
</cm_frame>
<sqrts type="float" value="3000">
<!-- If this number is greater than the sum of the incoming particle masses, it specifies the c.m. energy of the initial state in GeV. Applies only if cm_frame is true, and is ignored for decay processes. -->
</sqrts>
<luminosity type="float" value="0">
<!-- Integrated luminosity in fb-1 -->
</luminosity>
<polarized_beams type="T/F" value="T">
<!-- If true, the helicity content of the beams must be specified below in the blocks beam_input. -->
</polarized_beams>
<structured_beams type="T/F" value="T">
<!-- If true, the nature of the incoming beams must be specified below in the blocks beam_input. -->
</structured_beams>
<beam_recoil type="T/F" value="F">
<!-- If true, and if structure functions (e.g., ISR) are selected, the recoil of the partons against the beam remnant (e.g., the emitted photons) is taken into account. The pT distribution is computed within the approximation valid for the emission, hence it will be accurate at low pT. -->
</beam_recoil>
<recoil_conserve_momentum type="T/F" value="F">
<!-- Applies only if beam_recoil is set: if true, keep momentum balance between parton and recoil momenta at the expense of energy balance. If false, keep energy balance at the expense of momentum balance. -->
</recoil_conserve_momentum>
<filename type="string" value="whizard">
<!-- Base filename (w/o extension) to be used for all input/output files instead of the string "whizard". -->
</filename>
<directory type="string" value="">
<!-- Working directory for all further reading/writing of files. -->
</directory>
<input_file type="string" value="">
<!-- If nonempty, read the specified input file after the current one. The extension .in will be appended to the filename. -->
</input_file>
<input_slha_format type="T/F" value="F">
<!-- If true, assume that the next input file is in SUSY Les Houches Accord format (see Sec. 4.4.7). If false, determine the format from the first line. -->
</input_slha_format>
</process_input>
<integration_input>
<calls type="floatarray" value="1 50000 10 50000 1 1500000">
<!-- Array describing the number of iterations and number of calls per integration pass. Default values depend on the selected process. See below in subsection 4.6 for details. -->
</calls>
<seed type="integer" value="">
<!-- Random number generator seed (integer). When omitted, the time counter will be used, resulting in a different value each run. -->
</seed>
<reset_seed_each_process type="T/F" value="F">
<!-- Reset the random number generator seed to seed not just once, but each time a process is integrated. This is useful for comparing matrix elements which should be identical, but, e.g., have been generated by different programs. -->
</reset_seed_each_process>
<accuracy_goal type="float" value="0">
<!-- Goal for the accuracy estimate (6th column in the output). When this goal is reached and the efficiency goal is either also reached or unset, further grid adaptation iterations will be skipped (Sec. 4.9). -->
</accuracy_goal>
<efficiency_goal type="float" value="100">
<!-- Goal for the reweighting efficiency estimate (7th column in the output). When this goal is reached and the accuracy goal is either also reached or unset, further grid adaptation iterations will be skipped (Sec. 4.9). -->
</efficiency_goal>
<time_limit_adaptation type="integer" value="0">
<!-- If nonzero, grid adaptation for the current process will be stopped after the specified number of minutes, and the final integration pass started (Sec. 4.9). -->
</time_limit_adaptation>
<stratified type="T/F" value="T">
<!-- Use stratified (T) / importance (F) sampling. -->
</stratified>
<use_efficiency type="T/F" value="F">
<!-- Use efficiency (T) / accuracy (F) as the criterion for adapting the channel weights. -->
</use_efficiency>
<weights_power type="float" value="0.25">
<!-- Power used for adapting the channel weights. Lower value means slower adaptation (to suppress fluctuations). -->
</weights_power>
<min_bins type="integer" value="3">
<!-- Minimal number of bins per integration dimension. -->
</min_bins>
<max_bins type="integer" value="20">
<!-- Maximal number of bins per integration dimension. This number will be used as long as there are enough sampling points, otherwise the number of bins will be decreased. -->
</max_bins>
<min_calls_per_bin type="integer" value="10">
<!-- Minimal number of points per bin, integration dimension, and integration channel. If this limit cannot be satisfied, the total number of points will be increased. -->
</min_calls_per_bin>
<min_calls_per_channel type="integer" value="0">
<!-- All integration channel will get at least (approximately) this number of points. Prevents channels from being dropped during adaptation. -->
</min_calls_per_channel>
<write_grids type="T/F" value="T">
<!-- Write grids to files whizard.grb (best grid) and whizard.grc (current grid), to be reused later. -->
</write_grids>
<write_grids_raw type="T/F" value="F">
<!-- Use binary format for writing grids. Saves memory at the expense of portability. -->
</write_grids_raw>
<write_grids_file type="string" value="">
<!-- If nonempty, use the specified filename for writing grids instead of the default. The file extensions are appended to string. -->
</write_grids_file>
<write_all_grids type="T/F" value="F">
<!-- Write, in addition, after each iteration the current grid to file whizard.grXX, where XX is the iteration number. -->
</write_all_grids>
<write_all_grids_file type="string" value="">
<!-- If nonempty, use the specified filename for writing the extra grids instead of the default. The file extensions are appended to string. -->
</write_all_grids_file>
<read_grids type="T/F" value="F">
<!-- Read existing grids whizard.grb and whizard.grc if they have been written by a previous run. This avoids the time-consuming adaptation step. Makes sense only if no physical parameters have been changed. -->
</read_grids>
<read_grids_raw type="T/F" value="F">
<!-- If true, search first for binary grid files, then for ASCII grids. If false, do search first for ASCII.. -->
</read_grids_raw>
<read_grids_force type="T/F" value="T">
<!-- Set this to T if you want to read the grids from file even if some parameters have changed. Use with care! This may result in a program crash if the grid structures are incompatible. -->
</read_grids_force>
<read_grids_file type="string" value="">
<!-- If nonempty, use the specified filename for reading grids instead of the default. The file extensions are appended to string. -->
</read_grids_file>
<generate_phase_space type="T/F" value="T">
<!-- Generate a phase space configuration appropriate for the current process and write it to whizard.phx. -->
</generate_phase_space>
<read_model_file type="string" value="">
<!-- If nonempty, read vertex definitions for phase space setup from string.mdl instead of the default whizard.mdl. -->
</read_model_file>
<write_phase_space_file type="string" value="">
<!-- Write phase space configuration to string.phx instead of the default. -->
</write_phase_space_file>
<read_phase_space type="T/F" value="T">
<!-- Read phase space configuration from whizard.phs or a previously generated file whizard.phx if possible. -->
</read_phase_space>
<read_phase_space_file type="string" value="">
<!-- Read phase space configuration from string.phs or string.phx instead of the default. -->
</read_phase_space_file>
<phase_space_only type="T/F" value="F">
<!-- Stop the program after phase space generation. -->
</phase_space_only>
<use_equivalences type="T/F" value="T">
<!-- If true, use permutation symmetry when updating grids to improve the quality of the results. -->
</use_equivalences>
<azimuthal_dependence type="T/F" value="F">
<!-- If false, it is assumed that the scattering does not depend on the overall azimuthal angle. This will be automatically T if general beam polarization is switched on, therefore the user need only access this parameter in the case of azimuthal-dependent cuts. -->
</azimuthal_dependence>
<write_phase_space_channels_file type="string" value="">
<!-- Show phase space channels in string.ps instead of the default file whizard-channels.ps. Note that you need to call CHANNELS= string make -e channels in order to generate string.ps -->
</write_phase_space_channels_file>
<off_shell_lines type="integer" value="1">
<!-- Maximum number of off-shell-lines allowed for Feynman graphs which are initially taken into account for the phase space configuration. Log-enhanced (massless) propagators are not counted as off-shell. -->
</off_shell_lines>
<extra_off_shell_lines type="integer" value="1">
<!-- Use configurations with more off-shell lines, if they happen to be maximally resonant. -->
</extra_off_shell_lines>
<splitting_depth type="integer" value="1">
<!-- Up to this number of branchings, a (massless) propagator will be considered as log-enhanced and mapped like a photon propagator. -->
</splitting_depth>
<exchange_lines type="integer" value="3">
<!-- Up to this number of t-channel propagators, a multiperipheral graph will be taken into account. -->
</exchange_lines>
<show_deleted_channels type="T/F" value="F">
<!-- With extra_off_shell_lines, extra channels will be generated which are deleted if they do not contain enough resonances. With this flag, they are just commented out, so they could be manually activated. -->
</show_deleted_channels>
<single_off_shell_decays type="T/F" value="T">
<!-- Whether single-off-shell decays are relevant for the phase space configuration. -->
</single_off_shell_decays>
<double_off_shell_decays type="T/F" value="F">
<!-- Whether double-off-shell decays are relevant for the phase space configuration. -->
</double_off_shell_decays>
<single_off_shell_branchings type="T/F" value="T">
<!-- Whether single-off-shell branchings are relevant for the phase space configuration. -->
</single_off_shell_branchings>
<double_off_shell_branchings type="T/F" value="T">
<!-- Whether double-off-shell branchings are relevant for the phase space configuration. -->
</double_off_shell_branchings>
<massive_fsr type="T/F" value="T">
<!-- Whether the radiation of a massive particle in the final state is relevant for the phase space configuration. -->
</massive_fsr>
<threshold_mass type="float" value="-10">
<!-- A particle with a mass up to this value will be considered as massless for the purpose of phase-space setup. (But the true mass is taken into account when the particle appears as a resonant intermediate state.) -->
</threshold_mass>
<threshold_mass_t type="float" value="-10">
<!-- A particle with a mass up to this value will be considered as massless for the purpose of phase-space setup, when it appears as a t-channel propagator. -->
</threshold_mass_t>
<!-- <initial_decays_fatal type="T/F" value="T"> -->
<!-- As the phase space maps cannot describe on-shell decays of beam particles properly, WHIZARD normally gives a fatal error when such configurations are encountered. This option changes this to a warning at the price of a potentially screwed phase space setup. -->
<!-- </initial_decays_fatal> -->
<default_jet_cut type="float" value="10">
<!-- The default invariant mass cut in GeV applied to pairs of massless colored particles. -->
</default_jet_cut>
<default_mass_cut type="float" value="4">
<!-- The default invariant mass cut in GeV applied to pair production of massless colorless charged particles and to photon emission. -->
</default_mass_cut>
<default_energy_cut type="float" value="10">
<!-- The default energy cut in GeV applied to photon and gluon emission. -->
</default_energy_cut>
<default_q_cut type="float" value="4">
<!-- The default Q cut in GeV applied to photon and gluon exchange. -->
</default_q_cut>
<write_default_cuts_file type="string" value="">
<!-- If nonempty, write the list of default cuts to this file (augmented by the file extension) instead of the default. Note that the settings in this file are overwritten by a user-defined cut configuration, if present. -->
</write_default_cuts_file>
<read_cuts_file type="string" value="">
<!-- Look for user-defined cut configurations in string.cut1 instead of whizard.cut1. -->
</read_cuts_file>
<user_cut_mode type="integer" value="0">
<!-- Set this nonzero to activate a user-defined cut function (Sec. 5.4). -->
</user_cut_mode>
<user_weight_mode type="integer" value="0">
<!-- Set this nonzero to activate a user-defined weight function (Sec. 5.5). -->
</user_weight_mode>
</integration_input>
<simulation_input>
<n_events type="integer" value="0">
<!-- Number of (unweighted) events to generate at least, irrespective of the luminosity setting. -->
</n_events>
<n_calls type="integer" value="0">
<!-- Number of matrix-element calls (weighted events) to execute at least, irrespective of the luminosity setting. -->
</n_calls>
<n_events_warmup type="integer" value="0">
<!-- Number of extra warmup events (see below, Sec. 4.7). -->
</n_events_warmup>
<unweighted type="T/F" value="T">
<!-- Reweight events to generate an unweighted event sample. -->
</unweighted>
<normalize_weight type="T/F" value="T">
<!-- If true, normalize the event weight to unity. If false, normalize to the total cross section. -->
</normalize_weight>
<write_weights type="T/F" value="F">
<!-- If unweighted=F, write weight distribution data to whizard.wgt. -->
</write_weights>
<write_weights_file type="string" value="">
<!-- Write weight distribution to string.wgt instead. -->
</write_weights_file>
<safety_factor type="float" value="1">
<!-- Multiply the estimate for the highest weight by this factor before starting event generation. -->
</safety_factor>
<write_events type="T/F" value="T">
<!-- Write generated events to file whizard.evt to be used by an external analysis package. -->
</write_events>
<write_events_format type="integer" value="20">
<!-- The format to be used for writing events, where the file extension depends on the format (.evt for format = 1, see Sec. 4.7). -->
</write_events_format>
<write_events_file type="string" value="">
<!-- If nonempty, use string as filename for writing events, where the file extension will be appended. -->
</write_events_file>
<events_per_file type="integer" value="5000000">
<!-- If positive, begin a new event file once the number of entries exceeds this number. The event file counter is appended to each event file name, separated with a dot (before the file extension). This feature applies only to non-binary event formats. -->
</events_per_file>
<bytes_per_file type="integer" value="0">
<!-- If positive, begin a new event file once the number of bytes in the file exceeds this number. The event file counter is appended to each event file name, separated with a dot (before the file extension). This feature applies only to non-binary event formats. See Sec. 4.7.1. -->
</bytes_per_file>
<min_file_count type="integer" value="1">
<!-- If event files are split, use this index for the first event file. Increase the counter by one for each successive event file. -->
</min_file_count>
<max_file_count type="integer" value="999">
<!-- Limit for the event file counter; if this limit is exceeded, event generation is terminated. (For weighted events only, this is an error condition since the event sample must be complete for being usable.) -->
</max_file_count>
<write_events_raw type="T/F" value="F">
<!-- Write events to whizard.evx in condensed binary format, so they can be internally reused in another run. -->
</write_events_raw>
<write_events_raw_file type="string" value="">
<!-- Write raw events to string.evx instead. -->
</write_events_raw_file>
<read_events type="T/F" value="F">
<!-- Read events from file whizard.evx (raw format) instead of generating them. This is equivalent to read_events_raw. -->
</read_events>
<read_events_force type="T/F" value="T">
<!-- This was intended to force WHIZARD to read in events from file even if some parameters have changed. However, the MD5 checksum implemented to check for parameter changes has some deficiencies. Hence, we always enforce to read in events, because this feature could otherwise not be used at all. Use with great care! (Note that this problem has been solved in WHIZARD 2.) -->
</read_events_force>
<read_events_raw_file type="string" value="">
<!-- Read raw events from string.evx instead. -->
</read_events_raw_file>
<keep_beam_remnants type="T/F" value="T">
<!-- Keep the beam remnants in the event record when applying structure functions. See Sec. 4.4.8. -->
</keep_beam_remnants>
<keep_initials type="T/F" value="T">
<!-- Keep the beam particles and the partons which initiate the hard scattering in the event record. See Sec. 4.4.8. -->
</keep_initials>
<guess_color_flow type="T/F" value="F">
<!-- Infer the color flow for hadronization from the particle ordering, if it is nontrivial and not available directly. -->
</guess_color_flow>
<recalculate type="T/F" value="F">
<!-- Recalculate the matrix element value for each event of a previously generated sample. Setting this flag automatically turns on reading grids and events from file. -->
</recalculate>
<fragment type="T/F" value="T">
<!-- Fragment the events depending on the value of fragmentation_method (see Sec. 4.8). -->
</fragment>
<fragmentation_method type="integer" value="3">
<!-- Method used for fragmentation if fragment is true: 0=no fragmentation; 1=JETSET; 2=PYTHIA; 3=user. -->
</fragmentation_method>
<user_fragmentation_mode type="integer" value="0">
<!-- When user-defined fragmentation routines are called, this parameter may select different modes. -->
</user_fragmentation_mode>
<pythia_parameters type="string" value="PMAS(25,1)=120.; PMAS(25,2)=0.3605E-02; MSTU(22)=20 ;MSTJ(28)=2 ;PARJ(21)=0.40000;PARJ(41)=0.11000; PARJ(42)=0.52000; PARJ(81)=0.25000; PARJ(82)=1.90000; MSTJ(11)=3; PARJ(54)=-0.03100; PARJ(55)=-0.00200;PARJ(1)=0.08500; PARJ(3)=0.45000; PARJ(4)=0.02500; PARJ(2)=0.31000; PARJ(11)=0.60000; PARJ(12)=0.40000; PARJ(13)=0.72000;PARJ(14)=0.43000; PARJ(15)=0.08000; PARJ(16)=0.08000; PARJ(17)=0.17000; MSTP(3)=1;">
<!-- String to be given to PYTHIA's pygive call before starting event generation. This allows to modify PYTHIA/JETSET properties, set particle masses, etc. The string is also available within user-defined fragmentation routines and can there be abused for different purposes. -->
</pythia_parameters>
<pythia_processes type="string" value="">
<!-- PYTHIA background processes to be simulated in addition to the WHIZARD processes: A list of integers separated by blanks, enclosed in quotation marks. Refer to the PYTHIA manual for the list of processes. -->
</pythia_processes>
<shower type="T/F" value="F">
<!-- Switches the internal shower on or off. As a default it is off. Note that the shower only works with LHEF event format (foramt type 6). This shower is highly experimental. Mainly intended for testing purposes. -->
</shower>
<shower_nf type="integer" value="5">
<!-- Number of light flavors in the shower. -->
</shower_nf>
<shower_running_alpha_s type="T/F" value="F">
<!-- Whether to use a running strong coupling alpha_s or not in the shower. As a default it is fixed. -->
</shower_running_alpha_s>
<shower_alpha_s type="float" value="0.2">
<!-- The value of the strong coupling constant alpha_s as used by the internal shower. The default is 0.2. -->
</shower_alpha_s>
<shower_lambda type="float" value="0.29">
<!-- The value of the QCD scale Lambda_QCD as used by the internal shower. The default is 0.29 GeV. -->
</shower_lambda>
<shower_t_min type="float" value="1.0">
<!-- The infrared cutoff for the evolution parameter tmin as used by the internal shower. The default is 1 GeV. -->
</shower_t_min>
<shower_md type="float" value="0.330">
<!-- The constituent d quark mass md as used by the internal shower. The default is 0.330 GeV. -->
</shower_md>
<shower_mu type="float" value="0.330">
<!-- The constituent u quark mass mu as used by the internal shower. The default is 0.330 GeV. -->
</shower_mu>
<shower_ms type="float" value="0.500">
<!-- The constituent s quark mass ms as used by the internal shower. The default is 0.5 GeV. -->
</shower_ms>
<shower_mc type="float" value="1.5">
<!-- The constituent c quark mass mc as used by the internal shower. The default is 1.5 GeV. -->
</shower_mc>
<shower_mb type="float" value="4.8">
<!-- The constituent b quark mass mb as used by the internal shower. The default is 4.8 GeV.diagnostics_input -->
</shower_mb>
</simulation_input>
<diagnostics_input>
<chattiness type="integer" value="4">
<!-- How much information to show on screen: (0) only fatal errors, (1) and non-fatal errors, (2) and warnings, (3) and messages, (4) and results, (5) and debugging messages (if any). -->
</chattiness>
<catch_signals type="T/F" value="T">
<!-- If the compiler supports it, try to catch external signals such as SIGINT and SIGXCPU and exit gracefully, closing files first. -->
</catch_signals>
<time_limit type="integer" value="0"> -->
<!-- If nonzero, exit gracefully after the given number of minutes has passed. This is useful to prevent an external kill within a batch environment. -->
</time_limit>
<warn_empty_channel type="T/F" value="F">
<!-- Issue a warning whenever the integral within a phase space channel is zero. -->
</warn_empty_channel>
<screen_events type="T/F" value="F">
<!-- Whether to show generated events on screen. -->
</screen_events>
<screen_histograms type="T/F" value="F">
<!-- Whether to show histograms on screen. -->
</screen_histograms>
<screen_diagnostics type="T/F" value="F">
<!-- Whether to repeat the input parameters on screen. -->
</screen_diagnostics>
<show_pythia_banner type="T/F" value="T">
<!-- Whether to display the PYTHIA banner page if fragmentation is enabled. -->
</show_pythia_banner>
<show_pythia_initialization type="T/F" value="T">
<!-- Whether to display the PYTHIA initialization messages if fragmentation is enabled. -->
</show_pythia_initialization>
<show_pythia_statistics type="T/F" value="T">
<!-- Whether to display the PYTHIA statistics summary after event generation is completed. -->
</show_pythia_statistics>
<write_logfile type="T/F" value="T">
<!-- Whether to write the (process-specific) output file(s) whizard.XX.out. -->
</write_logfile>
<write_logfile_file type="string" value="">
<!-- Use this as the filename for the logfile. -->
</write_logfile_file>
<show_input type="T/F" value="T">
<!-- Whether to repeat the input parameters in the logfile. -->
</show_input>
<show_results type="T/F" value="T">
<!-- Whether to show the integration results in namelist format in the logfile. -->
</show_results>
<show_phase_space type="T/F" value="F">
<!-- Whether to show the phase space configuration in the logfile. -->
</show_phase_space>
<show_cuts type="T/F" value="T">
<!-- Whether to show the cut configuration in the logfile. -->
</show_cuts>
<show_histories type="T/F" value="F">
<!-- Whether to show the individual VAMP channel histories in the logfile. -->
</show_histories>
<show_history type="T/F" value="T">
<!-- Whether to show the overall VAMP history in the logfile. -->
</show_history>
<show_weights type="T/F" value="T">
<!-- Whether to show the weight adaptation in the logfile. -->
</show_weights>
<show_event type="T/F" value="F">
<!-- Whether to show the last event in the logfile. -->
</show_event>
<show_histograms type="T/F" value="F">
<!-- Whether to show histograms in the logfile. -->
</show_histograms>
<show_overflow type="T/F" value="F">
<!-- Whether to show events beyond the first or last bin in histogram listings. -->
</show_overflow>
<show_excess type="T/F" value="T">
<!-- Whether to show a summary of events with weight exceeding one. -->
</show_excess>
<read_analysis_file type="string" value="">
<!-- Use this (string.cut5) as the filename for the analysis setup instead of whizard.cut5 -->
</read_analysis_file>
<plot_width type="float" value="130">
<!-- The width in mm of the plots if online analysis is enabled. -->
</plot_width>
<plot_height type="float" value="90">
<!-- The height in mm of the plots if online analysis is enabled. -->
</plot_height>
<plot_excess type="T/F" value="T">
<!-- In the plots, display excess events in red. -->
</plot_excess>
<plot_history type="T/F" value="T">
<!-- If this is enabled, write a graphics driver file for displaying the integration history, i.e., the integral with error bars for each iteration. Use make history to generate the graphics file whizard-history.ps. -->
</plot_history>
<plot_grids_channels type="string" value="">
<!-- The string is a list of phase-space channels (integers) for which the bin distribution will be histogrammed. Use make grids to generate the graphics file whizard-grids.ps. -->
</plot_grids_channels>
<plot_grids_logscale type="float" value="10">
<!-- Use logarithmic scale for the grid plots if the bin width varies over more than this ratio. -->
</plot_grids_logscale>
<slha_rewrite_input type="T/F" value="T">
<!-- If SUSY Les Houches Accord data have been used, whether to repeat this input in the process-specific logfiles (including comments) or to rewrite it there using the data which have actually been used. -->
</slha_rewrite_input>
<slha_ignore_errors type="T/F" value="F">
<!-- If this is false, an error signaled in the SLHA input file (in the SPINFO or DCINFO block) will cause WHIZARD to stop before calculating anything. If true, such errors will be displayed, but the run continues. -->
</slha_ignore_errors>
</diagnostics_input>
%s
<beam_input_1>
<energy type="float" value="0">
<!-- If greater than the beam particle mass, this specifies the beam energy in the lab frame. Otherwise, the beam energy is set equal to the particle mass (fixed target). -->
</energy>
<angle type="float" value="0">
<!-- If direction is not set, this specifies a rotation of the beam axis in the lab frame around the positive y axis. (By default, the beam directions are along the positive/negative z axis, so a rotation by the angle pi/2 turns them into the positive/negative x axis.) If direction is set, this parameter is ignored. -->
</angle>
<direction type="floatarray" value="0 0 0">
<!-- If any component is nonzero, this vector explicitly specifies the direction of the given beam in the lab frame. -->
</direction>
<vector_polarization type="T/F" value="F">
<!-- If false (default), use the standard helicity basis (left-/right-handed). Set this flag if you need another basis, in particular transversal polarization. -->
</vector_polarization>
<polarization type="floatarray" value="0.0 0.0">
<!-- Fraction of left/right polarization (fermions, photons, gluons), resp. left/longitudinal/right polarization (massive vector bosons). If the vector polarization model is selected, the three numbers denote the polarization vector. -->
</polarization>
<particle_code type="integer" value="0">
<!-- PDG code of the incoming beam particle. -->
</particle_code>
<particle_name type="string" value="e1">
<!-- Name of the incoming beam particle. -->
</particle_name>
<USER_spectrum_on type="T/F" value="T">
<!-- Apply or not the user spectrum -->
</USER_spectrum_on>
<USER_spectrum_mode type="integer" value="11">
<!-- User spectrum -->
</USER_spectrum_mode>
<ISR_on type="T/F" value="T">
<!-- Whether to apply ISR (electron or positron beam). -->
</ISR_on>
<ISR_alpha type="float" value="0.0072993">
<!-- The value of alpha_QED to be used for the spectrum. -->
</ISR_alpha>
<ISR_m_in type="float" value="0.000511">
<!-- The mass of the incoming particle. -->
</ISR_m_in>
<ISR_Q_max type="float" value="sqrts">
<!-- The hard scale which cuts off photon radiation. -->
</ISR_Q_max>
<ISR_LLA_order type="0/1/2/3" value="3">
<!-- The order of the leading-logarithmic approximation. -->
</ISR_LLA_order>
<ISR_map type="T/F" value="T">
<!-- Whether to use a mapping of the singularity at x=1 when evaluating the structure function (recommended; note that switching this off might even lead to an uncaught arithmetic exception). -->
</ISR_map>
<EPA_on type="T/F" value="F">
<!-- Whether to use the EPA spectrum (photon beam). -->
</EPA_on>
<EPA_map type="T/F" value="T">
<!-- Whether to apply a mapping to improve convergence. -->
</EPA_map>
<EPA_alpha type="float" value="0.0072993">
<!-- The value of alpha_QED to be used for the spectrum. -->
</EPA_alpha>
<EPA_m_in type="float" value="0.000511">
<!-- The mass of the incoming beam particle. -->
</EPA_m_in>
<EPA_mX type="float" value="4">
<!-- The lower cutoff for the produced invariant mass. -->
</EPA_mX>
<EPA_Q_max type="float" value="4">
<!-- The upper cutoff on the virtuality of the photon (Qmax&gt;0). -->
</EPA_Q_max>
<EPA_x0 type="float" value="0">
<!-- The lower cutoff on the energy fraction of the incoming photon -->
</EPA_x0>
<EPA_x1 type="float" value="0">
<!-- The upper cutoff on the energy fraction of the incoming photon -->
</EPA_x1>
</beam_input_1>
<beam_input_2>
<energy type="float" value="0">
<!-- If greater than the beam particle mass, this specifies the beam energy in the lab frame. Otherwise, the beam energy is set equal to the particle mass (fixed target). -->
</energy>
<angle type="float" value="0">
<!-- If direction is not set, this specifies a rotation of the beam axis in the lab frame around the positive y axis. (By default, the beam directions are along the positive/negative z axis, so a rotation by the angle pi/2 turns them into the positive/negative x axis.) If direction is set, this parameter is ignored. -->
</angle>
<direction type="floatarray" value="0 0 0">
<!-- If any component is nonzero, this vector explicitly specifies the direction of the given beam in the lab frame. -->
</direction>
<vector_polarization type="T/F" value="F">
<!-- If false (default), use the standard helicity basis (left-/right-handed). Set this flag if you need another basis, in particular transversal polarization. -->
</vector_polarization>
<polarization type="floatarray" value="0.0 0.0">
<!-- Fraction of left/right polarization (fermions, photons, gluons), resp. left/longitudinal/right polarization (massive vector bosons). If the vector polarization model is selected, the three numbers denote the polarization vector. -->
</polarization>
<particle_code type="integer" value="0">
<!-- PDG code of the incoming beam particle. -->
</particle_code>
<particle_name type="string" value="E1">
<!-- Name of the incoming beam particle. -->
</particle_name>
<USER_spectrum_on type="T/F" value="T">
<!-- Apply or not the user spectrum -->
</USER_spectrum_on>
<USER_spectrum_mode type="integer" value="-11">
<!-- User spectrum -->
</USER_spectrum_mode>
<ISR_on type="T/F" value="T">
<!-- Whether to apply ISR (electron or positron beam). -->
</ISR_on>
<ISR_alpha type="float" value="0.0072993">
<!-- The value of alpha_QED to be used for the spectrum. -->
</ISR_alpha>
<ISR_m_in type="float" value="0.000511">
<!-- The mass of the incoming particle. -->
</ISR_m_in>
<ISR_Q_max type="float" value="sqrts">
<!-- The hard scale which cuts off photon radiation. -->
</ISR_Q_max>
<ISR_LLA_order type="0/1/2/3" value="3">
<!-- The order of the leading-logarithmic approximation. -->
</ISR_LLA_order>
<ISR_map type="T/F" value="T">
<!-- Whether to use a mapping of the singularity at x=1 when evaluating the structure function (recommended; note that switching this off might even lead to an uncaught arithmetic exception). -->
</ISR_map>
<EPA_on type="T/F" value="F">
<!-- Whether to use the EPA spectrum (photon beam). -->
</EPA_on>
<EPA_map type="T/F" value="T">
<!-- Whether to apply a mapping to improve convergence. -->
</EPA_map>
<EPA_alpha type="float" value="0.0072993">
<!-- The value of alpha_QED to be used for the spectrum. -->
</EPA_alpha>
<EPA_m_in type="float" value="0.000511">
<!-- The mass of the incoming beam particle. -->
</EPA_m_in>
<EPA_mX type="float" value="4">
<!-- The lower cutoff for the produced invariant mass. -->
</EPA_mX>
<EPA_Q_max type="float" value="4">
<!-- The upper cutoff on the virtuality of the photon (Qmax&gt;0). -->
</EPA_Q_max>
<EPA_x0 type="float" value="0">
<!-- The lower cutoff on the energy fraction of the incoming photon -->
</EPA_x0>
<EPA_x1 type="float" value="0">
<!-- The upper cutoff on the energy fraction of the incoming photon -->
</EPA_x1>
</beam_input_2>
</whizard>
""" % modelparams)
        self.getInputFiles(model)
Exemplo n.º 10
0
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]))