CMS 3D CMS Logo

ConfigBuilder.py
Go to the documentation of this file.
1 #! /usr/bin/env python
2 
3 from __future__ import print_function
4 __version__ = "$Revision: 1.19 $"
5 __source__ = "$Source: /local/reps/CMSSW/CMSSW/Configuration/Applications/python/ConfigBuilder.py,v $"
6 
7 import FWCore.ParameterSet.Config as cms
8 from FWCore.ParameterSet.Modules import _Module
9 import six
10 # The following import is provided for backward compatibility reasons.
11 # The function used to be defined in this file.
12 from FWCore.ParameterSet.MassReplace import massReplaceInputTag as MassReplaceInputTag
13 
14 import hashlib
15 import sys
16 import re
17 import collections
18 from subprocess import Popen,PIPE
19 import FWCore.ParameterSet.DictTypes as DictTypes
20 class Options:
21  pass
22 
23 # the canonical defaults
24 defaultOptions = Options()
25 defaultOptions.datamix = 'DataOnSim'
26 defaultOptions.isMC=False
27 defaultOptions.isData=True
28 defaultOptions.step=''
29 defaultOptions.pileup='NoPileUp'
30 defaultOptions.pileup_input = None
31 defaultOptions.pileup_dasoption = ''
32 defaultOptions.geometry = 'SimDB'
33 defaultOptions.geometryExtendedOptions = ['ExtendedGFlash','Extended','NoCastor']
34 defaultOptions.magField = ''
35 defaultOptions.conditions = None
36 defaultOptions.scenarioOptions=['pp','cosmics','nocoll','HeavyIons']
37 defaultOptions.harvesting= 'AtRunEnd'
38 defaultOptions.gflash = False
39 defaultOptions.number = -1
40 defaultOptions.number_out = None
41 defaultOptions.arguments = ""
42 defaultOptions.name = "NO NAME GIVEN"
43 defaultOptions.evt_type = ""
44 defaultOptions.filein = ""
45 defaultOptions.dasquery=""
46 defaultOptions.dasoption=""
47 defaultOptions.secondfilein = ""
48 defaultOptions.customisation_file = []
49 defaultOptions.customisation_file_unsch = []
50 defaultOptions.customise_commands = ""
51 defaultOptions.inline_custom=False
52 defaultOptions.particleTable = 'pythiapdt'
53 defaultOptions.particleTableList = ['pythiapdt','pdt']
54 defaultOptions.dirin = ''
55 defaultOptions.dirout = ''
56 defaultOptions.filetype = 'EDM'
57 defaultOptions.fileout = 'output.root'
58 defaultOptions.filtername = ''
59 defaultOptions.lazy_download = False
60 defaultOptions.custom_conditions = ''
61 defaultOptions.hltProcess = ''
62 defaultOptions.eventcontent = None
63 defaultOptions.datatier = None
64 defaultOptions.inlineEventContent = True
65 defaultOptions.inlineObjets =''
66 defaultOptions.hideGen=False
67 from Configuration.StandardSequences.VtxSmeared import VtxSmearedDefaultKey,VtxSmearedHIDefaultKey
68 defaultOptions.beamspot=None
69 defaultOptions.outputDefinition =''
70 defaultOptions.inputCommands = None
71 defaultOptions.outputCommands = None
72 defaultOptions.inputEventContent = ''
73 defaultOptions.dropDescendant = False
74 defaultOptions.relval = None
75 defaultOptions.profile = None
76 defaultOptions.isRepacked = False
77 defaultOptions.restoreRNDSeeds = False
78 defaultOptions.donotDropOnInput = ''
79 defaultOptions.python_filename =''
80 defaultOptions.io=None
81 defaultOptions.lumiToProcess=None
82 defaultOptions.fast=False
83 defaultOptions.runsAndWeightsForMC = None
84 defaultOptions.runsScenarioForMC = None
85 defaultOptions.runUnscheduled = False
86 defaultOptions.timeoutOutput = False
87 defaultOptions.nThreads = '1'
88 defaultOptions.nStreams = '0'
89 defaultOptions.nConcurrentLumis = '1'
90 
91 # some helper routines
92 def dumpPython(process,name):
93  theObject = getattr(process,name)
94  if isinstance(theObject,cms.Path) or isinstance(theObject,cms.EndPath) or isinstance(theObject,cms.Sequence):
95  return "process."+name+" = " + theObject.dumpPython()
96  elif isinstance(theObject,_Module) or isinstance(theObject,cms.ESProducer):
97  return "process."+name+" = " + theObject.dumpPython()+"\n"
98  else:
99  return "process."+name+" = " + theObject.dumpPython()+"\n"
100 def filesFromList(fileName,s=None):
101  import os
102  import FWCore.ParameterSet.Config as cms
103  prim=[]
104  sec=[]
105  for line in open(fileName,'r'):
106  if line.count(".root")>=2:
107  #two files solution...
108  entries=line.replace("\n","").split()
109  if not entries[0] in prim:
110  prim.append(entries[0])
111  if not entries[1] in sec:
112  sec.append(entries[1])
113  elif (line.find(".root")!=-1):
114  entry=line.replace("\n","")
115  if not entry in prim:
116  prim.append(entry)
117  if s:
118  if not hasattr(s,"fileNames"):
119  s.fileNames=cms.untracked.vstring(prim)
120  else:
121  s.fileNames.extend(prim)
122  if len(sec)!=0:
123  if not hasattr(s,"secondaryFileNames"):
124  s.secondaryFileNames=cms.untracked.vstring(sec)
125  else:
126  s.secondaryFileNames.extend(sec)
127  print("found files: ",prim)
128  if len(prim)==0:
129  raise Exception("There are not files in input from the file list")
130  if len(sec)!=0:
131  print("found parent files:",sec)
132  return (prim,sec)
133 
134 def filesFromDASQuery(query,option="",s=None):
135  import os,time
136  import FWCore.ParameterSet.Config as cms
137  prim=[]
138  sec=[]
139  print("the query is",query)
140  eC=5
141  count=0
142  while eC!=0 and count<3:
143  if count!=0:
144  print('Sleeping, then retrying DAS')
145  time.sleep(100)
146  p = Popen('dasgoclient %s --query "%s"'%(option,query), stdout=PIPE,shell=True, universal_newlines=True)
147  pipe=p.stdout.read()
148  tupleP = os.waitpid(p.pid, 0)
149  eC=tupleP[1]
150  count=count+1
151  if eC==0:
152  print("DAS succeeded after",count,"attempts",eC)
153  else:
154  print("DAS failed 3 times- I give up")
155  for line in pipe.split('\n'):
156  if line.count(".root")>=2:
157  #two files solution...
158  entries=line.replace("\n","").split()
159  if not entries[0] in prim:
160  prim.append(entries[0])
161  if not entries[1] in sec:
162  sec.append(entries[1])
163  elif (line.find(".root")!=-1):
164  entry=line.replace("\n","")
165  if not entry in prim:
166  prim.append(entry)
167  if s:
168  if not hasattr(s,"fileNames"):
169  s.fileNames=cms.untracked.vstring(prim)
170  else:
171  s.fileNames.extend(prim)
172  if len(sec)!=0:
173  if not hasattr(s,"secondaryFileNames"):
174  s.secondaryFileNames=cms.untracked.vstring(sec)
175  else:
176  s.secondaryFileNames.extend(sec)
177  print("found files: ",prim)
178  if len(sec)!=0:
179  print("found parent files:",sec)
180  return (prim,sec)
181 
182 def anyOf(listOfKeys,dict,opt=None):
183  for k in listOfKeys:
184  if k in dict:
185  toReturn=dict[k]
186  dict.pop(k)
187  return toReturn
188  if opt!=None:
189  return opt
190  else:
191  raise Exception("any of "+','.join(listOfKeys)+" are mandatory entries of --output options")
192 
194  """The main building routines """
195 
196  def __init__(self, options, process = None, with_output = False, with_input = False ):
197  """options taken from old cmsDriver and optparse """
198 
199  options.outfile_name = options.dirout+options.fileout
200 
201  self._options = options
202 
203  if self._options.isData and options.isMC:
204  raise Exception("ERROR: You may specify only --data or --mc, not both")
205  #if not self._options.conditions:
206  # raise Exception("ERROR: No conditions given!\nPlease specify conditions. E.g. via --conditions=IDEAL_30X::All")
207 
208  # check that MEtoEDMConverter (running in ENDJOB) and DQMIO don't run in the same job
209  if 'ENDJOB' in self._options.step:
210  if (hasattr(self._options,"outputDefinition") and \
211  self._options.outputDefinition != '' and \
212  any(anyOf(['t','tier','dataTier'],outdic) == 'DQMIO' for outdic in eval(self._options.outputDefinition))) or \
213  (hasattr(self._options,"datatier") and \
214  self._options.datatier and \
215  'DQMIO' in self._options.datatier):
216  print("removing ENDJOB from steps since not compatible with DQMIO dataTier")
217  self._options.step=self._options.step.replace(',ENDJOB','')
218 
219 
220 
221  # what steps are provided by this class?
222  stepList = [re.sub(r'^prepare_', '', methodName) for methodName in ConfigBuilder.__dict__ if methodName.startswith('prepare_')]
223  self.stepMap={}
224  self.stepKeys=[]
225  for step in self._options.step.split(","):
226  if step=='': continue
227  stepParts = step.split(":")
228  stepName = stepParts[0]
229  if stepName not in stepList and not stepName.startswith('re'):
230  raise ValueError("Step "+stepName+" unknown")
231  if len(stepParts)==1:
232  self.stepMap[stepName]=""
233  elif len(stepParts)==2:
234  self.stepMap[stepName]=stepParts[1].split('+')
235  elif len(stepParts)==3:
236  self.stepMap[stepName]=(stepParts[2].split('+'),stepParts[1])
237  else:
238  raise ValueError("Step definition "+step+" invalid")
239  self.stepKeys.append(stepName)
240 
241  #print "map of steps is:",self.stepMap
242 
243  self.with_output = with_output
244  self.process=process
245 
246  if hasattr(self._options,"no_output_flag") and self._options.no_output_flag:
247  self.with_output = False
248  self.with_input = with_input
249  self.imports = []
250  self.create_process()
251  self.define_Configs()
252  self.schedule = list()
253 
254  # we are doing three things here:
255  # creating a process to catch errors
256  # building the code to re-create the process
257 
259  # TODO: maybe a list of to be dumped objects would help as well
260  self.blacklist_paths = []
261  self.addedObjects = []
263 
269 
270  def profileOptions(self):
271  """
272  addIgProfService
273  Function to add the igprof profile service so that you can dump in the middle
274  of the run.
275  """
276  profileOpts = self._options.profile.split(':')
277  profilerStart = 1
278  profilerInterval = 100
279  profilerFormat = None
280  profilerJobFormat = None
281 
282  if len(profileOpts):
283  #type, given as first argument is unused here
284  profileOpts.pop(0)
285  if len(profileOpts):
286  startEvent = profileOpts.pop(0)
287  if not startEvent.isdigit():
288  raise Exception("%s is not a number" % startEvent)
289  profilerStart = int(startEvent)
290  if len(profileOpts):
291  eventInterval = profileOpts.pop(0)
292  if not eventInterval.isdigit():
293  raise Exception("%s is not a number" % eventInterval)
294  profilerInterval = int(eventInterval)
295  if len(profileOpts):
296  profilerFormat = profileOpts.pop(0)
297 
298 
299  if not profilerFormat:
300  profilerFormat = "%s___%s___%%I.gz" % (
301  self._options.evt_type.replace("_cfi", ""),
302  hashlib.md5(
303  str(self._options.step) + str(self._options.pileup) + str(self._options.conditions) +
304  str(self._options.datatier) + str(self._options.profileTypeLabel)
305  ).hexdigest()
306  )
307  if not profilerJobFormat and profilerFormat.endswith(".gz"):
308  profilerJobFormat = profilerFormat.replace(".gz", "_EndOfJob.gz")
309  elif not profilerJobFormat:
310  profilerJobFormat = profilerFormat + "_EndOfJob.gz"
311 
312  return (profilerStart,profilerInterval,profilerFormat,profilerJobFormat)
313 
314  def load(self,includeFile):
315  includeFile = includeFile.replace('/','.')
316  self.process.load(includeFile)
317  return sys.modules[includeFile]
318 
319  def loadAndRemember(self, includeFile):
320  """helper routine to load am memorize imports"""
321  # we could make the imports a on-the-fly data method of the process instance itself
322  # not sure if the latter is a good idea
323  includeFile = includeFile.replace('/','.')
324  self.imports.append(includeFile)
325  self.process.load(includeFile)
326  return sys.modules[includeFile]
327 
328  def executeAndRemember(self, command):
329  """helper routine to remember replace statements"""
330  self.additionalCommands.append(command)
331  if not command.strip().startswith("#"):
332  # substitute: process.foo = process.bar -> self.process.foo = self.process.bar
333  import re
334  exec(re.sub(r"([^a-zA-Z_0-9]|^)(process)([^a-zA-Z_0-9])",r"\1self.process\3",command))
335  #exec(command.replace("process.","self.process."))
336 
337  def addCommon(self):
338  if 'HARVESTING' in self.stepMap.keys() or 'ALCAHARVEST' in self.stepMap.keys():
339  self.process.options = cms.untracked.PSet( Rethrow = cms.untracked.vstring('ProductNotFound'),fileMode = cms.untracked.string('FULLMERGE'))
340  else:
341  self.process.options = cms.untracked.PSet( )
342 
343  self.addedObjects.append(("","options"))
344 
345  if self._options.lazy_download:
346  self.process.AdaptorConfig = cms.Service("AdaptorConfig",
347  stats = cms.untracked.bool(True),
348  enable = cms.untracked.bool(True),
349  cacheHint = cms.untracked.string("lazy-download"),
350  readHint = cms.untracked.string("read-ahead-buffered")
351  )
352  self.addedObjects.append(("Setup lazy download","AdaptorConfig"))
353 
354  #self.process.cmsDriverCommand = cms.untracked.PSet( command=cms.untracked.string('cmsDriver.py '+self._options.arguments) )
355  #self.addedObjects.append(("what cmsDriver command was used","cmsDriverCommand"))
356 
357  if self._options.profile:
358  (start, interval, eventFormat, jobFormat)=self.profileOptions()
359  self.process.IgProfService = cms.Service("IgProfService",
360  reportFirstEvent = cms.untracked.int32(start),
361  reportEventInterval = cms.untracked.int32(interval),
362  reportToFileAtPostEvent = cms.untracked.string("| gzip -c > %s"%(eventFormat)),
363  reportToFileAtPostEndJob = cms.untracked.string("| gzip -c > %s"%(jobFormat)))
364  self.addedObjects.append(("Setup IGProf Service for profiling","IgProfService"))
365 
366  def addMaxEvents(self):
367  """Here we decide how many evts will be processed"""
368  self.process.maxEvents=cms.untracked.PSet(input=cms.untracked.int32(int(self._options.number)))
369  if self._options.number_out:
370  self.process.maxEvents.output = cms.untracked.int32(int(self._options.number_out))
371  self.addedObjects.append(("","maxEvents"))
372 
373  def addSource(self):
374  """Here the source is built. Priority: file, generator"""
375  self.addedObjects.append(("Input source","source"))
376 
377  def filesFromOption(self):
378  for entry in self._options.filein.split(','):
379  print("entry",entry)
380  if entry.startswith("filelist:"):
381  filesFromList(entry[9:],self.process.source)
382  elif entry.startswith("dbs:") or entry.startswith("das:"):
383  filesFromDASQuery('file dataset = %s'%(entry[4:]),self._options.dasoption,self.process.source)
384  else:
385  self.process.source.fileNames.append(self._options.dirin+entry)
386  if self._options.secondfilein:
387  if not hasattr(self.process.source,"secondaryFileNames"):
388  raise Exception("--secondfilein not compatible with "+self._options.filetype+"input type")
389  for entry in self._options.secondfilein.split(','):
390  print("entry",entry)
391  if entry.startswith("filelist:"):
392  self.process.source.secondaryFileNames.extend((filesFromList(entry[9:]))[0])
393  elif entry.startswith("dbs:") or entry.startswith("das:"):
394  self.process.source.secondaryFileNames.extend((filesFromDASQuery('file dataset = %s'%(entry[4:]),self._options.dasoption))[0])
395  else:
396  self.process.source.secondaryFileNames.append(self._options.dirin+entry)
397 
398  if self._options.filein or self._options.dasquery:
399  if self._options.filetype == "EDM":
400  self.process.source=cms.Source("PoolSource",
401  fileNames = cms.untracked.vstring(),
402  secondaryFileNames= cms.untracked.vstring())
403  filesFromOption(self)
404  elif self._options.filetype == "DAT":
405  self.process.source=cms.Source("NewEventStreamFileReader",fileNames = cms.untracked.vstring())
406  filesFromOption(self)
407  elif self._options.filetype == "LHE":
408  self.process.source=cms.Source("LHESource", fileNames = cms.untracked.vstring())
409  if self._options.filein.startswith("lhe:"):
410  #list the article directory automatically
411  args=self._options.filein.split(':')
412  article=args[1]
413  print('LHE input from article ',article)
414  location='/store/lhe/'
415  import os
416  textOfFiles=os.popen('cmsLHEtoEOSManager.py -l '+article)
417  for line in textOfFiles:
418  for fileName in [x for x in line.split() if '.lhe' in x]:
419  self.process.source.fileNames.append(location+article+'/'+fileName)
420  #check first if list of LHE files is loaded (not empty)
421  if len(line)<2:
422  print('Issue to load LHE files, please check and try again.')
423  sys.exit(-1)
424  #Additional check to protect empty fileNames in process.source
425  if len(self.process.source.fileNames)==0:
426  print('Issue with empty filename, but can pass line check')
427  sys.exit(-1)
428  if len(args)>2:
429  self.process.source.skipEvents = cms.untracked.uint32(int(args[2]))
430  else:
431  filesFromOption(self)
432 
433  elif self._options.filetype == "DQM":
434  self.process.source=cms.Source("DQMRootSource",
435  fileNames = cms.untracked.vstring())
436  filesFromOption(self)
437 
438  elif self._options.filetype == "DQMDAQ":
439  # FIXME: how to configure it if there are no input files specified?
440  self.process.source=cms.Source("DQMStreamerReader")
441 
442 
443  if ('HARVESTING' in self.stepMap.keys() or 'ALCAHARVEST' in self.stepMap.keys()) and (not self._options.filetype == "DQM"):
444  self.process.source.processingMode = cms.untracked.string("RunsAndLumis")
445 
446  if self._options.dasquery!='':
447  self.process.source=cms.Source("PoolSource", fileNames = cms.untracked.vstring(),secondaryFileNames = cms.untracked.vstring())
448  filesFromDASQuery(self._options.dasquery,self._options.dasoption,self.process.source)
449 
450  if ('HARVESTING' in self.stepMap.keys() or 'ALCAHARVEST' in self.stepMap.keys()) and (not self._options.filetype == "DQM"):
451  self.process.source.processingMode = cms.untracked.string("RunsAndLumis")
452 
453  ##drop LHEXMLStringProduct on input to save memory if appropriate
454  if 'GEN' in self.stepMap.keys():
455  if self._options.inputCommands:
456  self._options.inputCommands+=',drop LHEXMLStringProduct_*_*_*,'
457  else:
458  self._options.inputCommands='keep *, drop LHEXMLStringProduct_*_*_*,'
459 
460  if self.process.source and self._options.inputCommands:
461  if not hasattr(self.process.source,'inputCommands'): self.process.source.inputCommands=cms.untracked.vstring()
462  for command in self._options.inputCommands.split(','):
463  # remove whitespace around the keep/drop statements
464  command = command.strip()
465  if command=='': continue
466  self.process.source.inputCommands.append(command)
467  if not self._options.dropDescendant:
468  self.process.source.dropDescendantsOfDroppedBranches = cms.untracked.bool(False)
469 
470  if self._options.lumiToProcess:
471  import FWCore.PythonUtilities.LumiList as LumiList
472  self.process.source.lumisToProcess = cms.untracked.VLuminosityBlockRange( LumiList.LumiList(self._options.lumiToProcess).getCMSSWString().split(',') )
473 
474  if 'GEN' in self.stepMap.keys() or 'LHE' in self.stepMap or (not self._options.filein and hasattr(self._options, "evt_type")):
475  if self.process.source is None:
476  self.process.source=cms.Source("EmptySource")
477 
478  # modify source in case of run-dependent MC
479  self.runsAndWeights=None
480  if self._options.runsAndWeightsForMC or self._options.runsScenarioForMC :
481  if not self._options.isMC :
482  raise Exception("options --runsAndWeightsForMC and --runsScenarioForMC are only valid for MC")
483  if self._options.runsAndWeightsForMC:
484  self.runsAndWeights = eval(self._options.runsAndWeightsForMC)
485  else:
486  from Configuration.StandardSequences.RunsAndWeights import RunsAndWeights
487  if isinstance(RunsAndWeights[self._options.runsScenarioForMC], str):
488  __import__(RunsAndWeights[self._options.runsScenarioForMC])
489  self.runsAndWeights = sys.modules[RunsAndWeights[self._options.runsScenarioForMC]].runProbabilityDistribution
490  else:
491  self.runsAndWeights = RunsAndWeights[self._options.runsScenarioForMC]
492 
493  if self.runsAndWeights:
494  import SimGeneral.Configuration.ThrowAndSetRandomRun as ThrowAndSetRandomRun
496  self.additionalCommands.append('import SimGeneral.Configuration.ThrowAndSetRandomRun as ThrowAndSetRandomRun')
497  self.additionalCommands.append('ThrowAndSetRandomRun.throwAndSetRandomRun(process.source,%s)'%(self.runsAndWeights))
498 
499  return
500 
501  def addOutput(self):
502  """ Add output module to the process """
503  result=""
504  if self._options.outputDefinition:
505  if self._options.datatier:
506  print("--datatier & --eventcontent options ignored")
507 
508  #new output convention with a list of dict
509  outList = eval(self._options.outputDefinition)
510  for (id,outDefDict) in enumerate(outList):
511  outDefDictStr=outDefDict.__str__()
512  if not isinstance(outDefDict,dict):
513  raise Exception("--output needs to be passed a list of dict"+self._options.outputDefinition+" is invalid")
514  #requires option: tier
515  theTier=anyOf(['t','tier','dataTier'],outDefDict)
516  #optional option: eventcontent, filtername, selectEvents, moduleLabel, filename
517  ## event content
518  theStreamType=anyOf(['e','ec','eventContent','streamType'],outDefDict,theTier)
519  theFilterName=anyOf(['f','ftN','filterName'],outDefDict,'')
520  theSelectEvent=anyOf(['s','sE','selectEvents'],outDefDict,'')
521  theModuleLabel=anyOf(['l','mL','moduleLabel'],outDefDict,'')
522  theExtraOutputCommands=anyOf(['o','oC','outputCommands'],outDefDict,'')
523  # module label has a particular role
524  if not theModuleLabel:
525  tryNames=[theStreamType.replace(theTier.replace('-',''),'')+theTier.replace('-','')+'output',
526  theStreamType.replace(theTier.replace('-',''),'')+theTier.replace('-','')+theFilterName+'output',
527  theStreamType.replace(theTier.replace('-',''),'')+theTier.replace('-','')+theFilterName+theSelectEvent.split(',')[0].replace(':','for').replace(' ','')+'output'
528  ]
529  for name in tryNames:
530  if not hasattr(self.process,name):
531  theModuleLabel=name
532  break
533  if not theModuleLabel:
534  raise Exception("cannot find a module label for specification: "+outDefDictStr)
535  if id==0:
536  defaultFileName=self._options.outfile_name
537  else:
538  defaultFileName=self._options.outfile_name.replace('.root','_in'+theTier+'.root')
539 
540  theFileName=self._options.dirout+anyOf(['fn','fileName'],outDefDict,defaultFileName)
541  if not theFileName.endswith('.root'):
542  theFileName+='.root'
543 
544  if len(outDefDict):
545  raise Exception("unused keys from --output options: "+','.join(outDefDict.keys()))
546  if theStreamType=='DQMIO': theStreamType='DQM'
547  if theStreamType=='ALL':
548  theEventContent = cms.PSet(outputCommands = cms.untracked.vstring('keep *'))
549  else:
550  theEventContent = getattr(self.process, theStreamType+"EventContent")
551 
552 
553  addAlCaSelects=False
554  if theStreamType=='ALCARECO' and not theFilterName:
555  theFilterName='StreamALCACombined'
556  addAlCaSelects=True
557 
558  CppType='PoolOutputModule'
559  if self._options.timeoutOutput:
560  CppType='TimeoutPoolOutputModule'
561  if theStreamType=='DQM' and theTier=='DQMIO': CppType='DQMRootOutputModule'
562  output = cms.OutputModule(CppType,
563  theEventContent.clone(),
564  fileName = cms.untracked.string(theFileName),
565  dataset = cms.untracked.PSet(
566  dataTier = cms.untracked.string(theTier),
567  filterName = cms.untracked.string(theFilterName))
568  )
569  if not theSelectEvent and hasattr(self.process,'generation_step') and theStreamType!='LHE':
570  output.SelectEvents = cms.untracked.PSet(SelectEvents = cms.vstring('generation_step'))
571  if not theSelectEvent and hasattr(self.process,'filtering_step'):
572  output.SelectEvents = cms.untracked.PSet(SelectEvents = cms.vstring('filtering_step'))
573  if theSelectEvent:
574  output.SelectEvents =cms.untracked.PSet(SelectEvents = cms.vstring(theSelectEvent))
575 
576  if addAlCaSelects:
577  if not hasattr(output,'SelectEvents'):
578  output.SelectEvents=cms.untracked.PSet(SelectEvents=cms.vstring())
579  for alca in self.AlCaPaths:
580  output.SelectEvents.SelectEvents.extend(getattr(self.process,'OutALCARECO'+alca).SelectEvents.SelectEvents)
581 
582 
583  if hasattr(self.process,theModuleLabel):
584  raise Exception("the current process already has a module "+theModuleLabel+" defined")
585  #print "creating output module ",theModuleLabel
586  setattr(self.process,theModuleLabel,output)
587  outputModule=getattr(self.process,theModuleLabel)
588  setattr(self.process,theModuleLabel+'_step',cms.EndPath(outputModule))
589  path=getattr(self.process,theModuleLabel+'_step')
590  self.schedule.append(path)
591 
592  if not self._options.inlineEventContent and hasattr(self.process,theStreamType+"EventContent"):
593  def doNotInlineEventContent(instance,label = "cms.untracked.vstring(process."+theStreamType+"EventContent.outputCommands)"):
594  return label
595  outputModule.outputCommands.__dict__["dumpPython"] = doNotInlineEventContent
596  if theExtraOutputCommands:
597  if not isinstance(theExtraOutputCommands,list):
598  raise Exception("extra ouput command in --option must be a list of strings")
599  if hasattr(self.process,theStreamType+"EventContent"):
600  self.executeAndRemember('process.%s.outputCommands.extend(%s)'%(theModuleLabel,theExtraOutputCommands))
601  else:
602  outputModule.outputCommands.extend(theExtraOutputCommands)
603 
604  result+="\nprocess."+theModuleLabel+" = "+outputModule.dumpPython()
605 
606  ##ends the --output options model
607  return result
608 
609  streamTypes=self._options.eventcontent.split(',')
610  tiers=self._options.datatier.split(',')
611  if not self._options.outputDefinition and len(streamTypes)!=len(tiers):
612  raise Exception("number of event content arguments does not match number of datatier arguments")
613 
614  # if the only step is alca we don't need to put in an output
615  if self._options.step.split(',')[0].split(':')[0] == 'ALCA':
616  return "\n"
617 
618  for i,(streamType,tier) in enumerate(zip(streamTypes,tiers)):
619  if streamType=='': continue
620  if streamType == 'ALCARECO' and not 'ALCAPRODUCER' in self._options.step: continue
621  if streamType=='DQMIO': streamType='DQM'
622  eventContent=streamType
623  ## override streamType to eventContent in case NANOEDM
624  if streamType == "NANOEDMAOD" :
625  eventContent = "NANOAOD"
626  elif streamType == "NANOEDMAODSIM" :
627  eventContent = "NANOAODSIM"
628  theEventContent = getattr(self.process, eventContent+"EventContent")
629  if i==0:
630  theFileName=self._options.outfile_name
631  theFilterName=self._options.filtername
632  else:
633  theFileName=self._options.outfile_name.replace('.root','_in'+streamType+'.root')
634  theFilterName=self._options.filtername
635  CppType='PoolOutputModule'
636  if self._options.timeoutOutput:
637  CppType='TimeoutPoolOutputModule'
638  if streamType=='DQM' and tier=='DQMIO': CppType='DQMRootOutputModule'
639  if "NANOAOD" in streamType : CppType='NanoAODOutputModule'
640  output = cms.OutputModule(CppType,
641  theEventContent,
642  fileName = cms.untracked.string(theFileName),
643  dataset = cms.untracked.PSet(dataTier = cms.untracked.string(tier),
644  filterName = cms.untracked.string(theFilterName)
645  )
646  )
647  if hasattr(self.process,"generation_step") and streamType!='LHE':
648  output.SelectEvents = cms.untracked.PSet(SelectEvents = cms.vstring('generation_step'))
649  if hasattr(self.process,"filtering_step"):
650  output.SelectEvents = cms.untracked.PSet(SelectEvents = cms.vstring('filtering_step'))
651 
652  if streamType=='ALCARECO':
653  output.dataset.filterName = cms.untracked.string('StreamALCACombined')
654 
655  if "MINIAOD" in streamType:
656  from PhysicsTools.PatAlgos.slimming.miniAOD_tools import miniAOD_customizeOutput
658 
659  outputModuleName=streamType+'output'
660  setattr(self.process,outputModuleName,output)
661  outputModule=getattr(self.process,outputModuleName)
662  setattr(self.process,outputModuleName+'_step',cms.EndPath(outputModule))
663  path=getattr(self.process,outputModuleName+'_step')
664  self.schedule.append(path)
665 
666  if self._options.outputCommands and streamType!='DQM':
667  for evct in self._options.outputCommands.split(','):
668  if not evct: continue
669  self.executeAndRemember("process.%s.outputCommands.append('%s')"%(outputModuleName,evct.strip()))
670 
671  if not self._options.inlineEventContent:
672  tmpstreamType=streamType
673  if "NANOEDM" in tmpstreamType :
674  tmpstreamType=tmpstreamType.replace("NANOEDM","NANO")
675  def doNotInlineEventContent(instance,label = "process."+tmpstreamType+"EventContent.outputCommands"):
676  return label
677  outputModule.outputCommands.__dict__["dumpPython"] = doNotInlineEventContent
678 
679  result+="\nprocess."+outputModuleName+" = "+outputModule.dumpPython()
680 
681  return result
682 
684  """
685  Add selected standard sequences to the process
686  """
687  # load the pile up file
688  if self._options.pileup:
689  pileupSpec=self._options.pileup.split(',')[0]
690 
691  # Does the requested pile-up scenario exist?
692  from Configuration.StandardSequences.Mixing import Mixing,defineMixing
693  if not pileupSpec in Mixing and '.' not in pileupSpec and 'file:' not in pileupSpec:
694  message = pileupSpec+' is not a know mixing scenario:\n available are: '+'\n'.join(Mixing.keys())
695  raise Exception(message)
696 
697  # Put mixing parameters in a dictionary
698  if '.' in pileupSpec:
699  mixingDict={'file':pileupSpec}
700  elif pileupSpec.startswith('file:'):
701  mixingDict={'file':pileupSpec[5:]}
702  else:
703  import copy
704  mixingDict=copy.copy(Mixing[pileupSpec])
705  if len(self._options.pileup.split(','))>1:
706  mixingDict.update(eval(self._options.pileup[self._options.pileup.find(',')+1:]))
707 
708  # Load the pu cfg file corresponding to the requested pu scenario
709  if 'file:' in pileupSpec:
710  #the file is local
711  self.process.load(mixingDict['file'])
712  print("inlining mixing module configuration")
713  self._options.inlineObjets+=',mix'
714  else:
715  self.loadAndRemember(mixingDict['file'])
716 
717  mixingDict.pop('file')
718  if not "DATAMIX" in self.stepMap.keys(): # when DATAMIX is present, pileup_input refers to pre-mixed GEN-RAW
719  if self._options.pileup_input:
720  if self._options.pileup_input.startswith('dbs:') or self._options.pileup_input.startswith('das:'):
721  mixingDict['F']=filesFromDASQuery('file dataset = %s'%(self._options.pileup_input[4:],),self._options.pileup_dasoption)[0]
722  elif self._options.pileup_input.startswith("filelist:"):
723  mixingDict['F']=(filesFromList(self._options.pileup_input[9:]))[0]
724  else:
725  mixingDict['F']=self._options.pileup_input.split(',')
726  specialization=defineMixing(mixingDict)
727  for command in specialization:
728  self.executeAndRemember(command)
729  if len(mixingDict)!=0:
730  raise Exception('unused mixing specification: '+mixingDict.keys().__str__())
731 
732 
733  # load the geometry file
734  try:
735  if len(self.stepMap):
736  self.loadAndRemember(self.GeometryCFF)
737  if ('SIM' in self.stepMap or 'reSIM' in self.stepMap) and not self._options.fast:
739  if self.geometryDBLabel:
740  self.executeAndRemember('process.XMLFromDBSource.label = cms.string("%s")'%(self.geometryDBLabel))
741  except ImportError:
742  print("Geometry option",self._options.geometry,"unknown.")
743  raise
744 
745  if len(self.stepMap):
746  self.loadAndRemember(self.magFieldCFF)
747 
748  for stepName in self.stepKeys:
749  stepSpec = self.stepMap[stepName]
750  print("Step:", stepName,"Spec:",stepSpec)
751  if stepName.startswith('re'):
752  ##add the corresponding input content
753  if stepName[2:] not in self._options.donotDropOnInput:
754  self._options.inputEventContent='%s,%s'%(stepName.upper(),self._options.inputEventContent)
755  stepName=stepName[2:]
756  if stepSpec=="":
757  getattr(self,"prepare_"+stepName)(sequence = getattr(self,stepName+"DefaultSeq"))
758  elif isinstance(stepSpec, list):
759  getattr(self,"prepare_"+stepName)(sequence = '+'.join(stepSpec))
760  elif isinstance(stepSpec, tuple):
761  getattr(self,"prepare_"+stepName)(sequence = ','.join([stepSpec[1],'+'.join(stepSpec[0])]))
762  else:
763  raise ValueError("Invalid step definition")
764 
765  if self._options.restoreRNDSeeds!=False:
766  #it is either True, or a process name
767  if self._options.restoreRNDSeeds==True:
768  self.executeAndRemember('process.RandomNumberGeneratorService.restoreStateLabel=cms.untracked.string("randomEngineStateProducer")')
769  else:
770  self.executeAndRemember('process.RandomNumberGeneratorService.restoreStateTag=cms.untracked.InputTag("randomEngineStateProducer","","%s")'%(self._options.restoreRNDSeeds))
771  if self._options.inputEventContent or self._options.inputCommands:
772  if self._options.inputCommands:
773  self._options.inputCommands+='keep *_randomEngineStateProducer_*_*,'
774  else:
775  self._options.inputCommands='keep *_randomEngineStateProducer_*_*,'
776 
777 
779  if self._options.inputEventContent:
780  import copy
781  def dropSecondDropStar(iec):
782  #drop occurence of 'drop *' in the list
783  count=0
784  for item in iec:
785  if item=='drop *':
786  if count!=0:
787  iec.remove(item)
788  count+=1
789 
790 
791  ## allow comma separated input eventcontent
792  if not hasattr(self.process.source,'inputCommands'): self.process.source.inputCommands=cms.untracked.vstring()
793  for evct in self._options.inputEventContent.split(','):
794  if evct=='': continue
795  theEventContent = getattr(self.process, evct+"EventContent")
796  if hasattr(theEventContent,'outputCommands'):
797  self.process.source.inputCommands.extend(copy.copy(theEventContent.outputCommands))
798  if hasattr(theEventContent,'inputCommands'):
799  self.process.source.inputCommands.extend(copy.copy(theEventContent.inputCommands))
800 
801  dropSecondDropStar(self.process.source.inputCommands)
802 
803  if not self._options.dropDescendant:
804  self.process.source.dropDescendantsOfDroppedBranches = cms.untracked.bool(False)
805 
806 
807  return
808 
809  def addConditions(self):
810  """Add conditions to the process"""
811  if not self._options.conditions: return
812 
813  if 'FrontierConditions_GlobalTag' in self._options.conditions:
814  print('using FrontierConditions_GlobalTag in --conditions is not necessary anymore and will be deprecated soon. please update your command line')
815  self._options.conditions = self._options.conditions.replace("FrontierConditions_GlobalTag,",'')
816 
818  from Configuration.AlCa.GlobalTag import GlobalTag
819  self.process.GlobalTag = GlobalTag(self.process.GlobalTag, self._options.conditions, self._options.custom_conditions)
820  self.additionalCommands.append('from Configuration.AlCa.GlobalTag import GlobalTag')
821  self.additionalCommands.append('process.GlobalTag = GlobalTag(process.GlobalTag, %s, %s)' % (repr(self._options.conditions), repr(self._options.custom_conditions)))
822 
823 
824  def addCustomise(self,unsch=0):
825  """Include the customise code """
826 
827  custOpt=[]
828  if unsch==0:
829  for c in self._options.customisation_file:
830  custOpt.extend(c.split(","))
831  else:
832  for c in self._options.customisation_file_unsch:
833  custOpt.extend(c.split(","))
834 
835  custMap=DictTypes.SortedKeysDict()
836  for opt in custOpt:
837  if opt=='': continue
838  if opt.count('.')>1:
839  raise Exception("more than . in the specification:"+opt)
840  fileName=opt.split('.')[0]
841  if opt.count('.')==0: rest='customise'
842  else:
843  rest=opt.split('.')[1]
844  if rest=='py': rest='customise' #catch the case of --customise file.py
845 
846  if fileName in custMap:
847  custMap[fileName].extend(rest.split('+'))
848  else:
849  custMap[fileName]=rest.split('+')
850 
851  if len(custMap)==0:
852  final_snippet='\n'
853  else:
854  final_snippet='\n# customisation of the process.\n'
855 
856  allFcn=[]
857  for opt in custMap:
858  allFcn.extend(custMap[opt])
859  for fcn in allFcn:
860  if allFcn.count(fcn)!=1:
861  raise Exception("cannot specify twice "+fcn+" as a customisation method")
862 
863  for f in custMap:
864  # let python search for that package and do syntax checking at the same time
865  packageName = f.replace(".py","").replace("/",".")
866  __import__(packageName)
867  package = sys.modules[packageName]
868 
869  # now ask the package for its definition and pick .py instead of .pyc
870  customiseFile = re.sub(r'\.pyc$', '.py', package.__file__)
871 
872  final_snippet+='\n# Automatic addition of the customisation function from '+packageName+'\n'
873  if self._options.inline_custom:
874  for line in file(customiseFile,'r'):
875  if "import FWCore.ParameterSet.Config" in line:
876  continue
877  final_snippet += line
878  else:
879  final_snippet += 'from %s import %s \n'%(packageName,','.join(custMap[f]))
880  for fcn in custMap[f]:
881  print("customising the process with",fcn,"from",f)
882  if not hasattr(package,fcn):
883  #bound to fail at run time
884  raise Exception("config "+f+" has no function "+fcn)
885  #execute the command
886  self.process=getattr(package,fcn)(self.process)
887  #and print it in the configuration
888  final_snippet += "\n#call to customisation function "+fcn+" imported from "+packageName
889  final_snippet += "\nprocess = %s(process)\n"%(fcn,)
890 
891  if len(custMap)!=0:
892  final_snippet += '\n# End of customisation functions\n'
893 
894  ### now for a useful command
895  return final_snippet
896 
898  final_snippet='\n# Customisation from command line\n'
899  if self._options.customise_commands:
900  import string
901  for com in self._options.customise_commands.split('\\n'):
902  com=com.lstrip()
903  self.executeAndRemember(com)
904  final_snippet +='\n'+com
905 
906  return final_snippet
907 
908  #----------------------------------------------------------------------------
909  # here the methods to define the python includes for each step or
910  # conditions
911  #----------------------------------------------------------------------------
912  def define_Configs(self):
913  if len(self.stepMap):
914  self.loadAndRemember('Configuration/StandardSequences/Services_cff')
915  if self._options.particleTable not in defaultOptions.particleTableList:
916  print('Invalid particle table provided. Options are:')
917  print(defaultOptions.particleTable)
918  sys.exit(-1)
919  else:
920  if len(self.stepMap):
921  self.loadAndRemember('SimGeneral.HepPDTESSource.'+self._options.particleTable+'_cfi')
922 
923  self.loadAndRemember('FWCore/MessageService/MessageLogger_cfi')
924 
925  self.ALCADefaultCFF="Configuration/StandardSequences/AlCaRecoStreams_cff"
926  self.GENDefaultCFF="Configuration/StandardSequences/Generator_cff"
927  self.SIMDefaultCFF="Configuration/StandardSequences/Sim_cff"
928  self.DIGIDefaultCFF="Configuration/StandardSequences/Digi_cff"
929  self.DIGI2RAWDefaultCFF="Configuration/StandardSequences/DigiToRaw_cff"
930  self.L1EMDefaultCFF='Configuration/StandardSequences/SimL1Emulator_cff'
931  self.L1MENUDefaultCFF="Configuration/StandardSequences/L1TriggerDefaultMenu_cff"
932  self.HLTDefaultCFF="Configuration/StandardSequences/HLTtable_cff"
933  self.RAW2DIGIDefaultCFF="Configuration/StandardSequences/RawToDigi_Data_cff"
934  if self._options.isRepacked: self.RAW2DIGIDefaultCFF="Configuration/StandardSequences/RawToDigi_DataMapper_cff"
935  self.L1RecoDefaultCFF="Configuration/StandardSequences/L1Reco_cff"
936  self.L1TrackTriggerDefaultCFF="Configuration/StandardSequences/L1TrackTrigger_cff"
937  self.RECODefaultCFF="Configuration/StandardSequences/Reconstruction_Data_cff"
938  self.RECOSIMDefaultCFF="Configuration/StandardSequences/RecoSim_cff"
939  self.PATDefaultCFF="Configuration/StandardSequences/PAT_cff"
940  self.NANODefaultCFF="PhysicsTools/NanoAOD/nano_cff"
941  self.EIDefaultCFF=None
942  self.SKIMDefaultCFF="Configuration/StandardSequences/Skims_cff"
943  self.POSTRECODefaultCFF="Configuration/StandardSequences/PostRecoGenerator_cff"
944  self.VALIDATIONDefaultCFF="Configuration/StandardSequences/Validation_cff"
945  self.L1HwValDefaultCFF = "Configuration/StandardSequences/L1HwVal_cff"
946  self.DQMOFFLINEDefaultCFF="DQMOffline/Configuration/DQMOffline_cff"
947  self.HARVESTINGDefaultCFF="Configuration/StandardSequences/Harvesting_cff"
948  self.ALCAHARVESTDefaultCFF="Configuration/StandardSequences/AlCaHarvesting_cff"
949  self.ENDJOBDefaultCFF="Configuration/StandardSequences/EndOfProcess_cff"
950  self.ConditionsDefaultCFF = "Configuration/StandardSequences/FrontierConditions_GlobalTag_cff"
951  self.CFWRITERDefaultCFF = "Configuration/StandardSequences/CrossingFrameWriter_cff"
952  self.REPACKDefaultCFF="Configuration/StandardSequences/DigiToRaw_Repack_cff"
953 
954  if "DATAMIX" in self.stepMap.keys():
955  self.DATAMIXDefaultCFF="Configuration/StandardSequences/DataMixer"+self._options.datamix+"_cff"
956  self.DIGIDefaultCFF="Configuration/StandardSequences/DigiDM_cff"
957  self.DIGI2RAWDefaultCFF="Configuration/StandardSequences/DigiToRawDM_cff"
958  self.L1EMDefaultCFF='Configuration/StandardSequences/SimL1EmulatorDM_cff'
959 
960  self.ALCADefaultSeq=None
961  self.LHEDefaultSeq='externalLHEProducer'
962  self.GENDefaultSeq='pgen'
963  self.SIMDefaultSeq='psim'
964  self.DIGIDefaultSeq='pdigi'
966  self.DIGI2RAWDefaultSeq='DigiToRaw'
967  self.HLTDefaultSeq='GRun'
968  self.L1DefaultSeq=None
973  self.RAW2DIGIDefaultSeq='RawToDigi'
974  self.L1RecoDefaultSeq='L1Reco'
975  self.L1TrackTriggerDefaultSeq='L1TrackTrigger'
976  if self._options.fast or ('RAW2DIGI' in self.stepMap and 'RECO' in self.stepMap):
977  self.RECODefaultSeq='reconstruction'
978  else:
979  self.RECODefaultSeq='reconstruction_fromRECO'
980  self.RECOSIMDefaultSeq='recosim'
981  self.EIDefaultSeq='top'
983  self.L1HwValDefaultSeq='L1HwVal'
984  self.DQMDefaultSeq='DQMOffline'
986  self.ENDJOBDefaultSeq='endOfProcess'
987  self.REPACKDefaultSeq='DigiToRawRepack'
988  self.PATDefaultSeq='miniAOD'
989  self.PATGENDefaultSeq='miniGEN'
990  self.NANODefaultSeq='nanoSequence'
991 
992  self.EVTCONTDefaultCFF="Configuration/EventContent/EventContent_cff"
993 
994  if not self._options.beamspot:
995  self._options.beamspot=VtxSmearedDefaultKey
996 
997  # if its MC then change the raw2digi
998  if self._options.isMC==True:
999  self.RAW2DIGIDefaultCFF="Configuration/StandardSequences/RawToDigi_cff"
1000  self.RECODefaultCFF="Configuration/StandardSequences/Reconstruction_cff"
1001  self.PATDefaultCFF="Configuration/StandardSequences/PATMC_cff"
1002  self.PATGENDefaultCFF="Configuration/StandardSequences/PATGEN_cff"
1003  self.DQMOFFLINEDefaultCFF="DQMOffline/Configuration/DQMOfflineMC_cff"
1004  self.ALCADefaultCFF="Configuration/StandardSequences/AlCaRecoStreamsMC_cff"
1005  self.NANODefaultSeq='nanoSequenceMC'
1006  else:
1007  self._options.beamspot = None
1008 
1009  #patch for gen, due to backward incompatibility
1010  if 'reGEN' in self.stepMap:
1011  self.GENDefaultSeq='fixGenInfo'
1012 
1013  if self._options.scenario=='cosmics':
1014  self._options.pileup='Cosmics'
1015  self.DIGIDefaultCFF="Configuration/StandardSequences/DigiCosmics_cff"
1016  self.RECODefaultCFF="Configuration/StandardSequences/ReconstructionCosmics_cff"
1017  self.SKIMDefaultCFF="Configuration/StandardSequences/SkimsCosmics_cff"
1018  self.EVTCONTDefaultCFF="Configuration/EventContent/EventContentCosmics_cff"
1019  self.VALIDATIONDefaultCFF="Configuration/StandardSequences/ValidationCosmics_cff"
1020  self.DQMOFFLINEDefaultCFF="DQMOffline/Configuration/DQMOfflineCosmics_cff"
1021  if self._options.isMC==True:
1022  self.DQMOFFLINEDefaultCFF="DQMOffline/Configuration/DQMOfflineCosmicsMC_cff"
1023  self.HARVESTINGDefaultCFF="Configuration/StandardSequences/HarvestingCosmics_cff"
1024  self.RECODefaultSeq='reconstructionCosmics'
1025  self.DQMDefaultSeq='DQMOfflineCosmics'
1026 
1027  if self._options.scenario=='HeavyIons':
1028  if not self._options.beamspot:
1029  self._options.beamspot=VtxSmearedHIDefaultKey
1030  self.HLTDefaultSeq = 'HIon'
1031  self.VALIDATIONDefaultCFF="Configuration/StandardSequences/ValidationHeavyIons_cff"
1032  self.VALIDATIONDefaultSeq=''
1033  self.EVTCONTDefaultCFF="Configuration/EventContent/EventContentHeavyIons_cff"
1034  self.RECODefaultCFF="Configuration/StandardSequences/ReconstructionHeavyIons_cff"
1035  self.RECODefaultSeq='reconstructionHeavyIons'
1036  self.ALCADefaultCFF = "Configuration/StandardSequences/AlCaRecoStreamsHeavyIons_cff"
1037  self.DQMOFFLINEDefaultCFF="DQMOffline/Configuration/DQMOfflineHeavyIons_cff"
1038  self.DQMDefaultSeq='DQMOfflineHeavyIons'
1039  self.SKIMDefaultCFF="Configuration/StandardSequences/SkimsHeavyIons_cff"
1040  self.HARVESTINGDefaultCFF="Configuration/StandardSequences/HarvestingHeavyIons_cff"
1041  if self._options.isMC==True:
1042  self.DQMOFFLINEDefaultCFF="DQMOffline/Configuration/DQMOfflineHeavyIonsMC_cff"
1043 
1044 
1046 
1047  self.USERDefaultSeq='user'
1048  self.USERDefaultCFF=None
1049 
1050  # the magnetic field
1051  if self._options.isData:
1052  if self._options.magField==defaultOptions.magField:
1053  print("magnetic field option forced to: AutoFromDBCurrent")
1054  self._options.magField='AutoFromDBCurrent'
1055  self.magFieldCFF = 'Configuration/StandardSequences/MagneticField_'+self._options.magField.replace('.','')+'_cff'
1056  self.magFieldCFF = self.magFieldCFF.replace("__",'_')
1057 
1058  # the geometry
1059  self.GeometryCFF='Configuration/StandardSequences/GeometryRecoDB_cff'
1061  simGeometry=''
1062  if self._options.fast:
1063  if 'start' in self._options.conditions.lower():
1064  self.GeometryCFF='FastSimulation/Configuration/Geometries_START_cff'
1065  else:
1066  self.GeometryCFF='FastSimulation/Configuration/Geometries_MC_cff'
1067  else:
1068  def inGeometryKeys(opt):
1069  from Configuration.StandardSequences.GeometryConf import GeometryConf
1070  if opt in GeometryConf:
1071  return GeometryConf[opt]
1072  else:
1073  return opt
1074 
1075  geoms=self._options.geometry.split(',')
1076  if len(geoms)==1: geoms=inGeometryKeys(geoms[0]).split(',')
1077  if len(geoms)==2:
1078  #may specify the reco geometry
1079  if '/' in geoms[1] or '_cff' in geoms[1]:
1080  self.GeometryCFF=geoms[1]
1081  else:
1082  self.GeometryCFF='Configuration/Geometry/Geometry'+geoms[1]+'_cff'
1083 
1084  if (geoms[0].startswith('DB:')):
1085  self.SimGeometryCFF='Configuration/StandardSequences/GeometrySimDB_cff'
1086  self.geometryDBLabel=geoms[0][3:]
1087  print("with DB:")
1088  else:
1089  if '/' in geoms[0] or '_cff' in geoms[0]:
1090  self.SimGeometryCFF=geoms[0]
1091  else:
1092  simGeometry=geoms[0]
1093  if self._options.gflash==True:
1094  self.SimGeometryCFF='Configuration/Geometry/Geometry'+geoms[0]+'GFlash_cff'
1095  else:
1096  self.SimGeometryCFF='Configuration/Geometry/Geometry'+geoms[0]+'_cff'
1097 
1098  # synchronize the geometry configuration and the FullSimulation sequence to be used
1099  if simGeometry not in defaultOptions.geometryExtendedOptions:
1100  self.SIMDefaultCFF="Configuration/StandardSequences/SimIdeal_cff"
1101 
1102  if self._options.scenario=='nocoll' or self._options.scenario=='cosmics':
1103  self.SIMDefaultCFF="Configuration/StandardSequences/SimNOBEAM_cff"
1104  self._options.beamspot='NoSmear'
1105 
1106  # fastsim requires some changes to the default cff files and sequences
1107  if self._options.fast:
1108  self.SIMDefaultCFF = 'FastSimulation.Configuration.SimIdeal_cff'
1109  self.RECODefaultCFF= 'FastSimulation.Configuration.Reconstruction_AftMix_cff'
1110  self.RECOBEFMIXDefaultCFF = 'FastSimulation.Configuration.Reconstruction_BefMix_cff'
1111  self.RECOBEFMIXDefaultSeq = 'reconstruction_befmix'
1112  self.NANODefaultSeq = 'nanoSequenceFS'
1113  self.DQMOFFLINEDefaultCFF="DQMOffline.Configuration.DQMOfflineFS_cff"
1114 
1115  # Mixing
1116  if self._options.pileup=='default':
1117  from Configuration.StandardSequences.Mixing import MixingDefaultKey
1118  self._options.pileup=MixingDefaultKey
1119 
1120 
1121  #not driven by a default cff anymore
1122  if self._options.isData:
1123  self._options.pileup=None
1124 
1125 
1127 
1128  # for alca, skims, etc
1129  def addExtraStream(self,name,stream,workflow='full'):
1130  # define output module and go from there
1131  output = cms.OutputModule("PoolOutputModule")
1132  if stream.selectEvents.parameters_().__len__()!=0:
1133  output.SelectEvents = stream.selectEvents
1134  else:
1135  output.SelectEvents = cms.untracked.PSet()
1136  output.SelectEvents.SelectEvents=cms.vstring()
1137  if isinstance(stream.paths,tuple):
1138  for path in stream.paths:
1139  output.SelectEvents.SelectEvents.append(path.label())
1140  else:
1141  output.SelectEvents.SelectEvents.append(stream.paths.label())
1142 
1143 
1144 
1145  if isinstance(stream.content,str):
1146  evtPset=getattr(self.process,stream.content)
1147  for p in evtPset.parameters_():
1148  setattr(output,p,getattr(evtPset,p))
1149  if not self._options.inlineEventContent:
1150  def doNotInlineEventContent(instance,label = "process."+stream.content+".outputCommands"):
1151  return label
1152  output.outputCommands.__dict__["dumpPython"] = doNotInlineEventContent
1153  else:
1154  output.outputCommands = stream.content
1155 
1156 
1157  output.fileName = cms.untracked.string(self._options.dirout+stream.name+'.root')
1158 
1159  output.dataset = cms.untracked.PSet( dataTier = stream.dataTier,
1160  filterName = cms.untracked.string(stream.name))
1161 
1162  if self._options.filtername:
1163  output.dataset.filterName= cms.untracked.string(self._options.filtername+"_"+stream.name)
1164 
1165  #add an automatic flushing to limit memory consumption
1166  output.eventAutoFlushCompressedSize=cms.untracked.int32(5*1024*1024)
1167 
1168  if workflow in ("producers,full"):
1169  if isinstance(stream.paths,tuple):
1170  for path in stream.paths:
1171  self.schedule.append(path)
1172  else:
1173  self.schedule.append(stream.paths)
1174 
1175 
1176  # in case of relvals we don't want to have additional outputs
1177  if (not self._options.relval) and workflow in ("full","output"):
1178  self.additionalOutputs[name] = output
1179  setattr(self.process,name,output)
1180 
1181  if workflow == 'output':
1182  # adjust the select events to the proper trigger results from previous process
1183  filterList = output.SelectEvents.SelectEvents
1184  for i, filter in enumerate(filterList):
1185  filterList[i] = filter+":"+self._options.triggerResultsProcess
1186 
1187  return output
1188 
1189  #----------------------------------------------------------------------------
1190  # here the methods to create the steps. Of course we are doing magic here ;)
1191  # prepare_STEPNAME modifies self.process and what else's needed.
1192  #----------------------------------------------------------------------------
1193 
1194  def loadDefaultOrSpecifiedCFF(self, sequence,defaultCFF):
1195  if ( len(sequence.split('.'))==1 ):
1196  l=self.loadAndRemember(defaultCFF)
1197  elif ( len(sequence.split('.'))==2 ):
1198  l=self.loadAndRemember(sequence.split('.')[0])
1199  sequence=sequence.split('.')[1]
1200  else:
1201  print("sub sequence configuration must be of the form dir/subdir/cff.a+b+c or cff.a")
1202  print(sequence,"not recognized")
1203  raise
1204  return l
1205 
1206  def scheduleSequence(self,seq,prefix,what='Path'):
1207  if '*' in seq:
1208  #create only one path with all sequences in it
1209  for i,s in enumerate(seq.split('*')):
1210  if i==0:
1211  setattr(self.process,prefix,getattr(cms,what)( getattr(self.process, s) ))
1212  else:
1213  p=getattr(self.process,prefix)
1214  tmp = getattr(self.process, s)
1215  if isinstance(tmp, cms.Task):
1216  p.associate(tmp)
1217  else:
1218  p+=tmp
1219  self.schedule.append(getattr(self.process,prefix))
1220  return
1221  else:
1222  #create as many path as many sequences
1223  if not '+' in seq:
1224  if self.nextScheduleIsConditional:
1225  self.conditionalPaths.append(prefix)
1226  setattr(self.process,prefix,getattr(cms,what)( getattr(self.process, seq) ))
1227  self.schedule.append(getattr(self.process,prefix))
1228  else:
1229  for i,s in enumerate(seq.split('+')):
1230  sn=prefix+'%d'%(i)
1231  setattr(self.process,sn,getattr(cms,what)( getattr(self.process, s) ))
1232  self.schedule.append(getattr(self.process,sn))
1233  return
1234 
1235  def scheduleSequenceAtEnd(self,seq,prefix):
1236  self.scheduleSequence(seq,prefix,what='EndPath')
1237  return
1238 
1239  def prepare_ALCAPRODUCER(self, sequence = None):
1240  self.prepare_ALCA(sequence, workflow = "producers")
1241 
1242  def prepare_ALCAOUTPUT(self, sequence = None):
1243  self.prepare_ALCA(sequence, workflow = "output")
1244 
1245  def prepare_ALCA(self, sequence = None, workflow = 'full'):
1246  """ Enrich the process with alca streams """
1247  alcaConfig=self.loadDefaultOrSpecifiedCFF(sequence,self.ALCADefaultCFF)
1248  sequence = sequence.split('.')[-1]
1249 
1250  # decide which ALCA paths to use
1251  alcaList = sequence.split("+")
1252  maxLevel=0
1253  from Configuration.AlCa.autoAlca import autoAlca
1254  # support @X from autoAlca.py, and recursion support: i.e T0:@Mu+@EG+...
1255  self.expandMapping(alcaList,autoAlca)
1256  self.AlCaPaths=[]
1257  for name in alcaConfig.__dict__:
1258  alcastream = getattr(alcaConfig,name)
1259  shortName = name.replace('ALCARECOStream','')
1260  if shortName in alcaList and isinstance(alcastream,cms.FilteredStream):
1261  output = self.addExtraStream(name,alcastream, workflow = workflow)
1262  self.executeAndRemember('process.ALCARECOEventContent.outputCommands.extend(process.OutALCARECO'+shortName+'_noDrop.outputCommands)')
1263  self.AlCaPaths.append(shortName)
1264  if 'DQM' in alcaList:
1265  if not self._options.inlineEventContent and hasattr(self.process,name):
1266  self.executeAndRemember('process.' + name + '.outputCommands.append("keep *_MEtoEDMConverter_*_*")')
1267  else:
1268  output.outputCommands.append("keep *_MEtoEDMConverter_*_*")
1269 
1270  #rename the HLT process name in the alca modules
1271  if self._options.hltProcess or 'HLT' in self.stepMap:
1272  if isinstance(alcastream.paths,tuple):
1273  for path in alcastream.paths:
1274  self.renameHLTprocessInSequence(path.label())
1275  else:
1276  self.renameHLTprocessInSequence(alcastream.paths.label())
1277 
1278  for i in range(alcaList.count(shortName)):
1279  alcaList.remove(shortName)
1280 
1281  # DQM needs a special handling
1282  elif name == 'pathALCARECODQM' and 'DQM' in alcaList:
1283  path = getattr(alcaConfig,name)
1284  self.schedule.append(path)
1285  alcaList.remove('DQM')
1286 
1287  if isinstance(alcastream,cms.Path):
1288  #black list the alca path so that they do not appear in the cfg
1289  self.blacklist_paths.append(alcastream)
1290 
1291 
1292  if len(alcaList) != 0:
1293  available=[]
1294  for name in alcaConfig.__dict__:
1295  alcastream = getattr(alcaConfig,name)
1296  if isinstance(alcastream,cms.FilteredStream):
1297  available.append(name.replace('ALCARECOStream',''))
1298  print("The following alcas could not be found "+str(alcaList))
1299  print("available ",available)
1300  #print "verify your configuration, ignoring for now"
1301  raise Exception("The following alcas could not be found "+str(alcaList))
1302 
1303  def prepare_LHE(self, sequence = None):
1304  #load the fragment
1305  ##make it loadable
1306  loadFragment = self._options.evt_type.replace('.py','',).replace('.','_').replace('python/','').replace('/','.')
1307  print("Loading lhe fragment from",loadFragment)
1308  __import__(loadFragment)
1309  self.process.load(loadFragment)
1310  ##inline the modules
1311  self._options.inlineObjets+=','+sequence
1312 
1313  getattr(self.process,sequence).nEvents = int(self._options.number)
1314 
1315  #schedule it
1316  self.process.lhe_step = cms.Path( getattr( self.process,sequence) )
1317  self.excludedPaths.append("lhe_step")
1318  self.schedule.append( self.process.lhe_step )
1319 
1320  def prepare_GEN(self, sequence = None):
1321  """ load the fragment of generator configuration """
1322  loadFailure=False
1323  #remove trailing .py
1324  #support old style .cfi by changing into something.cfi into something_cfi
1325  #remove python/ from the name
1326  loadFragment = self._options.evt_type.replace('.py','',).replace('.','_').replace('python/','')
1327  #standard location of fragments
1328  if not '/' in loadFragment:
1329  loadFragment='Configuration.Generator.'+loadFragment
1330  else:
1331  loadFragment=loadFragment.replace('/','.')
1332  try:
1333  print("Loading generator fragment from",loadFragment)
1334  __import__(loadFragment)
1335  except:
1336  loadFailure=True
1337  #if self.process.source and self.process.source.type_()=='EmptySource':
1338  if not (self._options.filein or self._options.dasquery):
1339  raise Exception("Neither gen fragment of input files provided: this is an inconsistent GEN step configuration")
1340 
1341  if not loadFailure:
1342  generatorModule=sys.modules[loadFragment]
1343  genModules=generatorModule.__dict__
1344  #remove lhe producer module since this should have been
1345  #imported instead in the LHE step
1346  if self.LHEDefaultSeq in genModules:
1347  del genModules[self.LHEDefaultSeq]
1348 
1349  if self._options.hideGen:
1350  self.loadAndRemember(loadFragment)
1351  else:
1352  self.process.load(loadFragment)
1353  # expose the objects from that fragment to the configuration
1354  import FWCore.ParameterSet.Modules as cmstypes
1355  for name in genModules:
1356  theObject = getattr(generatorModule,name)
1357  if isinstance(theObject, cmstypes._Module):
1358  self._options.inlineObjets=name+','+self._options.inlineObjets
1359  elif isinstance(theObject, cms.Sequence) or isinstance(theObject, cmstypes.ESProducer):
1360  self._options.inlineObjets+=','+name
1361 
1362  if sequence == self.GENDefaultSeq or sequence == 'pgen_genonly':
1363  if 'ProductionFilterSequence' in genModules and ('generator' in genModules):
1364  self.productionFilterSequence = 'ProductionFilterSequence'
1365  elif 'generator' in genModules:
1366  self.productionFilterSequence = 'generator'
1367 
1368  """ Enrich the schedule with the rest of the generation step """
1369  self.loadDefaultOrSpecifiedCFF(sequence,self.GENDefaultCFF)
1370  genSeqName=sequence.split('.')[-1]
1371 
1372  if True:
1373  try:
1374  from Configuration.StandardSequences.VtxSmeared import VtxSmeared
1375  cffToBeLoaded=VtxSmeared[self._options.beamspot]
1376  self.loadAndRemember(cffToBeLoaded)
1377  except ImportError:
1378  raise Exception("VertexSmearing type or beamspot "+self._options.beamspot+" unknown.")
1379 
1380  if self._options.scenario == 'HeavyIons':
1381  if self._options.pileup=='HiMixGEN':
1382  self.loadAndRemember("Configuration/StandardSequences/GeneratorMix_cff")
1383  else:
1384  self.loadAndRemember("Configuration/StandardSequences/GeneratorHI_cff")
1385 
1386  self.process.generation_step = cms.Path( getattr(self.process,genSeqName) )
1387  self.schedule.append(self.process.generation_step)
1388 
1389  #register to the genstepfilter the name of the path (static right now, but might evolve)
1390  self.executeAndRemember('process.genstepfilter.triggerConditions=cms.vstring("generation_step")')
1391 
1392  if 'reGEN' in self.stepMap:
1393  #stop here
1394  return
1395 
1396  """ Enrich the schedule with the summary of the filter step """
1397  #the gen filter in the endpath
1398  self.loadAndRemember("GeneratorInterface/Core/genFilterSummary_cff")
1399  self.scheduleSequenceAtEnd('genFilterSummary','genfiltersummary_step')
1400  return
1401 
1402  def prepare_SIM(self, sequence = None):
1403  """ Enrich the schedule with the simulation step"""
1404  self.loadDefaultOrSpecifiedCFF(sequence,self.SIMDefaultCFF)
1405  if not self._options.fast:
1406  if self._options.gflash==True:
1407  self.loadAndRemember("Configuration/StandardSequences/GFlashSIM_cff")
1408 
1409  if self._options.magField=='0T':
1410  self.executeAndRemember("process.g4SimHits.UseMagneticField = cms.bool(False)")
1411  else:
1412  if self._options.magField=='0T':
1413  self.executeAndRemember("process.fastSimProducer.detectorDefinition.magneticFieldZ = cms.untracked.double(0.)")
1414 
1415  self.scheduleSequence(sequence.split('.')[-1],'simulation_step')
1416  return
1417 
1418  def prepare_DIGI(self, sequence = None):
1419  """ Enrich the schedule with the digitisation step"""
1420  self.loadDefaultOrSpecifiedCFF(sequence,self.DIGIDefaultCFF)
1421 
1422  if self._options.gflash==True:
1423  self.loadAndRemember("Configuration/StandardSequences/GFlashDIGI_cff")
1424 
1425  if sequence == 'pdigi_valid' or sequence == 'pdigi_hi':
1426  self.executeAndRemember("process.mix.digitizers = cms.PSet(process.theDigitizersValid)")
1427 
1428  if sequence != 'pdigi_nogen' and sequence != 'pdigi_valid_nogen' and sequence != 'pdigi_hi_nogen' and not self.process.source.type_()=='EmptySource':
1429  if self._options.inputEventContent=='':
1430  self._options.inputEventContent='REGEN'
1431  else:
1432  self._options.inputEventContent=self._options.inputEventContent+',REGEN'
1433 
1434 
1435  self.scheduleSequence(sequence.split('.')[-1],'digitisation_step')
1436  return
1437 
1438  def prepare_CFWRITER(self, sequence = None):
1439  """ Enrich the schedule with the crossing frame writer step"""
1441  self.scheduleSequence('pcfw','cfwriter_step')
1442  return
1443 
1444  def prepare_DATAMIX(self, sequence = None):
1445  """ Enrich the schedule with the digitisation step"""
1447  self.scheduleSequence('pdatamix','datamixing_step')
1448 
1449  if self._options.pileup_input:
1450  theFiles=''
1451  if self._options.pileup_input.startswith('dbs:') or self._options.pileup_input.startswith('das:'):
1452  theFiles=filesFromDASQuery('file dataset = %s'%(self._options.pileup_input[4:],),self._options.pileup_dasoption)[0]
1453  elif self._options.pileup_input.startswith("filelist:"):
1454  theFiles= (filesFromList(self._options.pileup_input[9:]))[0]
1455  else:
1456  theFiles=self._options.pileup_input.split(',')
1457  #print theFiles
1458  self.executeAndRemember( "process.mixData.input.fileNames = cms.untracked.vstring(%s)"%( theFiles ) )
1459 
1460  return
1461 
1462  def prepare_DIGI2RAW(self, sequence = None):
1463  self.loadDefaultOrSpecifiedCFF(sequence,self.DIGI2RAWDefaultCFF)
1464  self.scheduleSequence(sequence.split('.')[-1],'digi2raw_step')
1465  return
1466 
1467  def prepare_REPACK(self, sequence = None):
1468  self.loadDefaultOrSpecifiedCFF(sequence,self.REPACKDefaultCFF)
1469  self.scheduleSequence(sequence.split('.')[-1],'digi2repack_step')
1470  return
1471 
1472  def prepare_L1(self, sequence = None):
1473  """ Enrich the schedule with the L1 simulation step"""
1474  assert(sequence == None)
1475  self.loadAndRemember(self.L1EMDefaultCFF)
1476  self.scheduleSequence('SimL1Emulator','L1simulation_step')
1477  return
1478 
1479  def prepare_L1REPACK(self, sequence = None):
1480  """ Enrich the schedule with the L1 simulation step, running the L1 emulator on data unpacked from the RAW collection, and repacking the result in a new RAW collection"""
1481  supported = ['GT','GT1','GT2','GCTGT','Full','FullSimTP','FullMC','Full2015Data','uGT','CalouGT']
1482  if sequence in supported:
1483  self.loadAndRemember('Configuration/StandardSequences/SimL1EmulatorRepack_%s_cff'%sequence)
1484  if self._options.scenario == 'HeavyIons':
1485  self.renameInputTagsInSequence("SimL1Emulator","rawDataCollector","rawDataRepacker")
1486  self.scheduleSequence('SimL1Emulator','L1RePack_step')
1487  else:
1488  print("L1REPACK with '",sequence,"' is not supported! Supported choices are: ",supported)
1489  raise Exception('unsupported feature')
1490 
1491 
1492  def prepare_HLT(self, sequence = None):
1493  """ Enrich the schedule with the HLT simulation step"""
1494  if not sequence:
1495  print("no specification of the hlt menu has been given, should never happen")
1496  raise Exception('no HLT sequence provided')
1497 
1498  if '@' in sequence:
1499  # case where HLT:@something was provided
1500  from Configuration.HLT.autoHLT import autoHLT
1501  key = sequence[1:]
1502  if key in autoHLT:
1503  sequence = autoHLT[key]
1504  else:
1505  raise ValueError('no HLT mapping key "%s" found in autoHLT' % key)
1506 
1507  if ',' in sequence:
1508  #case where HLT:something:something was provided
1509  self.executeAndRemember('import HLTrigger.Configuration.Utilities')
1510  optionsForHLT = {}
1511  if self._options.scenario == 'HeavyIons':
1512  optionsForHLT['type'] = 'HIon'
1513  else:
1514  optionsForHLT['type'] = 'GRun'
1515  optionsForHLTConfig = ', '.join('%s=%s' % (key, repr(val)) for (key, val) in six.iteritems(optionsForHLT))
1516  if sequence == 'run,fromSource':
1517  if hasattr(self.process.source,'firstRun'):
1518  self.executeAndRemember('process.loadHltConfiguration("run:%%d"%%(process.source.firstRun.value()),%s)'%(optionsForHLTConfig))
1519  elif hasattr(self.process.source,'setRunNumber'):
1520  self.executeAndRemember('process.loadHltConfiguration("run:%%d"%%(process.source.setRunNumber.value()),%s)'%(optionsForHLTConfig))
1521  else:
1522  raise Exception('Cannot replace menu to load %s'%(sequence))
1523  else:
1524  self.executeAndRemember('process.loadHltConfiguration("%s",%s)'%(sequence.replace(',',':'),optionsForHLTConfig))
1525  else:
1526  self.loadAndRemember('HLTrigger/Configuration/HLT_%s_cff' % sequence)
1527 
1528  if self._options.isMC:
1529  self._options.customisation_file.append("HLTrigger/Configuration/customizeHLTforMC.customizeHLTforMC")
1530 
1531  if self._options.name != 'HLT':
1532  self.additionalCommands.append('from HLTrigger.Configuration.CustomConfigs import ProcessName')
1533  self.additionalCommands.append('process = ProcessName(process)')
1534  self.additionalCommands.append('')
1535  from HLTrigger.Configuration.CustomConfigs import ProcessName
1536  self.process = ProcessName(self.process)
1537 
1538  self.schedule.append(self.process.HLTSchedule)
1539  [self.blacklist_paths.append(path) for path in self.process.HLTSchedule if isinstance(path,(cms.Path,cms.EndPath))]
1540 
1541  #this is a fake, to be removed with fastim migration and HLT menu dump
1542  if self._options.fast:
1543  if not hasattr(self.process,'HLTEndSequence'):
1544  self.executeAndRemember("process.HLTEndSequence = cms.Sequence( process.dummyModule )")
1545 
1546 
1547  def prepare_RAW2RECO(self, sequence = None):
1548  if ','in sequence:
1549  seqReco=sequence.split(',')[1]
1550  seqDigi=sequence.split(',')[0]
1551  else:
1552  print("RAW2RECO requires two specifications",sequence,"insufficient")
1553 
1554  self.prepare_RAW2DIGI(seqDigi)
1555  self.prepare_RECO(seqReco)
1556  return
1557 
1558  def prepare_RAW2DIGI(self, sequence = "RawToDigi"):
1559  self.loadDefaultOrSpecifiedCFF(sequence,self.RAW2DIGIDefaultCFF)
1560  self.scheduleSequence(sequence,'raw2digi_step')
1561  # if self._options.isRepacked:
1562  #self.renameInputTagsInSequence(sequence)
1563  return
1564 
1565  def prepare_PATFILTER(self, sequence=None):
1566  self.loadAndRemember("PhysicsTools/PatAlgos/slimming/metFilterPaths_cff")
1567  from PhysicsTools.PatAlgos.slimming.metFilterPaths_cff import allMetFilterPaths
1568  for filt in allMetFilterPaths:
1569  self.schedule.append(getattr(self.process,'Flag_'+filt))
1570 
1571  def prepare_L1HwVal(self, sequence = 'L1HwVal'):
1572  ''' Enrich the schedule with L1 HW validation '''
1573  self.loadDefaultOrSpecifiedCFF(sequence,self.L1HwValDefaultCFF)
1574  #self.scheduleSequence(sequence.split('.')[-1],'l1hwval_step')
1575  print('\n\n\n DEPRECATED this has no action \n\n\n')
1576  return
1577 
1578  def prepare_L1Reco(self, sequence = "L1Reco"):
1579  ''' Enrich the schedule with L1 reconstruction '''
1580  self.loadDefaultOrSpecifiedCFF(sequence,self.L1RecoDefaultCFF)
1581  self.scheduleSequence(sequence.split('.')[-1],'L1Reco_step')
1582  return
1583 
1584  def prepare_L1TrackTrigger(self, sequence = "L1TrackTrigger"):
1585  ''' Enrich the schedule with L1 reconstruction '''
1587  self.scheduleSequence(sequence.split('.')[-1],'L1TrackTrigger_step')
1588  return
1589 
1590  def prepare_FILTER(self, sequence = None):
1591  ''' Enrich the schedule with a user defined filter sequence '''
1592  ## load the relevant part
1593  filterConfig=self.load(sequence.split('.')[0])
1594  filterSeq=sequence.split('.')[-1]
1595  ## print it in the configuration
1596  class PrintAllModules(object):
1597  def __init__(self):
1598  self.inliner=''
1599  pass
1600  def enter(self,visitee):
1601  try:
1602  label=visitee.label()
1603  ##needs to be in reverse order
1604  self.inliner=label+','+self.inliner
1605  except:
1606  pass
1607  def leave(self,v): pass
1608 
1609  expander=PrintAllModules()
1610  getattr(self.process,filterSeq).visit( expander )
1611  self._options.inlineObjets+=','+expander.inliner
1612  self._options.inlineObjets+=','+filterSeq
1613 
1614  ## put the filtering path in the schedule
1615  self.scheduleSequence(filterSeq,'filtering_step')
1616  self.nextScheduleIsConditional=True
1617  ## put it before all the other paths
1618  self.productionFilterSequence = filterSeq
1619 
1620  return
1621 
1622  def prepare_RECO(self, sequence = "reconstruction"):
1623  ''' Enrich the schedule with reconstruction '''
1624  self.loadDefaultOrSpecifiedCFF(sequence,self.RECODefaultCFF)
1625  self.scheduleSequence(sequence.split('.')[-1],'reconstruction_step')
1626  return
1627 
1628  def prepare_RECOSIM(self, sequence = "recosim"):
1629  ''' Enrich the schedule with reconstruction '''
1630  self.loadDefaultOrSpecifiedCFF(sequence,self.RECOSIMDefaultCFF)
1631  self.scheduleSequence(sequence.split('.')[-1],'recosim_step')
1632  return
1633 
1634  def prepare_RECOBEFMIX(self, sequence = "reconstruction"):
1635  ''' Enrich the schedule with the part of reconstruction that is done before mixing in FastSim'''
1636  if not self._options.fast:
1637  print("ERROR: this step is only implemented for FastSim")
1638  sys.exit()
1640  self.scheduleSequence(sequence.split('.')[-1],'reconstruction_befmix_step')
1641  return
1642 
1643  def prepare_PAT(self, sequence = "miniAOD"):
1644  ''' Enrich the schedule with PAT '''
1645  self.prepare_PATFILTER(self)
1646  self.loadDefaultOrSpecifiedCFF(sequence,self.PATDefaultCFF)
1647  self.labelsToAssociate.append('patTask')
1648  if not self._options.runUnscheduled:
1649  raise Exception("MiniAOD production can only run in unscheduled mode, please run cmsDriver with --runUnscheduled")
1650  if self._options.isData:
1651  self._options.customisation_file_unsch.insert(0,"PhysicsTools/PatAlgos/slimming/miniAOD_tools.miniAOD_customizeAllData")
1652  else:
1653  if self._options.fast:
1654  self._options.customisation_file_unsch.insert(0,"PhysicsTools/PatAlgos/slimming/miniAOD_tools.miniAOD_customizeAllMCFastSim")
1655  else:
1656  self._options.customisation_file_unsch.insert(0,"PhysicsTools/PatAlgos/slimming/miniAOD_tools.miniAOD_customizeAllMC")
1657 
1658  if self._options.hltProcess:
1659  if len(self._options.customise_commands) > 1:
1660  self._options.customise_commands = self._options.customise_commands + " \n"
1661  self._options.customise_commands = self._options.customise_commands + "process.patTrigger.processName = \""+self._options.hltProcess+"\"\n"
1662  self._options.customise_commands = self._options.customise_commands + "process.slimmedPatTrigger.triggerResults= cms.InputTag( 'TriggerResults::"+self._options.hltProcess+"' )\n"
1663  self._options.customise_commands = self._options.customise_commands + "process.patMuons.triggerResults= cms.InputTag( 'TriggerResults::"+self._options.hltProcess+"' )\n"
1664 
1665 # self.renameHLTprocessInSequence(sequence)
1666 
1667  return
1668 
1669  def prepare_PATGEN(self, sequence = "miniGEN"):
1670  ''' Enrich the schedule with PATGEN '''
1671  self.loadDefaultOrSpecifiedCFF(sequence,self.PATGENDefaultCFF) #this is unscheduled
1672  self.labelsToAssociate.append('patGENTask')
1673  if not self._options.runUnscheduled:
1674  raise Exception("MiniGEN production can only run in unscheduled mode, please run cmsDriver with --runUnscheduled")
1675  if self._options.isData:
1676  raise Exception("PATGEN step can only run on MC")
1677  return
1678 
1679  def prepare_NANO(self, sequence = "nanoAOD"):
1680  ''' Enrich the schedule with NANO '''
1681  self.loadDefaultOrSpecifiedCFF(sequence,self.NANODefaultCFF)
1682  self.scheduleSequence(sequence.split('.')[-1],'nanoAOD_step')
1683  custom = "nanoAOD_customizeData" if self._options.isData else "nanoAOD_customizeMC"
1684  if self._options.runUnscheduled:
1685  self._options.customisation_file_unsch.insert(0,"PhysicsTools/NanoAOD/nano_cff."+custom)
1686  else:
1687  self._options.customisation_file.insert(0,"PhysicsTools/NanoAOD/nano_cff."+custom)
1688  if self._options.hltProcess:
1689  if len(self._options.customise_commands) > 1:
1690  self._options.customise_commands = self._options.customise_commands + " \n"
1691  self._options.customise_commands = self._options.customise_commands + "process.unpackedPatTrigger.triggerResults= cms.InputTag( 'TriggerResults::"+self._options.hltProcess+"' )\n"
1692 
1693 
1694  def prepare_EI(self, sequence = None):
1695  ''' Enrich the schedule with event interpretation '''
1696  from Configuration.StandardSequences.EventInterpretation import EventInterpretation
1697  if sequence in EventInterpretation:
1698  self.EIDefaultCFF = EventInterpretation[sequence]
1699  sequence = 'EIsequence'
1700  else:
1701  raise Exception('Cannot set %s event interpretation'%( sequence) )
1702  self.loadDefaultOrSpecifiedCFF(sequence,self.EIDefaultCFF)
1703  self.scheduleSequence(sequence.split('.')[-1],'eventinterpretaion_step')
1704  return
1705 
1706  def prepare_SKIM(self, sequence = "all"):
1707  ''' Enrich the schedule with skimming fragments'''
1708  skimConfig = self.loadDefaultOrSpecifiedCFF(sequence,self.SKIMDefaultCFF)
1709  sequence = sequence.split('.')[-1]
1710 
1711  skimlist=sequence.split('+')
1712  ## support @Mu+DiJet+@Electron configuration via autoSkim.py
1713  from Configuration.Skimming.autoSkim import autoSkim
1714  self.expandMapping(skimlist,autoSkim)
1715 
1716  #print "dictionnary for skims:",skimConfig.__dict__
1717  for skim in skimConfig.__dict__:
1718  skimstream = getattr(skimConfig,skim)
1719  if isinstance(skimstream,cms.Path):
1720  #black list the alca path so that they do not appear in the cfg
1721  self.blacklist_paths.append(skimstream)
1722  if (not isinstance(skimstream,cms.FilteredStream)):
1723  continue
1724  shortname = skim.replace('SKIMStream','')
1725  if (sequence=="all"):
1726  self.addExtraStream(skim,skimstream)
1727  elif (shortname in skimlist):
1728  self.addExtraStream(skim,skimstream)
1729  #add a DQM eventcontent for this guy
1730  if self._options.datatier=='DQM':
1731  self.process.load(self.EVTCONTDefaultCFF)
1732  skimstreamDQM = cms.FilteredStream(
1733  responsible = skimstream.responsible,
1734  name = skimstream.name+'DQM',
1735  paths = skimstream.paths,
1736  selectEvents = skimstream.selectEvents,
1737  content = self._options.datatier+'EventContent',
1738  dataTier = cms.untracked.string(self._options.datatier)
1739  )
1740  self.addExtraStream(skim+'DQM',skimstreamDQM)
1741  for i in range(skimlist.count(shortname)):
1742  skimlist.remove(shortname)
1743 
1744 
1745 
1746  if (skimlist.__len__()!=0 and sequence!="all"):
1747  print('WARNING, possible typo with SKIM:'+'+'.join(skimlist))
1748  raise Exception('WARNING, possible typo with SKIM:'+'+'.join(skimlist))
1749 
1750  def prepare_USER(self, sequence = None):
1751  ''' Enrich the schedule with a user defined sequence '''
1752  self.loadDefaultOrSpecifiedCFF(sequence,self.USERDefaultCFF)
1753  self.scheduleSequence(sequence.split('.')[-1],'user_step')
1754  return
1755 
1756  def prepare_POSTRECO(self, sequence = None):
1757  """ Enrich the schedule with the postreco step """
1759  self.scheduleSequence('postreco_generator','postreco_step')
1760  return
1761 
1762 
1763  def prepare_VALIDATION(self, sequence = 'validation'):
1764  print(sequence,"in preparing validation")
1766  from Validation.Configuration.autoValidation import autoValidation
1767  #in case VALIDATION:something:somethingelse -> something,somethingelse
1768  sequence=sequence.split('.')[-1]
1769  if sequence.find(',')!=-1:
1770  prevalSeqName=sequence.split(',')[0].split('+')
1771  valSeqName=sequence.split(',')[1].split('+')
1772  self.expandMapping(prevalSeqName,autoValidation,index=0)
1773  self.expandMapping(valSeqName,autoValidation,index=1)
1774  else:
1775  if '@' in sequence:
1776  prevalSeqName=sequence.split('+')
1777  valSeqName=sequence.split('+')
1778  self.expandMapping(prevalSeqName,autoValidation,index=0)
1779  self.expandMapping(valSeqName,autoValidation,index=1)
1780  else:
1781  postfix=''
1782  if sequence:
1783  postfix='_'+sequence
1784  prevalSeqName=['prevalidation'+postfix]
1785  valSeqName=['validation'+postfix]
1786  if not hasattr(self.process,valSeqName[0]):
1787  prevalSeqName=['']
1788  valSeqName=[sequence]
1789 
1790  def NFI(index):
1791  ##name from index, required to keep backward compatibility
1792  if index==0:
1793  return ''
1794  else:
1795  return '%s'%index
1796 
1797 
1798  #rename the HLT process in validation steps
1799  if ('HLT' in self.stepMap and not self._options.fast) or self._options.hltProcess:
1800  for s in valSeqName+prevalSeqName:
1801  if s:
1803  for (i,s) in enumerate(prevalSeqName):
1804  if s:
1805  setattr(self.process,'prevalidation_step%s'%NFI(i), cms.Path( getattr(self.process, s)) )
1806  self.schedule.append(getattr(self.process,'prevalidation_step%s'%NFI(i)))
1807 
1808  for (i,s) in enumerate(valSeqName):
1809  setattr(self.process,'validation_step%s'%NFI(i), cms.EndPath( getattr(self.process, s)))
1810  self.schedule.append(getattr(self.process,'validation_step%s'%NFI(i)))
1811 
1812  #needed in case the miniAODValidation sequence is run starting from AODSIM
1813  if 'PAT' in self.stepMap and not 'RECO' in self.stepMap:
1814  return
1815 
1816  if not 'DIGI' in self.stepMap and not self._options.fast and not any(map( lambda s : s.startswith('genvalid'), valSeqName)):
1817  if self._options.restoreRNDSeeds==False and not self._options.restoreRNDSeeds==True:
1818  self._options.restoreRNDSeeds=True
1819 
1820  if not 'DIGI' in self.stepMap and not self._options.fast:
1821  self.executeAndRemember("process.mix.playback = True")
1822  self.executeAndRemember("process.mix.digitizers = cms.PSet()")
1823  self.executeAndRemember("for a in process.aliases: delattr(process, a)")
1824  self._options.customisation_file.append("SimGeneral/MixingModule/fullMixCustomize_cff.setCrossingFrameOn")
1825 
1826  if hasattr(self.process,"genstepfilter") and len(self.process.genstepfilter.triggerConditions):
1827  #will get in the schedule, smoothly
1828  for (i,s) in enumerate(valSeqName):
1829  getattr(self.process,'validation_step%s'%NFI(i)).insert(0, self.process.genstepfilter)
1830 
1831  return
1832 
1833 
1835  """Visitor that travels within a cms.Sequence, looks for a parameter and replace its value
1836  It will climb down within PSets, VPSets and VInputTags to find its target"""
1837  def __init__(self, paramSearch, paramReplace, verbose=False, whitelist=()):
1838  self._paramReplace = paramReplace
1839  self._paramSearch = paramSearch
1840  self._verbose = verbose
1841  self._whitelist = whitelist
1842 
1843  def doIt(self,pset,base):
1844  if isinstance(pset, cms._Parameterizable):
1845  for name in pset.parameters_().keys():
1846  # skip whitelisted parameters
1847  if name in self._whitelist:
1848  continue
1849  # if I use pset.parameters_().items() I get copies of the parameter values
1850  # so I can't modify the nested pset
1851  value = getattr(pset,name)
1852  type = value.pythonTypeName()
1853  if type in ('cms.PSet', 'cms.untracked.PSet'):
1854  self.doIt(value,base+"."+name)
1855  elif type in ('cms.VPSet', 'cms.untracked.VPSet'):
1856  for (i,ps) in enumerate(value): self.doIt(ps, "%s.%s[%d]"%(base,name,i) )
1857  elif type in ('cms.string', 'cms.untracked.string'):
1858  if value.value() == self._paramSearch:
1859  if self._verbose: print("set string process name %s.%s %s ==> %s"% (base, name, value, self._paramReplace))
1860  setattr(pset, name,self._paramReplace)
1861  elif type in ('cms.VInputTag', 'cms.untracked.VInputTag'):
1862  for (i,n) in enumerate(value):
1863  if not isinstance(n, cms.InputTag):
1864  n=cms.InputTag(n)
1865  if n.processName == self._paramSearch:
1866  # VInputTag can be declared as a list of strings, so ensure that n is formatted correctly
1867  if self._verbose:print("set process name %s.%s[%d] %s ==> %s " % (base, name, i, n, self._paramReplace))
1868  setattr(n,"processName",self._paramReplace)
1869  value[i]=n
1870  elif type in ('cms.vstring', 'cms.untracked.vstring'):
1871  for (i,n) in enumerate(value):
1872  if n==self._paramSearch:
1873  getattr(pset,name)[i]=self._paramReplace
1874  elif type in ('cms.InputTag', 'cms.untracked.InputTag'):
1875  if value.processName == self._paramSearch:
1876  if self._verbose: print("set process name %s.%s %s ==> %s " % (base, name, value, self._paramReplace))
1877  setattr(getattr(pset, name),"processName",self._paramReplace)
1878 
1879  def enter(self,visitee):
1880  label = ''
1881  try:
1882  label = visitee.label()
1883  except AttributeError:
1884  label = '<Module not in a Process>'
1885  except:
1886  label = 'other execption'
1887  self.doIt(visitee, label)
1888 
1889  def leave(self,visitee):
1890  pass
1891 
1892  #visit a sequence to repalce all input tags
1893  def renameInputTagsInSequence(self,sequence,oldT="rawDataCollector",newT="rawDataRepacker"):
1894  print("Replacing all InputTag %s => %s"%(oldT,newT))
1895  from PhysicsTools.PatAlgos.tools.helpers import massSearchReplaceAnyInputTag
1896  massSearchReplaceAnyInputTag(getattr(self.process,sequence),oldT,newT)
1897  loadMe='from PhysicsTools.PatAlgos.tools.helpers import massSearchReplaceAnyInputTag'
1898  if not loadMe in self.additionalCommands:
1899  self.additionalCommands.append(loadMe)
1900  self.additionalCommands.append('massSearchReplaceAnyInputTag(process.%s,"%s","%s",False,True)'%(sequence,oldT,newT))
1901 
1902  #change the process name used to address HLT results in any sequence
1903  def renameHLTprocessInSequence(self,sequence,proc=None,HLTprocess='HLT'):
1904  if self._options.hltProcess:
1905  proc=self._options.hltProcess
1906  else:
1907  proc=self.process.name_()
1908  if proc==HLTprocess: return
1909  # look up all module in dqm sequence
1910  print("replacing %s process name - sequence %s will use '%s'" % (HLTprocess,sequence, proc))
1911  getattr(self.process,sequence).visit(ConfigBuilder.MassSearchReplaceProcessNameVisitor(HLTprocess,proc,whitelist = ("subSystemFolder",)))
1912  if 'from Configuration.Applications.ConfigBuilder import ConfigBuilder' not in self.additionalCommands:
1913  self.additionalCommands.append('from Configuration.Applications.ConfigBuilder import ConfigBuilder')
1914  self.additionalCommands.append('process.%s.visit(ConfigBuilder.MassSearchReplaceProcessNameVisitor("%s", "%s", whitelist = ("subSystemFolder",)))'% (sequence,HLTprocess, proc))
1915 
1916 
1917  def expandMapping(self,seqList,mapping,index=None):
1918  maxLevel=30
1919  level=0
1920  while '@' in repr(seqList) and level<maxLevel:
1921  level+=1
1922  for specifiedCommand in seqList:
1923  if specifiedCommand.startswith('@'):
1924  location=specifiedCommand[1:]
1925  if not location in mapping:
1926  raise Exception("Impossible to map "+location+" from "+repr(mapping))
1927  mappedTo=mapping[location]
1928  if index!=None:
1929  mappedTo=mappedTo[index]
1930  seqList.remove(specifiedCommand)
1931  seqList.extend(mappedTo.split('+'))
1932  break;
1933  if level==maxLevel:
1934  raise Exception("Could not fully expand "+repr(seqList)+" from "+repr(mapping))
1935 
1936  def prepare_DQM(self, sequence = 'DQMOffline'):
1937  # this one needs replacement
1938 
1939  # any 'DQM' job should use DQMStore in non-legacy mode (but not HARVESTING)
1940  self.loadAndRemember("DQMServices/Core/DQMStoreNonLegacy_cff")
1942  sequenceList=sequence.split('.')[-1].split('+')
1943  postSequenceList=sequence.split('.')[-1].split('+')
1944  from DQMOffline.Configuration.autoDQM import autoDQM
1945  self.expandMapping(sequenceList,autoDQM,index=0)
1946  self.expandMapping(postSequenceList,autoDQM,index=1)
1947 
1948  if len(set(sequenceList))!=len(sequenceList):
1949  sequenceList=list(set(sequenceList))
1950  print("Duplicate entries for DQM:, using",sequenceList)
1951 
1952  pathName='dqmoffline_step'
1953  for (i,sequence) in enumerate(sequenceList):
1954  if (i!=0):
1955  pathName='dqmoffline_%d_step'%(i)
1956 
1957  if 'HLT' in self.stepMap.keys() or self._options.hltProcess:
1958  self.renameHLTprocessInSequence(sequence)
1959 
1960  setattr(self.process,pathName, cms.EndPath( getattr(self.process,sequence ) ) )
1961  self.schedule.append(getattr(self.process,pathName))
1962 
1963  if hasattr(self.process,"genstepfilter") and len(self.process.genstepfilter.triggerConditions):
1964  #will get in the schedule, smoothly
1965  getattr(self.process,pathName).insert(0,self.process.genstepfilter)
1966 
1967 
1968  pathName='dqmofflineOnPAT_step'
1969  for (i,sequence) in enumerate(postSequenceList):
1970  #Fix needed to avoid duplication of sequences not defined in autoDQM or without a PostDQM
1971  if (sequenceList[i]==postSequenceList[i]):
1972  continue
1973  if (i!=0):
1974  pathName='dqmofflineOnPAT_%d_step'%(i)
1975 
1976  setattr(self.process,pathName, cms.EndPath( getattr(self.process, sequence ) ) )
1977  self.schedule.append(getattr(self.process,pathName))
1978 
1979  def prepare_HARVESTING(self, sequence = None):
1980  """ Enrich the process with harvesting step """
1981  self.DQMSaverCFF='Configuration/StandardSequences/DQMSaver'+self._options.harvesting+'_cff'
1982  self.loadAndRemember(self.DQMSaverCFF)
1983 
1984  harvestingConfig = self.loadDefaultOrSpecifiedCFF(sequence,self.HARVESTINGDefaultCFF)
1985  sequence = sequence.split('.')[-1]
1986 
1987  # decide which HARVESTING paths to use
1988  harvestingList = sequence.split("+")
1989  from DQMOffline.Configuration.autoDQM import autoDQM
1990  from Validation.Configuration.autoValidation import autoValidation
1991  import copy
1992  combined_mapping = copy.deepcopy( autoDQM )
1993  combined_mapping.update( autoValidation )
1994  self.expandMapping(harvestingList,combined_mapping,index=-1)
1995 
1996  if len(set(harvestingList))!=len(harvestingList):
1997  harvestingList=list(set(harvestingList))
1998  print("Duplicate entries for HARVESTING, using",harvestingList)
1999 
2000  for name in harvestingList:
2001  if not name in harvestingConfig.__dict__:
2002  print(name,"is not a possible harvesting type. Available are",harvestingConfig.__dict__.keys())
2003  continue
2004  harvestingstream = getattr(harvestingConfig,name)
2005  if isinstance(harvestingstream,cms.Path):
2006  self.schedule.append(harvestingstream)
2007  self.blacklist_paths.append(harvestingstream)
2008  if isinstance(harvestingstream,cms.Sequence):
2009  setattr(self.process,name+"_step",cms.Path(harvestingstream))
2010  self.schedule.append(getattr(self.process,name+"_step"))
2011 
2012  self.scheduleSequence('DQMSaver','dqmsave_step')
2013  return
2014 
2015  def prepare_ALCAHARVEST(self, sequence = None):
2016  """ Enrich the process with AlCaHarvesting step """
2017  harvestingConfig = self.loadAndRemember(self.ALCAHARVESTDefaultCFF)
2018  sequence=sequence.split(".")[-1]
2019 
2020  # decide which AlcaHARVESTING paths to use
2021  harvestingList = sequence.split("+")
2022 
2023 
2024 
2025  from Configuration.AlCa.autoPCL import autoPCL
2026  self.expandMapping(harvestingList,autoPCL)
2027 
2028  for name in harvestingConfig.__dict__:
2029  harvestingstream = getattr(harvestingConfig,name)
2030  if name in harvestingList and isinstance(harvestingstream,cms.Path):
2031  self.schedule.append(harvestingstream)
2032  if isinstance(getattr(harvestingConfig,"ALCAHARVEST" + name + "_dbOutput"), cms.VPSet) and \
2033  isinstance(getattr(harvestingConfig,"ALCAHARVEST" + name + "_metadata"), cms.VPSet):
2034  self.executeAndRemember("process.PoolDBOutputService.toPut.extend(process.ALCAHARVEST" + name + "_dbOutput)")
2035  self.executeAndRemember("process.pclMetadataWriter.recordsToMap.extend(process.ALCAHARVEST" + name + "_metadata)")
2036  else:
2037  self.executeAndRemember("process.PoolDBOutputService.toPut.append(process.ALCAHARVEST" + name + "_dbOutput)")
2038  self.executeAndRemember("process.pclMetadataWriter.recordsToMap.append(process.ALCAHARVEST" + name + "_metadata)")
2039  harvestingList.remove(name)
2040  # append the common part at the end of the sequence
2041  lastStep = getattr(harvestingConfig,"ALCAHARVESTDQMSaveAndMetadataWriter")
2042  self.schedule.append(lastStep)
2043 
2044  if len(harvestingList) != 0 and 'dummyHarvesting' not in harvestingList :
2045  print("The following harvesting could not be found : ", harvestingList)
2046  raise Exception("The following harvesting could not be found : "+str(harvestingList))
2047 
2048 
2049 
2050  def prepare_ENDJOB(self, sequence = 'endOfProcess'):
2051  self.loadDefaultOrSpecifiedCFF(sequence,self.ENDJOBDefaultCFF)
2052  self.scheduleSequenceAtEnd(sequence.split('.')[-1],'endjob_step')
2053  return
2054 
2056  self.process.reconstruction = cms.Path(self.process.reconstructionWithFamos)
2057  self.schedule.append(self.process.reconstruction)
2058 
2059 
2060  def build_production_info(self, evt_type, evtnumber):
2061  """ Add useful info for the production. """
2062  self.process.configurationMetadata=cms.untracked.PSet\
2063  (version=cms.untracked.string("$Revision: 1.19 $"),
2064  name=cms.untracked.string("Applications"),
2065  annotation=cms.untracked.string(evt_type+ " nevts:"+str(evtnumber))
2066  )
2067 
2068  self.addedObjects.append(("Production Info","configurationMetadata"))
2069 
2070 
2071  def create_process(self):
2072  self.pythonCfgCode = "# Auto generated configuration file\n"
2073  self.pythonCfgCode += "# using: \n# "+__version__[1:-1]+"\n# "+__source__[1:-1]+'\n'
2074  self.pythonCfgCode += "# with command line options: "+self._options.arguments+'\n'
2075  self.pythonCfgCode += "import FWCore.ParameterSet.Config as cms\n\n"
2076 
2077  # now set up the modifies
2078  modifiers=[]
2079  modifierStrings=[]
2080  modifierImports=[]
2081 
2082  if hasattr(self._options,"era") and self._options.era :
2083  # Multiple eras can be specified in a comma seperated list
2084  from Configuration.StandardSequences.Eras import eras
2085  for requestedEra in self._options.era.split(",") :
2086  modifierStrings.append(requestedEra)
2087  modifierImports.append(eras.pythonCfgLines[requestedEra])
2088  modifiers.append(getattr(eras,requestedEra))
2089 
2090 
2091  if hasattr(self._options,"procModifiers") and self._options.procModifiers:
2092  import importlib
2093  thingsImported=[]
2094  for pm in self._options.procModifiers.split(','):
2095  modifierStrings.append(pm)
2096  modifierImports.append('from Configuration.ProcessModifiers.'+pm+'_cff import '+pm)
2097  modifiers.append(getattr(importlib.import_module('Configuration.ProcessModifiers.'+pm+'_cff'),pm))
2098 
2099  self.pythonCfgCode += '\n'.join(modifierImports)+'\n\n'
2100  self.pythonCfgCode += "process = cms.Process('"+self._options.name+"'" # Start of the line, finished after the loop
2101 
2102 
2103  if len(modifierStrings)>0:
2104  self.pythonCfgCode+= ','+','.join(modifierStrings)
2105  self.pythonCfgCode+=')\n\n'
2106 
2107  #yes, the cfg code gets out of sync here if a process is passed in. That could be fixed in the future
2108  #assuming there is some way for the fwk to get the list of modifiers (and their stringified name)
2109  if self.process == None:
2110  if len(modifiers)>0:
2111  self.process = cms.Process(self._options.name,*modifiers)
2112  else:
2113  self.process = cms.Process(self._options.name)
2114 
2115 
2116 
2117 
2118  def prepare(self, doChecking = False):
2119  """ Prepare the configuration string and add missing pieces."""
2120 
2121  self.loadAndRemember(self.EVTCONTDefaultCFF) #load the event contents regardless
2122  self.addMaxEvents()
2123  if self.with_input:
2124  self.addSource()
2125  self.addStandardSequences()
2126  ##adding standard sequences might change the inputEventContent option and therefore needs to be finalized after
2127  self.completeInputCommand()
2128  self.addConditions()
2129 
2130 
2131  outputModuleCfgCode=""
2132  if not 'HARVESTING' in self.stepMap.keys() and not 'ALCAHARVEST' in self.stepMap.keys() and not 'ALCAOUTPUT' in self.stepMap.keys() and self.with_output:
2133  outputModuleCfgCode=self.addOutput()
2134 
2135  self.addCommon()
2136 
2137  self.pythonCfgCode += "# import of standard configurations\n"
2138  for module in self.imports:
2139  self.pythonCfgCode += ("process.load('"+module+"')\n")
2140 
2141  # production info
2142  if not hasattr(self.process,"configurationMetadata"):
2143  self.build_production_info(self._options.evt_type, self._options.number)
2144  else:
2145  #the PSet was added via a load
2146  self.addedObjects.append(("Production Info","configurationMetadata"))
2147 
2148  self.pythonCfgCode +="\n"
2149  for comment,object in self.addedObjects:
2150  if comment!="":
2151  self.pythonCfgCode += "\n# "+comment+"\n"
2152  self.pythonCfgCode += dumpPython(self.process,object)
2153 
2154  # dump the output definition
2155  self.pythonCfgCode += "\n# Output definition\n"
2156  self.pythonCfgCode += outputModuleCfgCode
2157 
2158  # dump all additional outputs (e.g. alca or skim streams)
2159  self.pythonCfgCode += "\n# Additional output definition\n"
2160  #I do not understand why the keys are not normally ordered.
2161  nl=sorted(self.additionalOutputs.keys())
2162  for name in nl:
2163  output = self.additionalOutputs[name]
2164  self.pythonCfgCode += "process.%s = %s" %(name, output.dumpPython())
2165  tmpOut = cms.EndPath(output)
2166  setattr(self.process,name+'OutPath',tmpOut)
2167  self.schedule.append(tmpOut)
2168 
2169  # dump all additional commands
2170  self.pythonCfgCode += "\n# Other statements\n"
2171  for command in self.additionalCommands:
2172  self.pythonCfgCode += command + "\n"
2173 
2174  #comma separated list of objects that deserve to be inlined in the configuration (typically from a modified config deep down)
2175  for object in self._options.inlineObjets.split(','):
2176  if not object:
2177  continue
2178  if not hasattr(self.process,object):
2179  print('cannot inline -'+object+'- : not known')
2180  else:
2181  self.pythonCfgCode +='\n'
2182  self.pythonCfgCode +=dumpPython(self.process,object)
2183 
2184  # dump all paths
2185  self.pythonCfgCode += "\n# Path and EndPath definitions\n"
2186  for path in self.process.paths:
2187  if getattr(self.process,path) not in self.blacklist_paths:
2188  self.pythonCfgCode += dumpPython(self.process,path)
2189 
2190  for endpath in self.process.endpaths:
2191  if getattr(self.process,endpath) not in self.blacklist_paths:
2192  self.pythonCfgCode += dumpPython(self.process,endpath)
2193 
2194  # dump the schedule
2195  self.pythonCfgCode += "\n# Schedule definition\n"
2196  result = "process.schedule = cms.Schedule("
2197 
2198  # handling of the schedule
2199  self.process.schedule = cms.Schedule()
2200  for item in self.schedule:
2201  if not isinstance(item, cms.Schedule):
2202  self.process.schedule.append(item)
2203  else:
2204  self.process.schedule.extend(item)
2205 
2206  if hasattr(self.process,"HLTSchedule"):
2207  beforeHLT = self.schedule[:self.schedule.index(self.process.HLTSchedule)]
2208  afterHLT = self.schedule[self.schedule.index(self.process.HLTSchedule)+1:]
2209  pathNames = ['process.'+p.label_() for p in beforeHLT]
2210  result += ','.join(pathNames)+')\n'
2211  result += 'process.schedule.extend(process.HLTSchedule)\n'
2212  pathNames = ['process.'+p.label_() for p in afterHLT]
2213  result += 'process.schedule.extend(['+','.join(pathNames)+'])\n'
2214  else:
2215  pathNames = ['process.'+p.label_() for p in self.schedule]
2216  result ='process.schedule = cms.Schedule('+','.join(pathNames)+')\n'
2217 
2218  self.pythonCfgCode += result
2219 
2220  for labelToAssociate in self.labelsToAssociate:
2221  self.process.schedule.associate(getattr(self.process, labelToAssociate))
2222  self.pythonCfgCode += 'process.schedule.associate(process.' + labelToAssociate + ')\n'
2223 
2224  from PhysicsTools.PatAlgos.tools.helpers import associatePatAlgosToolsTask
2226  self.pythonCfgCode+="from PhysicsTools.PatAlgos.tools.helpers import associatePatAlgosToolsTask\n"
2227  self.pythonCfgCode+="associatePatAlgosToolsTask(process)\n"
2228 
2229  if self._options.nThreads is not "1":
2230  self.pythonCfgCode +="\n"
2231  self.pythonCfgCode +="#Setup FWK for multithreaded\n"
2232  self.pythonCfgCode +="process.options.numberOfThreads=cms.untracked.uint32("+self._options.nThreads+")\n"
2233  self.pythonCfgCode +="process.options.numberOfStreams=cms.untracked.uint32("+self._options.nStreams+")\n"
2234  self.pythonCfgCode +="process.options.numberOfConcurrentLuminosityBlocks=cms.untracked.uint32("+self._options.nConcurrentLumis+")\n"
2235  self.process.options.numberOfThreads=cms.untracked.uint32(int(self._options.nThreads))
2236  self.process.options.numberOfStreams=cms.untracked.uint32(int(self._options.nStreams))
2237  self.process.options.numberOfConcurrentLuminosityBlocks=cms.untracked.uint32(int(self._options.nConcurrentLumis))
2238  #repacked version
2239  if self._options.isRepacked:
2240  self.pythonCfgCode +="\n"
2241  self.pythonCfgCode +="from Configuration.Applications.ConfigBuilder import MassReplaceInputTag\n"
2242  self.pythonCfgCode +="MassReplaceInputTag(process, new=\"rawDataMapperByLabel\", old=\"rawDataCollector\")\n"
2243  MassReplaceInputTag(self.process, new="rawDataMapperByLabel", old="rawDataCollector")
2244 
2245  # special treatment in case of production filter sequence 2/2
2246  if self.productionFilterSequence:
2247  self.pythonCfgCode +='# filter all path with the production filter sequence\n'
2248  self.pythonCfgCode +='for path in process.paths:\n'
2249  if len(self.conditionalPaths):
2250  self.pythonCfgCode +='\tif not path in %s: continue\n'%str(self.conditionalPaths)
2251  if len(self.excludedPaths):
2252  self.pythonCfgCode +='\tif path in %s: continue\n'%str(self.excludedPaths)
2253  self.pythonCfgCode +='\tgetattr(process,path).insert(0, process.%s)\n'%(self.productionFilterSequence,)
2254  pfs = getattr(self.process,self.productionFilterSequence)
2255  for path in self.process.paths:
2256  if not path in self.conditionalPaths: continue
2257  if path in self.excludedPaths: continue
2258  getattr(self.process,path).insert(0, pfs)
2259 
2260 
2261  # dump customise fragment
2262  self.pythonCfgCode += self.addCustomise()
2263 
2264  if self._options.runUnscheduled:
2265  # prune and delete paths
2266  #this is not supporting the blacklist at this point since I do not understand it
2267  self.pythonCfgCode+="#do not add changes to your config after this point (unless you know what you are doing)\n"
2268  self.pythonCfgCode+="from FWCore.ParameterSet.Utilities import convertToUnscheduled\n"
2269  self.pythonCfgCode+="process=convertToUnscheduled(process)\n"
2270 
2271  from FWCore.ParameterSet.Utilities import convertToUnscheduled
2273 
2274  self.pythonCfgCode += self.addCustomise(1)
2275 
2276  self.pythonCfgCode += self.addCustomiseCmdLine()
2277 
2278  if hasattr(self.process,"logErrorHarvester"):
2279  #configure logErrorHarvester to wait for same EDProducers to finish as the OutputModules
2280  self.pythonCfgCode +="\n#Have logErrorHarvester wait for the same EDProducers to finish as those providing data for the OutputModule\n"
2281  self.pythonCfgCode +="from FWCore.Modules.logErrorHarvester_cff import customiseLogErrorHarvesterUsingOutputCommands\n"
2282  self.pythonCfgCode +="process = customiseLogErrorHarvesterUsingOutputCommands(process)\n"
2283  from FWCore.Modules.logErrorHarvester_cff import customiseLogErrorHarvesterUsingOutputCommands
2285 
2286  # Temporary hack to put the early delete customization after
2287  # everything else
2288  #
2289  # FIXME: remove when no longer needed
2290  self.pythonCfgCode += "\n# Add early deletion of temporary data products to reduce peak memory need\n"
2291  self.pythonCfgCode += "from Configuration.StandardSequences.earlyDeleteSettings_cff import customiseEarlyDelete\n"
2292  self.pythonCfgCode += "process = customiseEarlyDelete(process)\n"
2293  self.pythonCfgCode += "# End adding early deletion\n"
2294  from Configuration.StandardSequences.earlyDeleteSettings_cff import customiseEarlyDelete
2295  self.process = customiseEarlyDelete(self.process)
2296 
2297 
2298  # make the .io file
2299 
2300  if self._options.io:
2301  #io=open(self._options.python_filename.replace('.py','.io'),'w')
2302  if not self._options.io.endswith('.io'): self._option.io+='.io'
2303  io=open(self._options.io,'w')
2304  ioJson={}
2305  if hasattr(self.process.source,"fileNames"):
2306  if len(self.process.source.fileNames.value()):
2307  ioJson['primary']=self.process.source.fileNames.value()
2308  if hasattr(self.process.source,"secondaryFileNames"):
2309  if len(self.process.source.secondaryFileNames.value()):
2310  ioJson['secondary']=self.process.source.secondaryFileNames.value()
2311  if self._options.pileup_input and (self._options.pileup_input.startswith('dbs:') or self._options.pileup_input.startswith('das:')):
2312  ioJson['pileup']=self._options.pileup_input[4:]
2313  for (o,om) in self.process.outputModules_().items():
2314  ioJson[o]=om.fileName.value()
2315  ioJson['GT']=self.process.GlobalTag.globaltag.value()
2316  if self.productionFilterSequence:
2317  ioJson['filter']=self.productionFilterSequence
2318  import json
2319  io.write(json.dumps(ioJson))
2320  return
2321 
def load(self, includeFile)
std::vector< std::string_view > split(std::string_view, const char *)
def prepare_ENDJOB(self, sequence='endOfProcess')
def prepare_LHE(self, sequence=None)
def prepare_DATAMIX(self, sequence=None)
def expandMapping(self, seqList, mapping, index=None)
def prepare_SIM(self, sequence=None)
def prepare_HARVESTING(self, sequence=None)
def prepare_USER(self, sequence=None)
def prepare_GEN(self, sequence=None)
def loadDefaultOrSpecifiedCFF(self, sequence, defaultCFF)
bool any(const std::vector< T > &v, const T &what)
Definition: ECalSD.cc:40
def massSearchReplaceAnyInputTag(sequence, oldInputTag, newInputTag, verbose=False, moduleLabelOnly=False, skipLabelTest=False)
Definition: MassReplace.py:73
def prepare_L1REPACK(self, sequence=None)
inliner
load the relevant part
def renameInputTagsInSequence(self, sequence, oldT="rawDataCollector", newT="rawDataRepacker")
def prepare_POSTRECO(self, sequence=None)
process
adding standard sequences might change the inputEventContent option and therefore needs to be finaliz...
def replace(string, replacements)
def prepare_REPACK(self, sequence=None)
def prepare_EI(self, sequence=None)
def prepare_RECOBEFMIX(self, sequence="reconstruction")
def prepare_FILTER(self, sequence=None)
S & print(S &os, JobReport::InputFile const &f)
Definition: JobReport.cc:66
def filesFromDASQuery(query, option="", s=None)
def prepare_PATFILTER(self, sequence=None)
def build_production_info(self, evt_type, evtnumber)
def ProcessName(process)
Definition: CustomConfigs.py:8
def __init__(self, paramSearch, paramReplace, verbose=False, whitelist=())
def prepare_L1HwVal(self, sequence='L1HwVal')
def prepare_CFWRITER(self, sequence=None)
def prepare_RAW2DIGI(self, sequence="RawToDigi")
def prepare_RECO(self, sequence="reconstruction")
OutputIterator zip(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result, Compare comp)
def anyOf(listOfKeys, dict, opt=None)
def convertToUnscheduled(proc)
def prepare_PATGEN(self, sequence="miniGEN")
def addExtraStream(self, name, stream, workflow='full')
def prepare_DQM(self, sequence='DQMOffline')
def prepare_L1Reco(self, sequence="L1Reco")
def renameHLTprocessInSequence(self, sequence, proc=None, HLTprocess='HLT')
def prepare_RECOSIM(self, sequence="recosim")
productionFilterSequence
put it before all the other paths
runsAndWeights
drop LHEXMLStringProduct on input to save memory if appropriate
def addCustomise(self, unsch=0)
def prepare_ALCAPRODUCER(self, sequence=None)
def prepare_ALCAOUTPUT(self, sequence=None)
def scheduleSequence(self, seq, prefix, what='Path')
bool insert(Storage &iStorage, ItemType *iItem, const IdTag &iIdTag)
Definition: HCMethods.h:50
def prepare_DIGI(self, sequence=None)
def prepare_DIGI2RAW(self, sequence=None)
def loadAndRemember(self, includeFile)
def throwAndSetRandomRun(source, runsAndProbs)
def prepare_NANO(self, sequence="nanoAOD")
def prepare_SKIM(self, sequence="all")
static std::string join(char **cmd)
Definition: RemoteFile.cc:17
def prepare_ALCAHARVEST(self, sequence=None)
def defineMixing(dict)
Definition: Mixing.py:185
def dumpPython(process, name)
def miniAOD_customizeOutput(out)
def prepare_L1TrackTrigger(self, sequence="L1TrackTrigger")
def prepare(self, doChecking=False)
def associatePatAlgosToolsTask(process)
Definition: helpers.py:25
def prepare_ALCA(self, sequence=None, workflow='full')
def prepare_HLT(self, sequence=None)
def __init__(self, options, process=None, with_output=False, with_input=False)
def prepare_VALIDATION(self, sequence='validation')
def prepare_L1(self, sequence=None)
def scheduleSequenceAtEnd(self, seq, prefix)
#define str(s)
def filesFromList(fileName, s=None)
def prepare_RAW2RECO(self, sequence=None)
def customiseLogErrorHarvesterUsingOutputCommands(process)
How EventSelector::AcceptEvent() decides whether to accept an event for output otherwise it is excluding the probing of A single or multiple positive and the trigger will pass if any such matching triggers are PASS or EXCEPTION[A criterion thatmatches no triggers at all is detected and causes a throw.] A single negative with an expectation of appropriate bit checking in the decision and the trigger will pass if any such matching triggers are FAIL or EXCEPTION A wildcarded negative criterion that matches more than one trigger in the trigger list("!*","!HLTx*"if it matches 2 triggers or more) will accept the event if all the matching triggers are FAIL.It will reject the event if any of the triggers are PASS or EXCEPTION(this matches the behavior of"!*"before the partial wildcard feature was incorporated).Triggers which are in the READY state are completely ignored.(READY should never be returned since the trigger paths have been run
def executeAndRemember(self, command)
def prepare_PAT(self, sequence="miniAOD")
nextScheduleIsConditional
put the filtering path in the schedule