示例#1
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()
示例#2
0
class ProcessListComplexTestCase(unittest.TestCase):
    """ Test the different methods of the class, providing a usable CFG
  """
    def setUp(self):
        with patch('%s.os.path.exists' % MODULE_NAME,
                   new=Mock(return_value=False)):
            self.prol = ProcessList('myTestProcess.list')
        self.prol.cfg.createNewSection('Processes')

    def test_updateproclist_and_getters(self):
        self.prol.cfg.createNewSection('Processes/myTestProcDeleteMe')
        self.prol.cfg.setOption(
            'Processes/myTestProcDeleteMe/someRandomOption', True)
        dict_1 = {'CrossSection': 'someCross'}
        dict_1.update(STD_PROC_DICT)
        dict_2 = {'CrossSection': 'some_other_val'}
        dict_2.update(STD_PROC_DICT)
        process_dict = {}
        process_dict['MytestProcess'] = dict_1
        process_dict['myTestProcDeleteMe'] = dict_2
        result = self.prol.updateProcessList(process_dict)
        assertDiracSucceeds(result, self)
        conf = self.prol.cfg
        self.assertFalse(
            conf.existsKey('Processes/myTestProcDeleteMe/someRandomOption'))
        options = [
            'Processes/MytestProcess/CrossSection',
            'Processes/myTestProcDeleteMe/CrossSection'
        ]
        assertEqualsImproved((map(conf.getOption, options)),
                             (['someCross', 'some_other_val']), self)
        assertEqualsImproved(
            (self.prol.getCSPath('myTestProcDeleteMe'),
             self.prol.getInFile('myTestProcDeleteMe'),
             self.prol.existsProcess('myTestProcDeleteMe'),
             self.prol.existsProcess(''),
             self.prol.existsProcess('invalidProcess'),
             self.prol.existsProcess('myTestProcDeleteMeToo')),
            ('/test/cs/path/ball.tar', 'my/file.in', S_OK(True), S_OK(True),
             S_OK(False), S_OK(False)), self)
        assertListContentEquals(self.prol.getProcesses(),
                                ['myTestProcDeleteMe', 'MytestProcess'], self)
        all_processes_dict = self.prol.getProcessesDict()
        assertEqualsImproved(len(all_processes_dict), 2, self)
        assertEqualsImproved(
            ('myTestProcDeleteMe' in all_processes_dict, 'MytestProcess'
             in all_processes_dict), (True, True), self)
        self.prol.printProcesses()

    def test_writeproclist(self):
        expected_write = 'Processes\n{\n  mytestprocess123\n  {\n    TarBallCSPath = /test/cs/path/bal.tarr\n    Detail = TestNoDetails\n    Generator = mytestGen21\n    Model = testmodel3001\n    Restrictions = \n    InFile = my/file.in\n    CrossSection = 0\n  }\n}\n'
        self.prol._addEntry(
            'mytestprocess123', {
                'TarBallCSPath': '/test/cs/path/bal.tarr',
                'Detail': 'TestNoDetails',
                'Generator': 'mytestGen21',
                'Model': 'testmodel3001',
                'Restrictions': '',
                'InFile': 'my/file.in'
            })
        exists_dict = {
            '/temp/dir': False,
            '/temp/dir/mytempfile.txt': True,
            '/my/folder/testpath.xml': True
        }
        fhandle_mock = Mock()
        with patch('tempfile.mkstemp', new=Mock(return_value=('handle', '/temp/dir/mytempfile.txt'))), \
             patch('__builtin__.file', new=Mock(return_value=fhandle_mock)) as file_mock, \
             patch('os.makedirs') as mkdir_mock, \
             patch('os.path.exists', new=Mock(side_effect=lambda path: exists_dict[path])), \
             patch('shutil.move') as move_mock, \
             patch('os.close') as close_mock:
            assertDiracSucceedsWith_equals(
                self.prol.writeProcessList('/my/folder/testpath.xml'),
                '/my/folder/testpath.xml', self)
            mkdir_mock.assert_called_once_with('/temp/dir')
            file_mock.assert_called_once_with('/temp/dir/mytempfile.txt', 'w')
            fhandle_mock.write.assert_called_once_with(expected_write)
            close_mock.assert_called_once_with('handle')
            move_mock.assert_called_once_with('/temp/dir/mytempfile.txt',
                                              '/my/folder/testpath.xml')

    def test_writeproclist_notwritten(self):
        exists_dict = {'myTmpNameTestme': True}
        cfg_mock = Mock()
        cfg_mock.writeToFile.return_value = False
        self.prol.cfg = cfg_mock
        self.prol.location = '/my/folder/testpath2.txt'
        with patch('os.close') as close_mock, \
             patch('os.path.exists', new=Mock(side_effect=lambda path: exists_dict[path])), \
             patch('os.remove') as remove_mock, \
             patch('tempfile.mkstemp', new=Mock(return_value=('myhandle', 'myTmpNameTestme'))):
            assertDiracFailsWith(self.prol.writeProcessList(),
                                 'failed to write repo', self)
            close_mock.assert_called_once_with('myhandle')
            remove_mock.assert_called_once_with('myTmpNameTestme')

    def test_writeproclist_notwritten_noremove(self):
        exists_dict = {'myTmpNameTestme': False}
        cfg_mock = Mock()
        cfg_mock.writeToFile.return_value = False
        self.prol.cfg = cfg_mock
        with patch('os.close') as close_mock, \
             patch('os.path.exists', new=Mock(side_effect=lambda path: exists_dict[path])), \
             patch('os.remove') as remove_mock, \
             patch('tempfile.mkstemp', new=Mock(return_value=('myhandle', 'myTmpNameTestme'))):
            assertDiracFailsWith(
                self.prol.writeProcessList('/my/folder/testpath2.txt'),
                'failed to write repo', self)
            close_mock.assert_called_once_with('myhandle')
            self.assertFalse(remove_mock.called)

    def test_writeproclist_move_fails(self):
        exists_dict = {'/my/folder/testpath2.txt': False}
        cfg_mock = Mock()
        cfg_mock.writeToFile.return_value = True
        self.prol.cfg = cfg_mock
        with patch('os.close') as close_mock, \
             patch('os.path.exists', new=Mock(side_effect=lambda path: exists_dict[path])), \
             patch('os.remove') as remove_mock, \
             patch('tempfile.mkstemp', new=Mock(return_value=('myhandle', 'myTmpNameTestme'))), \
             patch('shutil.move', new=Mock(side_effect=OSError('mytestErr_os'))):
            assertDiracFailsWith(
                self.prol.writeProcessList('/my/folder/testpath2.txt'),
                'failed to write repo', self)
            close_mock.assert_called_once_with('myhandle')
            self.assertFalse(remove_mock.called)

    def test_uploadproclist(self):
        import sys
        import DIRAC
        datman_mock = Mock()
        datman_mock.removeFile.return_value = S_OK('something')
        datmodule_mock = Mock()
        datmodule_mock.DataManager.return_value = datman_mock
        fileutil_mock = Mock()
        fileutil_mock.upload.return_value = S_OK('something')
        conf_mock = Mock()
        conf_mock.getOption.return_value = S_OK('/local/path/proc.list')
        mocked_modules = {
            'DIRAC.DataManagementSystem.Client.DataManager': datmodule_mock,
            'ILCDIRAC.Core.Utilities.FileUtils': fileutil_mock
        }
        module_patcher = patch.dict(sys.modules, mocked_modules)
        module_patcher.start()
        backup_conf = DIRAC.gConfig
        DIRAC.gConfig = conf_mock
        with patch('shutil.copy') as copy_mock, \
             patch('subprocess.call') as proc_mock:
            self.prol.uploadProcessListToFileCatalog(
                '/my/secret/path/processlist.whiz', 'v120')
            assertMockCalls(
                copy_mock,
                [('myTestProcess.list',
                  '/afs/cern.ch/eng/clic/software/whizard/whizard_195/'),
                 ('myTestProcess.list', '/local/path/proc.list')], self)
            proc_mock.assert_called_once_with([
                'svn', 'ci',
                '/afs/cern.ch/eng/clic/software/whizard/whizard_195/proc.list',
                "-m'Process list for whizard version v120'"
            ],
                                              shell=False)
        DIRAC.gConfig = backup_conf
        module_patcher.stop()

    def test_uploadproclist_remove_fails(self):
        import sys
        import DIRAC
        datman_mock = Mock()
        datman_mock.removeFile.return_value = S_ERROR('my_test_err')
        datmodule_mock = Mock()
        datmodule_mock.DataManager.return_value = datman_mock
        fileutil_mock = Mock()
        conf_mock = Mock()
        conf_mock.getOption.return_value = S_OK('somepath')
        mocked_modules = {
            'DIRAC.DataManagementSystem.Client.DataManager': datmodule_mock,
            'ILCDIRAC.Core.Utilities.FileUtils': fileutil_mock
        }
        module_patcher = patch.dict(sys.modules, mocked_modules)
        module_patcher.start()
        backup_conf = DIRAC.gConfig
        DIRAC.gConfig = conf_mock
        DIRAC.exit = abort_test
        with self.assertRaises(KeyboardInterrupt) as ki:
            self.prol.uploadProcessListToFileCatalog('asd', 'v1')
        key_interrupt = ki.exception
        assertEqualsImproved(key_interrupt.args, ('abort_my_test', ), self)
        DIRAC.gConfig = backup_conf
        module_patcher.stop()

    def test_uploadproclist_upload_fails(self):
        import sys
        import DIRAC
        datman_mock = Mock()
        datman_mock.removeFile.return_value = S_OK('something')
        datmodule_mock = Mock()
        datmodule_mock.DataManager.return_value = datman_mock
        fileutil_mock = Mock()
        fileutil_mock.upload.return_value = S_ERROR('something')
        conf_mock = Mock()
        conf_mock.getOption.return_value = S_OK('somepath')
        mocked_modules = {
            'DIRAC.DataManagementSystem.Client.DataManager': datmodule_mock,
            'ILCDIRAC.Core.Utilities.FileUtils': fileutil_mock
        }
        module_patcher = patch.dict(sys.modules, mocked_modules)
        module_patcher.start()
        backup_conf = DIRAC.gConfig
        DIRAC.gConfig = conf_mock
        DIRAC.exit = abort_test
        with self.assertRaises(KeyboardInterrupt) as ki:
            self.prol.uploadProcessListToFileCatalog('asd', 'v1')
        key_interrupt = ki.exception
        assertEqualsImproved(key_interrupt.args, ('abort_my_test', ), self)
        DIRAC.gConfig = backup_conf
        module_patcher.stop()

    def test_uploadproclist_copy_and_commit_fail(self):
        import sys
        import DIRAC
        datman_mock = Mock()
        datman_mock.removeFile.return_value = S_OK('something')
        datmodule_mock = Mock()
        datmodule_mock.DataManager.return_value = datman_mock
        fileutil_mock = Mock()
        fileutil_mock.upload.return_value = S_OK('something')
        conf_mock = Mock()
        conf_mock.getOption.return_value = S_OK('somepath')
        mocked_modules = {
            'DIRAC.DataManagementSystem.Client.DataManager': datmodule_mock,
            'ILCDIRAC.Core.Utilities.FileUtils': fileutil_mock
        }
        module_patcher = patch.dict(sys.modules, mocked_modules)
        module_patcher.start()
        backup_conf = DIRAC.gConfig
        DIRAC.gConfig = conf_mock
        DIRAC.exit = abort_test
        with patch('shutil.copy', new=Mock(side_effect=OSError('oserr_testme_keeprunning'))), \
             patch('subprocess.call', new=Mock(side_effect=OSError('subproc_test_err'))):
            self.prol.uploadProcessListToFileCatalog(
                '/my/secret/path/processlist.whiz', 'v120')
        DIRAC.gConfig = backup_conf
        module_patcher.stop()

    def test_uploadproclist_skip_copy(self):
        import sys
        import DIRAC
        datman_mock = Mock()
        datman_mock.removeFile.return_value = S_OK('something')
        datmodule_mock = Mock()
        datmodule_mock.DataManager.return_value = datman_mock
        fileutil_mock = Mock()
        fileutil_mock.upload.return_value = S_OK('something')
        conf_mock = Mock()
        conf_mock.getOption.return_value = S_OK('')
        mocked_modules = {
            'DIRAC.DataManagementSystem.Client.DataManager': datmodule_mock,
            'ILCDIRAC.Core.Utilities.FileUtils': fileutil_mock
        }
        module_patcher = patch.dict(sys.modules, mocked_modules)
        module_patcher.start()
        backup_conf = DIRAC.gConfig
        DIRAC.gConfig = conf_mock
        DIRAC.exit = abort_test
        with patch('shutil.copy', new=Mock(side_effect=IOError('dont_call_me'))), \
             patch('subprocess.call', new=Mock(side_effect=IOError('dont_call_me_either'))):
            self.prol.uploadProcessListToFileCatalog(
                '/my/secret/path/processlist.whiz', 'v120')
        DIRAC.gConfig = backup_conf
        module_patcher.stop()
示例#3
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()
示例#4
0
class ProcessListComplexTestCase( unittest.TestCase ):
  """ Test the different methods of the class, providing a usable CFG
  """

  def setUp( self ):
    with patch('%s.os.path.exists' % MODULE_NAME, new=Mock(return_value=False)):
      self.prol = ProcessList( 'myTestProcess.list' )
    self.prol.cfg.createNewSection( 'Processes' )

  def test_updateproclist_and_getters( self ):
    self.prol.cfg.createNewSection( 'Processes/myTestProcDeleteMe' )
    self.prol.cfg.setOption( 'Processes/myTestProcDeleteMe/someRandomOption', True )
    dict_1 = { 'CrossSection' : 'someCross' }
    dict_1.update( STD_PROC_DICT )
    dict_2 = { 'CrossSection' : 'some_other_val' }
    dict_2.update( STD_PROC_DICT )
    process_dict = {}
    process_dict[ 'MytestProcess' ] = dict_1
    process_dict[ 'myTestProcDeleteMe' ] = dict_2
    result = self.prol.updateProcessList( process_dict )
    assertDiracSucceeds( result, self )
    conf = self.prol.cfg
    self.assertFalse( conf.existsKey( 'Processes/myTestProcDeleteMe/someRandomOption' ) )
    options = [ 'Processes/MytestProcess/CrossSection', 'Processes/myTestProcDeleteMe/CrossSection' ]
    assertEqualsImproved( ( map( conf.getOption, options ) ), ( [ 'someCross', 'some_other_val' ] ), self )
    assertEqualsImproved( ( self.prol.getCSPath( 'myTestProcDeleteMe' ),
                            self.prol.getInFile( 'myTestProcDeleteMe' ),
                            self.prol.existsProcess( 'myTestProcDeleteMe' ),
                            self.prol.existsProcess( '' ), self.prol.existsProcess( 'invalidProcess' ),
                            self.prol.existsProcess( 'myTestProcDeleteMeToo' ) ),
                          ( '/test/cs/path/ball.tar', 'my/file.in', S_OK(True), S_OK(True), S_OK(False),
                            S_OK(False) ), self )
    assertListContentEquals( self.prol.getProcesses(), [ 'myTestProcDeleteMe', 'MytestProcess' ], self )
    all_processes_dict = self.prol.getProcessesDict()
    assertEqualsImproved( len(all_processes_dict), 2, self )
    assertEqualsImproved( ('myTestProcDeleteMe' in all_processes_dict, 'MytestProcess' in all_processes_dict),
                          ( True, True ), self )
    self.prol.printProcesses()

  def test_writeproclist( self ):
    expected_write = 'Processes\n{\n  mytestprocess123\n  {\n    TarBallCSPath = /test/cs/path/bal.tarr\n    Detail = TestNoDetails\n    Generator = mytestGen21\n    Model = testmodel3001\n    Restrictions = \n    InFile = my/file.in\n    CrossSection = 0\n  }\n}\n'
    self.prol._addEntry( 'mytestprocess123', { 'TarBallCSPath' : '/test/cs/path/bal.tarr', 'Detail' :
                                               'TestNoDetails', 'Generator' : 'mytestGen21', 'Model' :
                                               'testmodel3001', 'Restrictions' : '', 'InFile' : 'my/file.in'
                                             } )
    exists_dict = { '/temp/dir' : False, '/temp/dir/mytempfile.txt' : True, '/my/folder/testpath.xml' : True }
    fhandle_mock = Mock()

    file_mock = Mock(return_value=fhandle_mock)
    with patch('tempfile.mkstemp', new=Mock(return_value=('handle', '/temp/dir/mytempfile.txt'))), \
         patch('__builtin__.file', new=file_mock), \
         patch('__builtin__.open', new=file_mock), \
         patch('os.makedirs') as mkdir_mock, \
         patch('os.path.exists', new=Mock(side_effect=lambda path: exists_dict[path])), \
         patch('shutil.move') as move_mock, \
         patch('os.close') as close_mock:
      assertDiracSucceedsWith_equals( self.prol.writeProcessList( '/my/folder/testpath.xml' ),
                                      '/my/folder/testpath.xml', self )
      mkdir_mock.assert_called_once_with( '/temp/dir' )
      file_mock.assert_called_once_with( '/temp/dir/mytempfile.txt', 'w' )
      fhandle_mock.write.assert_called_once_with( expected_write )
      close_mock.assert_called_once_with( 'handle' )
      move_mock.assert_called_once_with( '/temp/dir/mytempfile.txt', '/my/folder/testpath.xml' )

  def test_writeproclist_notwritten( self ):
    exists_dict = { 'myTmpNameTestme' : True }
    cfg_mock = Mock()
    cfg_mock.writeToFile.return_value = False
    self.prol.cfg = cfg_mock
    self.prol.location = '/my/folder/testpath2.txt'
    with patch('os.close') as close_mock, \
         patch('os.path.exists', new=Mock(side_effect=lambda path: exists_dict[path])), \
         patch('os.remove') as remove_mock, \
         patch('tempfile.mkstemp', new=Mock(return_value=('myhandle', 'myTmpNameTestme'))):
      assertDiracFailsWith( self.prol.writeProcessList(), 'failed to write repo', self )
      close_mock.assert_called_once_with( 'myhandle' )
      remove_mock.assert_called_once_with( 'myTmpNameTestme')

  def test_writeproclist_notwritten_noremove( self ):
    exists_dict = { 'myTmpNameTestme' : False }
    cfg_mock = Mock()
    cfg_mock.writeToFile.return_value = False
    self.prol.cfg = cfg_mock
    with patch('os.close') as close_mock, \
         patch('os.path.exists', new=Mock(side_effect=lambda path: exists_dict[path])), \
         patch('os.remove') as remove_mock, \
         patch('tempfile.mkstemp', new=Mock(return_value=('myhandle', 'myTmpNameTestme'))):
      assertDiracFailsWith( self.prol.writeProcessList( '/my/folder/testpath2.txt' ),
                            'failed to write repo', self )
      close_mock.assert_called_once_with( 'myhandle' )
      self.assertFalse( remove_mock.called )

  def test_writeproclist_move_fails( self ):
    exists_dict = { '/my/folder/testpath2.txt' : False }
    cfg_mock = Mock()
    cfg_mock.writeToFile.return_value = True
    self.prol.cfg = cfg_mock
    with patch('os.close') as close_mock, \
         patch('os.path.exists', new=Mock(side_effect=lambda path: exists_dict[path])), \
         patch('os.remove') as remove_mock, \
         patch('tempfile.mkstemp', new=Mock(return_value=('myhandle', 'myTmpNameTestme'))), \
         patch('shutil.move', new=Mock(side_effect=OSError('mytestErr_os'))):
      assertDiracFailsWith( self.prol.writeProcessList( '/my/folder/testpath2.txt' ),
                            'failed to write repo', self )
      close_mock.assert_called_once_with( 'myhandle' )
      self.assertFalse( remove_mock.called )

  def test_uploadproclist( self ):
    import sys
    import DIRAC
    datman_mock = Mock()
    datman_mock.removeFile.return_value = S_OK('something')
    datmodule_mock = Mock()
    datmodule_mock.DataManager.return_value = datman_mock
    fileutil_mock = Mock()
    fileutil_mock.upload.return_value = S_OK('something')
    conf_mock = Mock()
    conf_mock.getOption.return_value = S_OK( '/local/path/proc.list' )
    mocked_modules = { 'DIRAC.DataManagementSystem.Client.DataManager' : datmodule_mock,
                       'ILCDIRAC.Core.Utilities.FileUtils' : fileutil_mock }
    module_patcher = patch.dict( sys.modules, mocked_modules )
    module_patcher.start()
    backup_conf = DIRAC.gConfig
    DIRAC.gConfig = conf_mock
    with patch('shutil.copy') as copy_mock, \
         patch('subprocess.call') as proc_mock:
      self.prol.uploadProcessListToFileCatalog( '/my/secret/path/processlist.whiz', 'v120' )
      assertMockCalls( copy_mock, [
        ( 'myTestProcess.list', '/afs/cern.ch/eng/clic/software/whizard/whizard_195/' ),
        ( 'myTestProcess.list', '/local/path/proc.list' ) ], self )
      proc_mock.assert_called_once_with(
        [ 'svn', 'ci', '/afs/cern.ch/eng/clic/software/whizard/whizard_195/proc.list',
          "-m'Process list for whizard version v120'" ], shell=False )
    DIRAC.gConfig = backup_conf
    module_patcher.stop()

  def test_uploadproclist_remove_fails( self ):
    import sys
    import DIRAC
    datman_mock = Mock()
    datman_mock.removeFile.return_value = S_ERROR('my_test_err')
    datmodule_mock = Mock()
    datmodule_mock.DataManager.return_value = datman_mock
    fileutil_mock = Mock()
    conf_mock = Mock()
    conf_mock.getOption.return_value = S_OK( 'somepath' )
    mocked_modules = { 'DIRAC.DataManagementSystem.Client.DataManager' : datmodule_mock,
                       'ILCDIRAC.Core.Utilities.FileUtils' : fileutil_mock }
    module_patcher = patch.dict( sys.modules, mocked_modules )
    module_patcher.start()
    backup_conf = DIRAC.gConfig
    DIRAC.gConfig = conf_mock
    DIRAC.exit = abort_test
    with self.assertRaises( KeyboardInterrupt ) as ki:
      self.prol.uploadProcessListToFileCatalog( 'asd', 'v1' )
    key_interrupt = ki.exception
    assertEqualsImproved( key_interrupt.args, ( 'abort_my_test', ), self )
    DIRAC.gConfig = backup_conf
    module_patcher.stop()

  def test_uploadproclist_upload_fails( self ):
    import sys
    import DIRAC
    datman_mock = Mock()
    datman_mock.removeFile.return_value = S_OK('something')
    datmodule_mock = Mock()
    datmodule_mock.DataManager.return_value = datman_mock
    fileutil_mock = Mock()
    fileutil_mock.upload.return_value = S_ERROR('something')
    conf_mock = Mock()
    conf_mock.getOption.return_value = S_OK( 'somepath' )
    mocked_modules = { 'DIRAC.DataManagementSystem.Client.DataManager' : datmodule_mock,
                       'ILCDIRAC.Core.Utilities.FileUtils' : fileutil_mock }
    module_patcher = patch.dict( sys.modules, mocked_modules )
    module_patcher.start()
    backup_conf = DIRAC.gConfig
    DIRAC.gConfig = conf_mock
    DIRAC.exit = abort_test
    with self.assertRaises( KeyboardInterrupt ) as ki:
      self.prol.uploadProcessListToFileCatalog( 'asd', 'v1' )
    key_interrupt = ki.exception
    assertEqualsImproved( key_interrupt.args, ( 'abort_my_test', ), self )
    DIRAC.gConfig = backup_conf
    module_patcher.stop()

  def test_uploadproclist_copy_and_commit_fail( self ):
    import sys
    import DIRAC
    datman_mock = Mock()
    datman_mock.removeFile.return_value = S_OK('something')
    datmodule_mock = Mock()
    datmodule_mock.DataManager.return_value = datman_mock
    fileutil_mock = Mock()
    fileutil_mock.upload.return_value = S_OK('something')
    conf_mock = Mock()
    conf_mock.getOption.return_value = S_OK( 'somepath' )
    mocked_modules = { 'DIRAC.DataManagementSystem.Client.DataManager' : datmodule_mock,
                       'ILCDIRAC.Core.Utilities.FileUtils' : fileutil_mock }
    module_patcher = patch.dict( sys.modules, mocked_modules )
    module_patcher.start()
    backup_conf = DIRAC.gConfig
    DIRAC.gConfig = conf_mock
    DIRAC.exit = abort_test
    with patch('shutil.copy', new=Mock(side_effect=OSError('oserr_testme_keeprunning'))), \
         patch('subprocess.call', new=Mock(side_effect=OSError('subproc_test_err'))):
      self.prol.uploadProcessListToFileCatalog( '/my/secret/path/processlist.whiz', 'v120' )
    DIRAC.gConfig = backup_conf
    module_patcher.stop()

  def test_uploadproclist_skip_copy( self ):
    import sys
    import DIRAC
    datman_mock = Mock()
    datman_mock.removeFile.return_value = S_OK('something')
    datmodule_mock = Mock()
    datmodule_mock.DataManager.return_value = datman_mock
    fileutil_mock = Mock()
    fileutil_mock.upload.return_value = S_OK('something')
    conf_mock = Mock()
    conf_mock.getOption.return_value = S_OK('')
    mocked_modules = { 'DIRAC.DataManagementSystem.Client.DataManager' : datmodule_mock,
                       'ILCDIRAC.Core.Utilities.FileUtils' : fileutil_mock }
    module_patcher = patch.dict( sys.modules, mocked_modules )
    module_patcher.start()
    backup_conf = DIRAC.gConfig
    DIRAC.gConfig = conf_mock
    DIRAC.exit = abort_test
    with patch('shutil.copy', new=Mock(side_effect=IOError('dont_call_me'))), \
         patch('subprocess.call', new=Mock(side_effect=IOError('dont_call_me_either'))):
      self.prol.uploadProcessListToFileCatalog( '/my/secret/path/processlist.whiz', 'v120' )
    DIRAC.gConfig = backup_conf
    module_patcher.stop()