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("process")
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  prim.append(entries[0])
110  sec.append(entries[1])
111  elif (line.find(".root")!=-1):
112  entry=line.replace("\n","")
113  prim.append(entry)
114  # remove any duplicates
115  prim = sorted(list(set(prim)))
116  sec = sorted(list(set(sec)))
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)
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  prim.append(entries[0])
160  sec.append(entries[1])
161  elif (line.find(".root")!=-1):
162  entry=line.replace("\n","")
163  prim.append(entry)
164  # remove any duplicates
165  prim = sorted(list(set(prim)))
166  sec = sorted(list(set(sec)))
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() and not self._options.filetype == "LHE":
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 and not self._options.filetype == "LHE":
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  ## allow comma separated input eventcontent
791  if not hasattr(self.process.source,'inputCommands'): self.process.source.inputCommands=cms.untracked.vstring()
792  for evct in self._options.inputEventContent.split(','):
793  if evct=='': continue
794  theEventContent = getattr(self.process, evct+"EventContent")
795  if hasattr(theEventContent,'outputCommands'):
796  self.process.source.inputCommands.extend(copy.copy(theEventContent.outputCommands))
797  if hasattr(theEventContent,'inputCommands'):
798  self.process.source.inputCommands.extend(copy.copy(theEventContent.inputCommands))
799 
800  dropSecondDropStar(self.process.source.inputCommands)
801 
802  if not self._options.dropDescendant:
803  self.process.source.dropDescendantsOfDroppedBranches = cms.untracked.bool(False)
804 
805 
806  return
807 
808  def addConditions(self):
809  """Add conditions to the process"""
810  if not self._options.conditions: return
811 
812  if 'FrontierConditions_GlobalTag' in self._options.conditions:
813  print('using FrontierConditions_GlobalTag in --conditions is not necessary anymore and will be deprecated soon. please update your command line')
814  self._options.conditions = self._options.conditions.replace("FrontierConditions_GlobalTag,",'')
815 
817  from Configuration.AlCa.GlobalTag import GlobalTag
818  self.process.GlobalTag = GlobalTag(self.process.GlobalTag, self._options.conditions, self._options.custom_conditions)
819  self.additionalCommands.append('from Configuration.AlCa.GlobalTag import GlobalTag')
820  self.additionalCommands.append('process.GlobalTag = GlobalTag(process.GlobalTag, %s, %s)' % (repr(self._options.conditions), repr(self._options.custom_conditions)))
821 
822 
823  def addCustomise(self,unsch=0):
824  """Include the customise code """
825 
826  custOpt=[]
827  if unsch==0:
828  for c in self._options.customisation_file:
829  custOpt.extend(c.split(","))
830  else:
831  for c in self._options.customisation_file_unsch:
832  custOpt.extend(c.split(","))
833 
834  custMap=DictTypes.SortedKeysDict()
835  for opt in custOpt:
836  if opt=='': continue
837  if opt.count('.')>1:
838  raise Exception("more than . in the specification:"+opt)
839  fileName=opt.split('.')[0]
840  if opt.count('.')==0: rest='customise'
841  else:
842  rest=opt.split('.')[1]
843  if rest=='py': rest='customise' #catch the case of --customise file.py
844 
845  if fileName in custMap:
846  custMap[fileName].extend(rest.split('+'))
847  else:
848  custMap[fileName]=rest.split('+')
849 
850  if len(custMap)==0:
851  final_snippet='\n'
852  else:
853  final_snippet='\n# customisation of the process.\n'
854 
855  allFcn=[]
856  for opt in custMap:
857  allFcn.extend(custMap[opt])
858  for fcn in allFcn:
859  if allFcn.count(fcn)!=1:
860  raise Exception("cannot specify twice "+fcn+" as a customisation method")
861 
862  for f in custMap:
863  # let python search for that package and do syntax checking at the same time
864  packageName = f.replace(".py","").replace("/",".")
865  __import__(packageName)
866  package = sys.modules[packageName]
867 
868  # now ask the package for its definition and pick .py instead of .pyc
869  customiseFile = re.sub(r'\.pyc$', '.py', package.__file__)
870 
871  final_snippet+='\n# Automatic addition of the customisation function from '+packageName+'\n'
872  if self._options.inline_custom:
873  for line in file(customiseFile,'r'):
874  if "import FWCore.ParameterSet.Config" in line:
875  continue
876  final_snippet += line
877  else:
878  final_snippet += 'from %s import %s \n'%(packageName,','.join(custMap[f]))
879  for fcn in custMap[f]:
880  print("customising the process with",fcn,"from",f)
881  if not hasattr(package,fcn):
882  #bound to fail at run time
883  raise Exception("config "+f+" has no function "+fcn)
884  #execute the command
885  self.process=getattr(package,fcn)(self.process)
886  #and print it in the configuration
887  final_snippet += "\n#call to customisation function "+fcn+" imported from "+packageName
888  final_snippet += "\nprocess = %s(process)\n"%(fcn,)
889 
890  if len(custMap)!=0:
891  final_snippet += '\n# End of customisation functions\n'
892 
893  ### now for a useful command
894  return final_snippet
895 
897  final_snippet='\n# Customisation from command line\n'
898  if self._options.customise_commands:
899  import string
900  for com in self._options.customise_commands.split('\\n'):
901  com=string.lstrip(com)
902  self.executeAndRemember(com)
903  final_snippet +='\n'+com
904 
905  return final_snippet
906 
907  #----------------------------------------------------------------------------
908  # here the methods to define the python includes for each step or
909  # conditions
910  #----------------------------------------------------------------------------
911  def define_Configs(self):
912  if len(self.stepMap):
913  self.loadAndRemember('Configuration/StandardSequences/Services_cff')
914  if self._options.particleTable not in defaultOptions.particleTableList:
915  print('Invalid particle table provided. Options are:')
916  print(defaultOptions.particleTable)
917  sys.exit(-1)
918  else:
919  if len(self.stepMap):
920  self.loadAndRemember('SimGeneral.HepPDTESSource.'+self._options.particleTable+'_cfi')
921 
922  self.loadAndRemember('FWCore/MessageService/MessageLogger_cfi')
923 
924  self.ALCADefaultCFF="Configuration/StandardSequences/AlCaRecoStreams_cff"
925  self.GENDefaultCFF="Configuration/StandardSequences/Generator_cff"
926  self.SIMDefaultCFF="Configuration/StandardSequences/Sim_cff"
927  self.DIGIDefaultCFF="Configuration/StandardSequences/Digi_cff"
928  self.DIGI2RAWDefaultCFF="Configuration/StandardSequences/DigiToRaw_cff"
929  self.L1EMDefaultCFF='Configuration/StandardSequences/SimL1Emulator_cff'
930  self.L1MENUDefaultCFF="Configuration/StandardSequences/L1TriggerDefaultMenu_cff"
931  self.HLTDefaultCFF="Configuration/StandardSequences/HLTtable_cff"
932  self.RAW2DIGIDefaultCFF="Configuration/StandardSequences/RawToDigi_Data_cff"
933  if self._options.isRepacked: self.RAW2DIGIDefaultCFF="Configuration/StandardSequences/RawToDigi_DataMapper_cff"
934  self.L1RecoDefaultCFF="Configuration/StandardSequences/L1Reco_cff"
935  self.L1TrackTriggerDefaultCFF="Configuration/StandardSequences/L1TrackTrigger_cff"
936  self.RECODefaultCFF="Configuration/StandardSequences/Reconstruction_Data_cff"
937  self.RECOSIMDefaultCFF="Configuration/StandardSequences/RecoSim_cff"
938  self.PATDefaultCFF="Configuration/StandardSequences/PAT_cff"
939  self.NANODefaultCFF="PhysicsTools/NanoAOD/nano_cff"
940  self.NANOGENDefaultCFF="PhysicsTools/NanoAOD/nanogen_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  #TODO: Check based of file input
991  self.NANOGENDefaultSeq='nanogenSequence'
992  self.NANODefaultSeq='nanoSequence'
993 
994  self.EVTCONTDefaultCFF="Configuration/EventContent/EventContent_cff"
995 
996  if not self._options.beamspot:
997  self._options.beamspot=VtxSmearedDefaultKey
998 
999  # if its MC then change the raw2digi
1000  if self._options.isMC==True:
1001  self.RAW2DIGIDefaultCFF="Configuration/StandardSequences/RawToDigi_cff"
1002  self.RECODefaultCFF="Configuration/StandardSequences/Reconstruction_cff"
1003  self.PATDefaultCFF="Configuration/StandardSequences/PATMC_cff"
1004  self.PATGENDefaultCFF="Configuration/StandardSequences/PATGEN_cff"
1005  self.DQMOFFLINEDefaultCFF="DQMOffline/Configuration/DQMOfflineMC_cff"
1006  self.ALCADefaultCFF="Configuration/StandardSequences/AlCaRecoStreamsMC_cff"
1007  self.NANODefaultSeq='nanoSequenceMC'
1008  else:
1009  self._options.beamspot = None
1010 
1011  #patch for gen, due to backward incompatibility
1012  if 'reGEN' in self.stepMap:
1013  self.GENDefaultSeq='fixGenInfo'
1014 
1015  if self._options.scenario=='cosmics':
1016  self._options.pileup='Cosmics'
1017  self.DIGIDefaultCFF="Configuration/StandardSequences/DigiCosmics_cff"
1018  self.RECODefaultCFF="Configuration/StandardSequences/ReconstructionCosmics_cff"
1019  self.SKIMDefaultCFF="Configuration/StandardSequences/SkimsCosmics_cff"
1020  self.EVTCONTDefaultCFF="Configuration/EventContent/EventContentCosmics_cff"
1021  self.VALIDATIONDefaultCFF="Configuration/StandardSequences/ValidationCosmics_cff"
1022  self.DQMOFFLINEDefaultCFF="DQMOffline/Configuration/DQMOfflineCosmics_cff"
1023  if self._options.isMC==True:
1024  self.DQMOFFLINEDefaultCFF="DQMOffline/Configuration/DQMOfflineCosmicsMC_cff"
1025  self.HARVESTINGDefaultCFF="Configuration/StandardSequences/HarvestingCosmics_cff"
1026  self.RECODefaultSeq='reconstructionCosmics'
1027  self.DQMDefaultSeq='DQMOfflineCosmics'
1028 
1029  if self._options.scenario=='HeavyIons':
1030  if not self._options.beamspot:
1031  self._options.beamspot=VtxSmearedHIDefaultKey
1032  self.HLTDefaultSeq = 'HIon'
1033  self.VALIDATIONDefaultCFF="Configuration/StandardSequences/ValidationHeavyIons_cff"
1034  self.VALIDATIONDefaultSeq=''
1035  self.EVTCONTDefaultCFF="Configuration/EventContent/EventContentHeavyIons_cff"
1036  self.RECODefaultCFF="Configuration/StandardSequences/ReconstructionHeavyIons_cff"
1037  self.RECODefaultSeq='reconstructionHeavyIons'
1038  self.ALCADefaultCFF = "Configuration/StandardSequences/AlCaRecoStreamsHeavyIons_cff"
1039  self.DQMOFFLINEDefaultCFF="DQMOffline/Configuration/DQMOfflineHeavyIons_cff"
1040  self.DQMDefaultSeq='DQMOfflineHeavyIons'
1041  self.SKIMDefaultCFF="Configuration/StandardSequences/SkimsHeavyIons_cff"
1042  self.HARVESTINGDefaultCFF="Configuration/StandardSequences/HarvestingHeavyIons_cff"
1043  if self._options.isMC==True:
1044  self.DQMOFFLINEDefaultCFF="DQMOffline/Configuration/DQMOfflineHeavyIonsMC_cff"
1045 
1046 
1048 
1049  self.USERDefaultSeq='user'
1050  self.USERDefaultCFF=None
1051 
1052  # the magnetic field
1053  if self._options.isData:
1054  if self._options.magField==defaultOptions.magField:
1055  print("magnetic field option forced to: AutoFromDBCurrent")
1056  self._options.magField='AutoFromDBCurrent'
1057  self.magFieldCFF = 'Configuration/StandardSequences/MagneticField_'+self._options.magField.replace('.','')+'_cff'
1058  self.magFieldCFF = self.magFieldCFF.replace("__",'_')
1059 
1060  # the geometry
1061  self.GeometryCFF='Configuration/StandardSequences/GeometryRecoDB_cff'
1063  simGeometry=''
1064  if self._options.fast:
1065  if 'start' in self._options.conditions.lower():
1066  self.GeometryCFF='FastSimulation/Configuration/Geometries_START_cff'
1067  else:
1068  self.GeometryCFF='FastSimulation/Configuration/Geometries_MC_cff'
1069  else:
1070  def inGeometryKeys(opt):
1071  from Configuration.StandardSequences.GeometryConf import GeometryConf
1072  if opt in GeometryConf:
1073  return GeometryConf[opt]
1074  else:
1075  return opt
1076 
1077  geoms=self._options.geometry.split(',')
1078  if len(geoms)==1: geoms=inGeometryKeys(geoms[0]).split(',')
1079  if len(geoms)==2:
1080  #may specify the reco geometry
1081  if '/' in geoms[1] or '_cff' in geoms[1]:
1082  self.GeometryCFF=geoms[1]
1083  else:
1084  self.GeometryCFF='Configuration/Geometry/Geometry'+geoms[1]+'_cff'
1085 
1086  if (geoms[0].startswith('DB:')):
1087  self.SimGeometryCFF='Configuration/StandardSequences/GeometrySimDB_cff'
1088  self.geometryDBLabel=geoms[0][3:]
1089  print("with DB:")
1090  else:
1091  if '/' in geoms[0] or '_cff' in geoms[0]:
1092  self.SimGeometryCFF=geoms[0]
1093  else:
1094  simGeometry=geoms[0]
1095  if self._options.gflash==True:
1096  self.SimGeometryCFF='Configuration/Geometry/Geometry'+geoms[0]+'GFlash_cff'
1097  else:
1098  self.SimGeometryCFF='Configuration/Geometry/Geometry'+geoms[0]+'_cff'
1099 
1100  # synchronize the geometry configuration and the FullSimulation sequence to be used
1101  if simGeometry not in defaultOptions.geometryExtendedOptions:
1102  self.SIMDefaultCFF="Configuration/StandardSequences/SimIdeal_cff"
1103 
1104  if self._options.scenario=='nocoll' or self._options.scenario=='cosmics':
1105  self.SIMDefaultCFF="Configuration/StandardSequences/SimNOBEAM_cff"
1106  self._options.beamspot='NoSmear'
1107 
1108  # fastsim requires some changes to the default cff files and sequences
1109  if self._options.fast:
1110  self.SIMDefaultCFF = 'FastSimulation.Configuration.SimIdeal_cff'
1111  self.RECODefaultCFF= 'FastSimulation.Configuration.Reconstruction_AftMix_cff'
1112  self.RECOBEFMIXDefaultCFF = 'FastSimulation.Configuration.Reconstruction_BefMix_cff'
1113  self.RECOBEFMIXDefaultSeq = 'reconstruction_befmix'
1114  self.NANODefaultSeq = 'nanoSequenceFS'
1115  self.DQMOFFLINEDefaultCFF="FastSimulation.Configuration.DQMOfflineMC_cff"
1116 
1117  # Mixing
1118  if self._options.pileup=='default':
1119  from Configuration.StandardSequences.Mixing import MixingDefaultKey
1120  self._options.pileup=MixingDefaultKey
1121 
1122 
1123  #not driven by a default cff anymore
1124  if self._options.isData:
1125  self._options.pileup=None
1126 
1127 
1129 
1130  # for alca, skims, etc
1131  def addExtraStream(self,name,stream,workflow='full'):
1132  # define output module and go from there
1133  output = cms.OutputModule("PoolOutputModule")
1134  if stream.selectEvents.parameters_().__len__()!=0:
1135  output.SelectEvents = stream.selectEvents
1136  else:
1137  output.SelectEvents = cms.untracked.PSet()
1138  output.SelectEvents.SelectEvents=cms.vstring()
1139  if isinstance(stream.paths,tuple):
1140  for path in stream.paths:
1141  output.SelectEvents.SelectEvents.append(path.label())
1142  else:
1143  output.SelectEvents.SelectEvents.append(stream.paths.label())
1144 
1145 
1146 
1147  if isinstance(stream.content,str):
1148  evtPset=getattr(self.process,stream.content)
1149  for p in evtPset.parameters_():
1150  setattr(output,p,getattr(evtPset,p))
1151  if not self._options.inlineEventContent:
1152  def doNotInlineEventContent(instance,label = "process."+stream.content+".outputCommands"):
1153  return label
1154  output.outputCommands.__dict__["dumpPython"] = doNotInlineEventContent
1155  else:
1156  output.outputCommands = stream.content
1157 
1158 
1159  output.fileName = cms.untracked.string(self._options.dirout+stream.name+'.root')
1160 
1161  output.dataset = cms.untracked.PSet( dataTier = stream.dataTier,
1162  filterName = cms.untracked.string(stream.name))
1163 
1164  if self._options.filtername:
1165  output.dataset.filterName= cms.untracked.string(self._options.filtername+"_"+stream.name)
1166 
1167  #add an automatic flushing to limit memory consumption
1168  output.eventAutoFlushCompressedSize=cms.untracked.int32(5*1024*1024)
1169 
1170  if workflow in ("producers,full"):
1171  if isinstance(stream.paths,tuple):
1172  for path in stream.paths:
1173  self.schedule.append(path)
1174  else:
1175  self.schedule.append(stream.paths)
1176 
1177 
1178  # in case of relvals we don't want to have additional outputs
1179  if (not self._options.relval) and workflow in ("full","output"):
1180  self.additionalOutputs[name] = output
1181  setattr(self.process,name,output)
1182 
1183  if workflow == 'output':
1184  # adjust the select events to the proper trigger results from previous process
1185  filterList = output.SelectEvents.SelectEvents
1186  for i, filter in enumerate(filterList):
1187  filterList[i] = filter+":"+self._options.triggerResultsProcess
1188 
1189  return output
1190 
1191  #----------------------------------------------------------------------------
1192  # here the methods to create the steps. Of course we are doing magic here ;)
1193  # prepare_STEPNAME modifies self.process and what else's needed.
1194  #----------------------------------------------------------------------------
1195 
1196  def loadDefaultOrSpecifiedCFF(self, sequence,defaultCFF):
1197  if ( len(sequence.split('.'))==1 ):
1198  l=self.loadAndRemember(defaultCFF)
1199  elif ( len(sequence.split('.'))==2 ):
1200  l=self.loadAndRemember(sequence.split('.')[0])
1201  sequence=sequence.split('.')[1]
1202  else:
1203  print("sub sequence configuration must be of the form dir/subdir/cff.a+b+c or cff.a")
1204  print(sequence,"not recognized")
1205  raise
1206  return l
1207 
1208  def scheduleSequence(self,seq,prefix,what='Path'):
1209  if '*' in seq:
1210  #create only one path with all sequences in it
1211  for i,s in enumerate(seq.split('*')):
1212  if i==0:
1213  setattr(self.process,prefix,getattr(cms,what)( getattr(self.process, s) ))
1214  else:
1215  p=getattr(self.process,prefix)
1216  tmp = getattr(self.process, s)
1217  if isinstance(tmp, cms.Task):
1218  p.associate(tmp)
1219  else:
1220  p+=tmp
1221  self.schedule.append(getattr(self.process,prefix))
1222  return
1223  else:
1224  #create as many path as many sequences
1225  if not '+' in seq:
1226  if self.nextScheduleIsConditional:
1227  self.conditionalPaths.append(prefix)
1228  setattr(self.process,prefix,getattr(cms,what)( getattr(self.process, seq) ))
1229  self.schedule.append(getattr(self.process,prefix))
1230  else:
1231  for i,s in enumerate(seq.split('+')):
1232  sn=prefix+'%d'%(i)
1233  setattr(self.process,sn,getattr(cms,what)( getattr(self.process, s) ))
1234  self.schedule.append(getattr(self.process,sn))
1235  return
1236 
1237  def scheduleSequenceAtEnd(self,seq,prefix):
1238  self.scheduleSequence(seq,prefix,what='EndPath')
1239  return
1240 
1241  def prepare_ALCAPRODUCER(self, sequence = None):
1242  self.prepare_ALCA(sequence, workflow = "producers")
1243 
1244  def prepare_ALCAOUTPUT(self, sequence = None):
1245  self.prepare_ALCA(sequence, workflow = "output")
1246 
1247  def prepare_ALCA(self, sequence = None, workflow = 'full'):
1248  """ Enrich the process with alca streams """
1249  alcaConfig=self.loadDefaultOrSpecifiedCFF(sequence,self.ALCADefaultCFF)
1250  sequence = sequence.split('.')[-1]
1251 
1252  # decide which ALCA paths to use
1253  alcaList = sequence.split("+")
1254  maxLevel=0
1255  from Configuration.AlCa.autoAlca import autoAlca
1256  # support @X from autoAlca.py, and recursion support: i.e T0:@Mu+@EG+...
1257  self.expandMapping(alcaList,autoAlca)
1258  self.AlCaPaths=[]
1259  for name in alcaConfig.__dict__:
1260  alcastream = getattr(alcaConfig,name)
1261  shortName = name.replace('ALCARECOStream','')
1262  if shortName in alcaList and isinstance(alcastream,cms.FilteredStream):
1263  output = self.addExtraStream(name,alcastream, workflow = workflow)
1264  self.executeAndRemember('process.ALCARECOEventContent.outputCommands.extend(process.OutALCARECO'+shortName+'_noDrop.outputCommands)')
1265  self.AlCaPaths.append(shortName)
1266  if 'DQM' in alcaList:
1267  if not self._options.inlineEventContent and hasattr(self.process,name):
1268  self.executeAndRemember('process.' + name + '.outputCommands.append("keep *_MEtoEDMConverter_*_*")')
1269  else:
1270  output.outputCommands.append("keep *_MEtoEDMConverter_*_*")
1271 
1272  #rename the HLT process name in the alca modules
1273  if self._options.hltProcess or 'HLT' in self.stepMap:
1274  if isinstance(alcastream.paths,tuple):
1275  for path in alcastream.paths:
1276  self.renameHLTprocessInSequence(path.label())
1277  else:
1278  self.renameHLTprocessInSequence(alcastream.paths.label())
1279 
1280  for i in range(alcaList.count(shortName)):
1281  alcaList.remove(shortName)
1282 
1283  # DQM needs a special handling
1284  elif name == 'pathALCARECODQM' and 'DQM' in alcaList:
1285  path = getattr(alcaConfig,name)
1286  self.schedule.append(path)
1287  alcaList.remove('DQM')
1288 
1289  if isinstance(alcastream,cms.Path):
1290  #black list the alca path so that they do not appear in the cfg
1291  self.blacklist_paths.append(alcastream)
1292 
1293 
1294  if len(alcaList) != 0:
1295  available=[]
1296  for name in alcaConfig.__dict__:
1297  alcastream = getattr(alcaConfig,name)
1298  if isinstance(alcastream,cms.FilteredStream):
1299  available.append(name.replace('ALCARECOStream',''))
1300  print("The following alcas could not be found "+str(alcaList))
1301  print("available ",available)
1302  #print "verify your configuration, ignoring for now"
1303  raise Exception("The following alcas could not be found "+str(alcaList))
1304 
1305  def prepare_LHE(self, sequence = None):
1306  #load the fragment
1307  ##make it loadable
1308  loadFragment = self._options.evt_type.replace('.py','',).replace('.','_').replace('python/','').replace('/','.')
1309  print("Loading lhe fragment from",loadFragment)
1310  __import__(loadFragment)
1311  self.process.load(loadFragment)
1312  ##inline the modules
1313  self._options.inlineObjets+=','+sequence
1314 
1315  getattr(self.process,sequence).nEvents = int(self._options.number)
1316 
1317  #schedule it
1318  self.process.lhe_step = cms.Path( getattr( self.process,sequence) )
1319  self.excludedPaths.append("lhe_step")
1320  self.schedule.append( self.process.lhe_step )
1321 
1322  def prepare_GEN(self, sequence = None):
1323  """ load the fragment of generator configuration """
1324  loadFailure=False
1325  #remove trailing .py
1326  #support old style .cfi by changing into something.cfi into something_cfi
1327  #remove python/ from the name
1328  loadFragment = self._options.evt_type.replace('.py','',).replace('.','_').replace('python/','')
1329  #standard location of fragments
1330  if not '/' in loadFragment:
1331  loadFragment='Configuration.Generator.'+loadFragment
1332  else:
1333  loadFragment=loadFragment.replace('/','.')
1334  try:
1335  print("Loading generator fragment from",loadFragment)
1336  __import__(loadFragment)
1337  except:
1338  loadFailure=True
1339  #if self.process.source and self.process.source.type_()=='EmptySource':
1340  if not (self._options.filein or self._options.dasquery):
1341  raise Exception("Neither gen fragment of input files provided: this is an inconsistent GEN step configuration")
1342 
1343  if not loadFailure:
1344  generatorModule=sys.modules[loadFragment]
1345  genModules=generatorModule.__dict__
1346  #remove lhe producer module since this should have been
1347  #imported instead in the LHE step
1348  if self.LHEDefaultSeq in genModules:
1349  del genModules[self.LHEDefaultSeq]
1350 
1351  if self._options.hideGen:
1352  self.loadAndRemember(loadFragment)
1353  else:
1354  self.process.load(loadFragment)
1355  # expose the objects from that fragment to the configuration
1356  import FWCore.ParameterSet.Modules as cmstypes
1357  for name in genModules:
1358  theObject = getattr(generatorModule,name)
1359  if isinstance(theObject, cmstypes._Module):
1360  self._options.inlineObjets=name+','+self._options.inlineObjets
1361  elif isinstance(theObject, cms.Sequence) or isinstance(theObject, cmstypes.ESProducer):
1362  self._options.inlineObjets+=','+name
1363 
1364  if sequence == self.GENDefaultSeq or sequence == 'pgen_genonly':
1365  if 'ProductionFilterSequence' in genModules and ('generator' in genModules):
1366  self.productionFilterSequence = 'ProductionFilterSequence'
1367  elif 'generator' in genModules:
1368  self.productionFilterSequence = 'generator'
1369 
1370  """ Enrich the schedule with the rest of the generation step """
1371  self.loadDefaultOrSpecifiedCFF(sequence,self.GENDefaultCFF)
1372  genSeqName=sequence.split('.')[-1]
1373 
1374  if True:
1375  try:
1376  from Configuration.StandardSequences.VtxSmeared import VtxSmeared
1377  cffToBeLoaded=VtxSmeared[self._options.beamspot]
1378  self.loadAndRemember(cffToBeLoaded)
1379  except ImportError:
1380  raise Exception("VertexSmearing type or beamspot "+self._options.beamspot+" unknown.")
1381 
1382  if self._options.scenario == 'HeavyIons':
1383  if self._options.pileup=='HiMixGEN':
1384  self.loadAndRemember("Configuration/StandardSequences/GeneratorMix_cff")
1385  else:
1386  self.loadAndRemember("Configuration/StandardSequences/GeneratorHI_cff")
1387 
1388  self.process.generation_step = cms.Path( getattr(self.process,genSeqName) )
1389  self.schedule.append(self.process.generation_step)
1390 
1391  #register to the genstepfilter the name of the path (static right now, but might evolve)
1392  self.executeAndRemember('process.genstepfilter.triggerConditions=cms.vstring("generation_step")')
1393 
1394  if 'reGEN' in self.stepMap:
1395  #stop here
1396  return
1397 
1398  """ Enrich the schedule with the summary of the filter step """
1399  #the gen filter in the endpath
1400  self.loadAndRemember("GeneratorInterface/Core/genFilterSummary_cff")
1401  self.scheduleSequenceAtEnd('genFilterSummary','genfiltersummary_step')
1402  return
1403 
1404  def prepare_SIM(self, sequence = None):
1405  """ Enrich the schedule with the simulation step"""
1406  self.loadDefaultOrSpecifiedCFF(sequence,self.SIMDefaultCFF)
1407  if not self._options.fast:
1408  if self._options.gflash==True:
1409  self.loadAndRemember("Configuration/StandardSequences/GFlashSIM_cff")
1410 
1411  if self._options.magField=='0T':
1412  self.executeAndRemember("process.g4SimHits.UseMagneticField = cms.bool(False)")
1413  else:
1414  if self._options.magField=='0T':
1415  self.executeAndRemember("process.fastSimProducer.detectorDefinition.magneticFieldZ = cms.untracked.double(0.)")
1416 
1417  self.scheduleSequence(sequence.split('.')[-1],'simulation_step')
1418  return
1419 
1420  def prepare_DIGI(self, sequence = None):
1421  """ Enrich the schedule with the digitisation step"""
1422  self.loadDefaultOrSpecifiedCFF(sequence,self.DIGIDefaultCFF)
1423 
1424  if self._options.gflash==True:
1425  self.loadAndRemember("Configuration/StandardSequences/GFlashDIGI_cff")
1426 
1427  if sequence == 'pdigi_valid' or sequence == 'pdigi_hi':
1428  self.executeAndRemember("process.mix.digitizers = cms.PSet(process.theDigitizersValid)")
1429 
1430  if sequence != 'pdigi_nogen' and sequence != 'pdigi_valid_nogen' and sequence != 'pdigi_hi_nogen' and not self.process.source.type_()=='EmptySource' and not self._options.filetype == "LHE":
1431  if self._options.inputEventContent=='':
1432  self._options.inputEventContent='REGEN'
1433  else:
1434  self._options.inputEventContent=self._options.inputEventContent+',REGEN'
1435 
1436 
1437  self.scheduleSequence(sequence.split('.')[-1],'digitisation_step')
1438  return
1439 
1440  def prepare_CFWRITER(self, sequence = None):
1441  """ Enrich the schedule with the crossing frame writer step"""
1443  self.scheduleSequence('pcfw','cfwriter_step')
1444  return
1445 
1446  def prepare_DATAMIX(self, sequence = None):
1447  """ Enrich the schedule with the digitisation step"""
1449  self.scheduleSequence('pdatamix','datamixing_step')
1450 
1451  if self._options.pileup_input:
1452  theFiles=''
1453  if self._options.pileup_input.startswith('dbs:') or self._options.pileup_input.startswith('das:'):
1454  theFiles=filesFromDASQuery('file dataset = %s'%(self._options.pileup_input[4:],),self._options.pileup_dasoption)[0]
1455  elif self._options.pileup_input.startswith("filelist:"):
1456  theFiles= (filesFromList(self._options.pileup_input[9:]))[0]
1457  else:
1458  theFiles=self._options.pileup_input.split(',')
1459  #print theFiles
1460  self.executeAndRemember( "process.mixData.input.fileNames = cms.untracked.vstring(%s)"%( theFiles ) )
1461 
1462  return
1463 
1464  def prepare_DIGI2RAW(self, sequence = None):
1465  self.loadDefaultOrSpecifiedCFF(sequence,self.DIGI2RAWDefaultCFF)
1466  self.scheduleSequence(sequence.split('.')[-1],'digi2raw_step')
1467  return
1468 
1469  def prepare_REPACK(self, sequence = None):
1470  self.loadDefaultOrSpecifiedCFF(sequence,self.REPACKDefaultCFF)
1471  self.scheduleSequence(sequence.split('.')[-1],'digi2repack_step')
1472  return
1473 
1474  def prepare_L1(self, sequence = None):
1475  """ Enrich the schedule with the L1 simulation step"""
1476  assert(sequence == None)
1477  self.loadAndRemember(self.L1EMDefaultCFF)
1478  self.scheduleSequence('SimL1Emulator','L1simulation_step')
1479  return
1480 
1481  def prepare_L1REPACK(self, sequence = None):
1482  """ 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"""
1483  supported = ['GT','GT1','GT2','GCTGT','Full','FullSimTP','FullMC','Full2015Data','uGT','CalouGT']
1484  if sequence in supported:
1485  self.loadAndRemember('Configuration/StandardSequences/SimL1EmulatorRepack_%s_cff'%sequence)
1486  if self._options.scenario == 'HeavyIons':
1487  self.renameInputTagsInSequence("SimL1Emulator","rawDataCollector","rawDataRepacker")
1488  self.scheduleSequence('SimL1Emulator','L1RePack_step')
1489  else:
1490  print("L1REPACK with '",sequence,"' is not supported! Supported choices are: ",supported)
1491  raise Exception('unsupported feature')
1492 
1493 
1494  def prepare_HLT(self, sequence = None):
1495  """ Enrich the schedule with the HLT simulation step"""
1496  if not sequence:
1497  print("no specification of the hlt menu has been given, should never happen")
1498  raise Exception('no HLT sequence provided')
1499 
1500  if '@' in sequence:
1501  # case where HLT:@something was provided
1502  from Configuration.HLT.autoHLT import autoHLT
1503  key = sequence[1:]
1504  if key in autoHLT:
1505  sequence = autoHLT[key]
1506  else:
1507  raise ValueError('no HLT mapping key "%s" found in autoHLT' % key)
1508 
1509  if ',' in sequence:
1510  #case where HLT:something:something was provided
1511  self.executeAndRemember('import HLTrigger.Configuration.Utilities')
1512  optionsForHLT = {}
1513  if self._options.scenario == 'HeavyIons':
1514  optionsForHLT['type'] = 'HIon'
1515  else:
1516  optionsForHLT['type'] = 'GRun'
1517  optionsForHLTConfig = ', '.join('%s=%s' % (key, repr(val)) for (key, val) in six.iteritems(optionsForHLT))
1518  if sequence == 'run,fromSource':
1519  if hasattr(self.process.source,'firstRun'):
1520  self.executeAndRemember('process.loadHltConfiguration("run:%%d"%%(process.source.firstRun.value()),%s)'%(optionsForHLTConfig))
1521  elif hasattr(self.process.source,'setRunNumber'):
1522  self.executeAndRemember('process.loadHltConfiguration("run:%%d"%%(process.source.setRunNumber.value()),%s)'%(optionsForHLTConfig))
1523  else:
1524  raise Exception('Cannot replace menu to load %s'%(sequence))
1525  else:
1526  self.executeAndRemember('process.loadHltConfiguration("%s",%s)'%(sequence.replace(',',':'),optionsForHLTConfig))
1527  else:
1528  self.loadAndRemember('HLTrigger/Configuration/HLT_%s_cff' % sequence)
1529 
1530  if self._options.isMC:
1531  self._options.customisation_file.append("HLTrigger/Configuration/customizeHLTforMC.customizeHLTforMC")
1532 
1533  if self._options.name != 'HLT':
1534  self.additionalCommands.append('from HLTrigger.Configuration.CustomConfigs import ProcessName')
1535  self.additionalCommands.append('process = ProcessName(process)')
1536  self.additionalCommands.append('')
1537  from HLTrigger.Configuration.CustomConfigs import ProcessName
1538  self.process = ProcessName(self.process)
1539 
1540  self.schedule.append(self.process.HLTSchedule)
1541  [self.blacklist_paths.append(path) for path in self.process.HLTSchedule if isinstance(path,(cms.Path,cms.EndPath))]
1542 
1543  #this is a fake, to be removed with fastim migration and HLT menu dump
1544  if self._options.fast:
1545  if not hasattr(self.process,'HLTEndSequence'):
1546  self.executeAndRemember("process.HLTEndSequence = cms.Sequence( process.dummyModule )")
1547 
1548 
1549  def prepare_RAW2RECO(self, sequence = None):
1550  if ','in sequence:
1551  seqReco=sequence.split(',')[1]
1552  seqDigi=sequence.split(',')[0]
1553  else:
1554  print("RAW2RECO requires two specifications",sequence,"insufficient")
1555 
1556  self.prepare_RAW2DIGI(seqDigi)
1557  self.prepare_RECO(seqReco)
1558  return
1559 
1560  def prepare_RAW2DIGI(self, sequence = "RawToDigi"):
1561  self.loadDefaultOrSpecifiedCFF(sequence,self.RAW2DIGIDefaultCFF)
1562  self.scheduleSequence(sequence,'raw2digi_step')
1563  # if self._options.isRepacked:
1564  #self.renameInputTagsInSequence(sequence)
1565  return
1566 
1567  def prepare_PATFILTER(self, sequence=None):
1568  self.loadAndRemember("PhysicsTools/PatAlgos/slimming/metFilterPaths_cff")
1569  from PhysicsTools.PatAlgos.slimming.metFilterPaths_cff import allMetFilterPaths
1570  for filt in allMetFilterPaths:
1571  self.schedule.append(getattr(self.process,'Flag_'+filt))
1572 
1573  def prepare_L1HwVal(self, sequence = 'L1HwVal'):
1574  ''' Enrich the schedule with L1 HW validation '''
1575  self.loadDefaultOrSpecifiedCFF(sequence,self.L1HwValDefaultCFF)
1576  #self.scheduleSequence(sequence.split('.')[-1],'l1hwval_step')
1577  print('\n\n\n DEPRECATED this has no action \n\n\n')
1578  return
1579 
1580  def prepare_L1Reco(self, sequence = "L1Reco"):
1581  ''' Enrich the schedule with L1 reconstruction '''
1582  self.loadDefaultOrSpecifiedCFF(sequence,self.L1RecoDefaultCFF)
1583  self.scheduleSequence(sequence.split('.')[-1],'L1Reco_step')
1584  return
1585 
1586  def prepare_L1TrackTrigger(self, sequence = "L1TrackTrigger"):
1587  ''' Enrich the schedule with L1 reconstruction '''
1589  self.scheduleSequence(sequence.split('.')[-1],'L1TrackTrigger_step')
1590  return
1591 
1592  def prepare_FILTER(self, sequence = None):
1593  ''' Enrich the schedule with a user defined filter sequence '''
1594  ## load the relevant part
1595  filterConfig=self.load(sequence.split('.')[0])
1596  filterSeq=sequence.split('.')[-1]
1597  ## print it in the configuration
1598  class PrintAllModules(object):
1599  def __init__(self):
1600  self.inliner=''
1601  pass
1602  def enter(self,visitee):
1603  try:
1604  label=visitee.label()
1605  ##needs to be in reverse order
1606  self.inliner=label+','+self.inliner
1607  except:
1608  pass
1609  def leave(self,v): pass
1610 
1611  expander=PrintAllModules()
1612  getattr(self.process,filterSeq).visit( expander )
1613  self._options.inlineObjets+=','+expander.inliner
1614  self._options.inlineObjets+=','+filterSeq
1615 
1616  ## put the filtering path in the schedule
1617  self.scheduleSequence(filterSeq,'filtering_step')
1618  self.nextScheduleIsConditional=True
1619  ## put it before all the other paths
1620  self.productionFilterSequence = filterSeq
1621 
1622  return
1623 
1624  def prepare_RECO(self, sequence = "reconstruction"):
1625  ''' Enrich the schedule with reconstruction '''
1626  self.loadDefaultOrSpecifiedCFF(sequence,self.RECODefaultCFF)
1627  self.scheduleSequence(sequence.split('.')[-1],'reconstruction_step')
1628  return
1629 
1630  def prepare_RECOSIM(self, sequence = "recosim"):
1631  ''' Enrich the schedule with reconstruction '''
1632  self.loadDefaultOrSpecifiedCFF(sequence,self.RECOSIMDefaultCFF)
1633  self.scheduleSequence(sequence.split('.')[-1],'recosim_step')
1634  return
1635 
1636  def prepare_RECOBEFMIX(self, sequence = "reconstruction"):
1637  ''' Enrich the schedule with the part of reconstruction that is done before mixing in FastSim'''
1638  if not self._options.fast:
1639  print("ERROR: this step is only implemented for FastSim")
1640  sys.exit()
1642  self.scheduleSequence(sequence.split('.')[-1],'reconstruction_befmix_step')
1643  return
1644 
1645  def prepare_PAT(self, sequence = "miniAOD"):
1646  ''' Enrich the schedule with PAT '''
1647  self.prepare_PATFILTER(self)
1648  self.loadDefaultOrSpecifiedCFF(sequence,self.PATDefaultCFF)
1649  self.labelsToAssociate.append('patTask')
1650  if not self._options.runUnscheduled:
1651  raise Exception("MiniAOD production can only run in unscheduled mode, please run cmsDriver with --runUnscheduled")
1652  if self._options.isData:
1653  self._options.customisation_file_unsch.insert(0,"PhysicsTools/PatAlgos/slimming/miniAOD_tools.miniAOD_customizeAllData")
1654  else:
1655  if self._options.fast:
1656  self._options.customisation_file_unsch.insert(0,"PhysicsTools/PatAlgos/slimming/miniAOD_tools.miniAOD_customizeAllMCFastSim")
1657  else:
1658  self._options.customisation_file_unsch.insert(0,"PhysicsTools/PatAlgos/slimming/miniAOD_tools.miniAOD_customizeAllMC")
1659 
1660  if self._options.hltProcess:
1661  if len(self._options.customise_commands) > 1:
1662  self._options.customise_commands = self._options.customise_commands + " \n"
1663  self._options.customise_commands = self._options.customise_commands + "process.patTrigger.processName = \""+self._options.hltProcess+"\"\n"
1664  self._options.customise_commands = self._options.customise_commands + "process.slimmedPatTrigger.triggerResults= cms.InputTag( 'TriggerResults::"+self._options.hltProcess+"' )\n"
1665  self._options.customise_commands = self._options.customise_commands + "process.patMuons.triggerResults= cms.InputTag( 'TriggerResults::"+self._options.hltProcess+"' )\n"
1666 
1667 # self.renameHLTprocessInSequence(sequence)
1668 
1669  return
1670 
1671  def prepare_PATGEN(self, sequence = "miniGEN"):
1672  ''' Enrich the schedule with PATGEN '''
1673  self.loadDefaultOrSpecifiedCFF(sequence,self.PATGENDefaultCFF) #this is unscheduled
1674  self.labelsToAssociate.append('patGENTask')
1675  if not self._options.runUnscheduled:
1676  raise Exception("MiniGEN production can only run in unscheduled mode, please run cmsDriver with --runUnscheduled")
1677  if self._options.isData:
1678  raise Exception("PATGEN step can only run on MC")
1679  return
1680 
1681  def prepare_NANO(self, sequence = "nanoAOD"):
1682  ''' Enrich the schedule with NANO '''
1683  self.loadDefaultOrSpecifiedCFF(sequence,self.NANODefaultCFF)
1684  self.scheduleSequence(sequence.split('.')[-1],'nanoAOD_step')
1685  custom = "nanoAOD_customizeData" if self._options.isData else "nanoAOD_customizeMC"
1686  if self._options.runUnscheduled:
1687  self._options.customisation_file_unsch.insert(0,"PhysicsTools/NanoAOD/nano_cff."+custom)
1688  else:
1689  self._options.customisation_file.insert(0,"PhysicsTools/NanoAOD/nano_cff."+custom)
1690  if self._options.hltProcess:
1691  if len(self._options.customise_commands) > 1:
1692  self._options.customise_commands = self._options.customise_commands + " \n"
1693  self._options.customise_commands = self._options.customise_commands + "process.unpackedPatTrigger.triggerResults= cms.InputTag( 'TriggerResults::"+self._options.hltProcess+"' )\n"
1694 
1695  def prepare_NANOGEN(self, sequence = "nanoAOD"):
1696  ''' Enrich the schedule with NANOGEN '''
1697  # TODO: Need to modify this based on the input file type
1698  fromGen = any([x in self.stepMap for x in ['LHE', 'GEN', 'AOD']])
1699  self.loadDefaultOrSpecifiedCFF(sequence,self.NANOGENDefaultCFF)
1700  self.scheduleSequence(sequence.split('.')[-1],'nanoAOD_step')
1701  custom = "customizeNanoGEN" if fromGen else "customizeNanoGENFromMini"
1702  if self._options.runUnscheduled:
1703  self._options.customisation_file_unsch.insert(0, '.'.join([self.NANOGENDefaultCFF, custom]))
1704  else:
1705  self._options.customisation_file.insert(0, '.'.join([self.NANOGENDefaultCFF, custom]))
1706 
1707  def prepare_EI(self, sequence = None):
1708  ''' Enrich the schedule with event interpretation '''
1709  from Configuration.StandardSequences.EventInterpretation import EventInterpretation
1710  if sequence in EventInterpretation:
1711  self.EIDefaultCFF = EventInterpretation[sequence]
1712  sequence = 'EIsequence'
1713  else:
1714  raise Exception('Cannot set %s event interpretation'%( sequence) )
1715  self.loadDefaultOrSpecifiedCFF(sequence,self.EIDefaultCFF)
1716  self.scheduleSequence(sequence.split('.')[-1],'eventinterpretaion_step')
1717  return
1718 
1719  def prepare_SKIM(self, sequence = "all"):
1720  ''' Enrich the schedule with skimming fragments'''
1721  skimConfig = self.loadDefaultOrSpecifiedCFF(sequence,self.SKIMDefaultCFF)
1722  sequence = sequence.split('.')[-1]
1723 
1724  skimlist=sequence.split('+')
1725  ## support @Mu+DiJet+@Electron configuration via autoSkim.py
1726  from Configuration.Skimming.autoSkim import autoSkim
1727  self.expandMapping(skimlist,autoSkim)
1728 
1729  #print "dictionnary for skims:",skimConfig.__dict__
1730  for skim in skimConfig.__dict__:
1731  skimstream = getattr(skimConfig,skim)
1732  if isinstance(skimstream,cms.Path):
1733  #black list the alca path so that they do not appear in the cfg
1734  self.blacklist_paths.append(skimstream)
1735  if (not isinstance(skimstream,cms.FilteredStream)):
1736  continue
1737  shortname = skim.replace('SKIMStream','')
1738  if (sequence=="all"):
1739  self.addExtraStream(skim,skimstream)
1740  elif (shortname in skimlist):
1741  self.addExtraStream(skim,skimstream)
1742  #add a DQM eventcontent for this guy
1743  if self._options.datatier=='DQM':
1744  self.process.load(self.EVTCONTDefaultCFF)
1745  skimstreamDQM = cms.FilteredStream(
1746  responsible = skimstream.responsible,
1747  name = skimstream.name+'DQM',
1748  paths = skimstream.paths,
1749  selectEvents = skimstream.selectEvents,
1750  content = self._options.datatier+'EventContent',
1751  dataTier = cms.untracked.string(self._options.datatier)
1752  )
1753  self.addExtraStream(skim+'DQM',skimstreamDQM)
1754  for i in range(skimlist.count(shortname)):
1755  skimlist.remove(shortname)
1756 
1757 
1758 
1759  if (skimlist.__len__()!=0 and sequence!="all"):
1760  print('WARNING, possible typo with SKIM:'+'+'.join(skimlist))
1761  raise Exception('WARNING, possible typo with SKIM:'+'+'.join(skimlist))
1762 
1763  def prepare_USER(self, sequence = None):
1764  ''' Enrich the schedule with a user defined sequence '''
1765  self.loadDefaultOrSpecifiedCFF(sequence,self.USERDefaultCFF)
1766  self.scheduleSequence(sequence.split('.')[-1],'user_step')
1767  return
1768 
1769  def prepare_POSTRECO(self, sequence = None):
1770  """ Enrich the schedule with the postreco step """
1772  self.scheduleSequence('postreco_generator','postreco_step')
1773  return
1774 
1775 
1776  def prepare_VALIDATION(self, sequence = 'validation'):
1777  print(sequence,"in preparing validation")
1779  from Validation.Configuration.autoValidation import autoValidation
1780  #in case VALIDATION:something:somethingelse -> something,somethingelse
1781  sequence=sequence.split('.')[-1]
1782  if sequence.find(',')!=-1:
1783  prevalSeqName=sequence.split(',')[0].split('+')
1784  valSeqName=sequence.split(',')[1].split('+')
1785  self.expandMapping(prevalSeqName,autoValidation,index=0)
1786  self.expandMapping(valSeqName,autoValidation,index=1)
1787  else:
1788  if '@' in sequence:
1789  prevalSeqName=sequence.split('+')
1790  valSeqName=sequence.split('+')
1791  self.expandMapping(prevalSeqName,autoValidation,index=0)
1792  self.expandMapping(valSeqName,autoValidation,index=1)
1793  else:
1794  postfix=''
1795  if sequence:
1796  postfix='_'+sequence
1797  prevalSeqName=['prevalidation'+postfix]
1798  valSeqName=['validation'+postfix]
1799  if not hasattr(self.process,valSeqName[0]):
1800  prevalSeqName=['']
1801  valSeqName=[sequence]
1802 
1803  def NFI(index):
1804  ##name from index, required to keep backward compatibility
1805  if index==0:
1806  return ''
1807  else:
1808  return '%s'%index
1809 
1810 
1811  #rename the HLT process in validation steps
1812  if ('HLT' in self.stepMap and not self._options.fast) or self._options.hltProcess:
1813  for s in valSeqName+prevalSeqName:
1814  if s:
1816  for (i,s) in enumerate(prevalSeqName):
1817  if s:
1818  setattr(self.process,'prevalidation_step%s'%NFI(i), cms.Path( getattr(self.process, s)) )
1819  self.schedule.append(getattr(self.process,'prevalidation_step%s'%NFI(i)))
1820 
1821  for (i,s) in enumerate(valSeqName):
1822  setattr(self.process,'validation_step%s'%NFI(i), cms.EndPath( getattr(self.process, s)))
1823  self.schedule.append(getattr(self.process,'validation_step%s'%NFI(i)))
1824 
1825  #needed in case the miniAODValidation sequence is run starting from AODSIM
1826  if 'PAT' in self.stepMap and not 'RECO' in self.stepMap:
1827  return
1828 
1829  if not 'DIGI' in self.stepMap and not self._options.fast and not any(map( lambda s : s.startswith('genvalid'), valSeqName)):
1830  if self._options.restoreRNDSeeds==False and not self._options.restoreRNDSeeds==True:
1831  self._options.restoreRNDSeeds=True
1832 
1833  if not 'DIGI' in self.stepMap and not self._options.fast:
1834  self.executeAndRemember("process.mix.playback = True")
1835  self.executeAndRemember("process.mix.digitizers = cms.PSet()")
1836  self.executeAndRemember("for a in process.aliases: delattr(process, a)")
1837  self._options.customisation_file.append("SimGeneral/MixingModule/fullMixCustomize_cff.setCrossingFrameOn")
1838 
1839  if hasattr(self.process,"genstepfilter") and len(self.process.genstepfilter.triggerConditions):
1840  #will get in the schedule, smoothly
1841  for (i,s) in enumerate(valSeqName):
1842  getattr(self.process,'validation_step%s'%NFI(i)).insert(0, self.process.genstepfilter)
1843 
1844  return
1845 
1846 
1848  """Visitor that travels within a cms.Sequence, looks for a parameter and replace its value
1849  It will climb down within PSets, VPSets and VInputTags to find its target"""
1850  def __init__(self, paramSearch, paramReplace, verbose=False, whitelist=()):
1851  self._paramReplace = paramReplace
1852  self._paramSearch = paramSearch
1853  self._verbose = verbose
1854  self._whitelist = whitelist
1855 
1856  def doIt(self,pset,base):
1857  if isinstance(pset, cms._Parameterizable):
1858  for name in pset.parameters_().keys():
1859  # skip whitelisted parameters
1860  if name in self._whitelist:
1861  continue
1862  # if I use pset.parameters_().items() I get copies of the parameter values
1863  # so I can't modify the nested pset
1864  value = getattr(pset,name)
1865  type = value.pythonTypeName()
1866  if type in ('cms.PSet', 'cms.untracked.PSet'):
1867  self.doIt(value,base+"."+name)
1868  elif type in ('cms.VPSet', 'cms.untracked.VPSet'):
1869  for (i,ps) in enumerate(value): self.doIt(ps, "%s.%s[%d]"%(base,name,i) )
1870  elif type in ('cms.string', 'cms.untracked.string'):
1871  if value.value() == self._paramSearch:
1872  if self._verbose: print("set string process name %s.%s %s ==> %s"% (base, name, value, self._paramReplace))
1873  setattr(pset, name,self._paramReplace)
1874  elif type in ('cms.VInputTag', 'cms.untracked.VInputTag'):
1875  for (i,n) in enumerate(value):
1876  if not isinstance(n, cms.InputTag):
1877  n=cms.InputTag(n)
1878  if n.processName == self._paramSearch:
1879  # VInputTag can be declared as a list of strings, so ensure that n is formatted correctly
1880  if self._verbose:print("set process name %s.%s[%d] %s ==> %s " % (base, name, i, n, self._paramReplace))
1881  setattr(n,"processName",self._paramReplace)
1882  value[i]=n
1883  elif type in ('cms.vstring', 'cms.untracked.vstring'):
1884  for (i,n) in enumerate(value):
1885  if n==self._paramSearch:
1886  getattr(pset,name)[i]=self._paramReplace
1887  elif type in ('cms.InputTag', 'cms.untracked.InputTag'):
1888  if value.processName == self._paramSearch:
1889  if self._verbose: print("set process name %s.%s %s ==> %s " % (base, name, value, self._paramReplace))
1890  setattr(getattr(pset, name),"processName",self._paramReplace)
1891 
1892  def enter(self,visitee):
1893  label = ''
1894  try:
1895  label = visitee.label()
1896  except AttributeError:
1897  label = '<Module not in a Process>'
1898  except:
1899  label = 'other execption'
1900  self.doIt(visitee, label)
1901 
1902  def leave(self,visitee):
1903  pass
1904 
1905  #visit a sequence to repalce all input tags
1906  def renameInputTagsInSequence(self,sequence,oldT="rawDataCollector",newT="rawDataRepacker"):
1907  print("Replacing all InputTag %s => %s"%(oldT,newT))
1908  from PhysicsTools.PatAlgos.tools.helpers import massSearchReplaceAnyInputTag
1909  massSearchReplaceAnyInputTag(getattr(self.process,sequence),oldT,newT)
1910  loadMe='from PhysicsTools.PatAlgos.tools.helpers import massSearchReplaceAnyInputTag'
1911  if not loadMe in self.additionalCommands:
1912  self.additionalCommands.append(loadMe)
1913  self.additionalCommands.append('massSearchReplaceAnyInputTag(process.%s,"%s","%s",False,True)'%(sequence,oldT,newT))
1914 
1915  #change the process name used to address HLT results in any sequence
1916  def renameHLTprocessInSequence(self,sequence,proc=None,HLTprocess='HLT'):
1917  if self._options.hltProcess:
1918  proc=self._options.hltProcess
1919  else:
1920  proc=self.process.name_()
1921  if proc==HLTprocess: return
1922  # look up all module in dqm sequence
1923  print("replacing %s process name - sequence %s will use '%s'" % (HLTprocess,sequence, proc))
1924  getattr(self.process,sequence).visit(ConfigBuilder.MassSearchReplaceProcessNameVisitor(HLTprocess,proc,whitelist = ("subSystemFolder",)))
1925  if 'from Configuration.Applications.ConfigBuilder import ConfigBuilder' not in self.additionalCommands:
1926  self.additionalCommands.append('from Configuration.Applications.ConfigBuilder import ConfigBuilder')
1927  self.additionalCommands.append('process.%s.visit(ConfigBuilder.MassSearchReplaceProcessNameVisitor("%s", "%s", whitelist = ("subSystemFolder",)))'% (sequence,HLTprocess, proc))
1928 
1929 
1930  def expandMapping(self,seqList,mapping,index=None):
1931  maxLevel=20
1932  level=0
1933  while '@' in repr(seqList) and level<maxLevel:
1934  level+=1
1935  for specifiedCommand in seqList:
1936  if specifiedCommand.startswith('@'):
1937  location=specifiedCommand[1:]
1938  if not location in mapping:
1939  raise Exception("Impossible to map "+location+" from "+repr(mapping))
1940  mappedTo=mapping[location]
1941  if index!=None:
1942  mappedTo=mappedTo[index]
1943  seqList.remove(specifiedCommand)
1944  seqList.extend(mappedTo.split('+'))
1945  break;
1946  if level==maxLevel:
1947  raise Exception("Could not fully expand "+repr(seqList)+" from "+repr(mapping))
1948 
1949  def prepare_DQM(self, sequence = 'DQMOffline'):
1950  # this one needs replacement
1951 
1952  # any 'DQM' job should use DQMStore in non-legacy mode (but not HARVESTING)
1953  self.loadAndRemember("DQMServices/Core/DQMStoreNonLegacy_cff")
1955  sequenceList=sequence.split('.')[-1].split('+')
1956  postSequenceList=sequence.split('.')[-1].split('+')
1957  from DQMOffline.Configuration.autoDQM import autoDQM
1958  self.expandMapping(sequenceList,autoDQM,index=0)
1959  self.expandMapping(postSequenceList,autoDQM,index=1)
1960 
1961  if len(set(sequenceList))!=len(sequenceList):
1962  sequenceList=list(set(sequenceList))
1963  print("Duplicate entries for DQM:, using",sequenceList)
1964 
1965  pathName='dqmoffline_step'
1966  for (i,sequence) in enumerate(sequenceList):
1967  if (i!=0):
1968  pathName='dqmoffline_%d_step'%(i)
1969 
1970  if 'HLT' in self.stepMap.keys() or self._options.hltProcess:
1971  self.renameHLTprocessInSequence(sequence)
1972 
1973  setattr(self.process,pathName, cms.EndPath( getattr(self.process,sequence ) ) )
1974  self.schedule.append(getattr(self.process,pathName))
1975 
1976  if hasattr(self.process,"genstepfilter") and len(self.process.genstepfilter.triggerConditions):
1977  #will get in the schedule, smoothly
1978  getattr(self.process,pathName).insert(0,self.process.genstepfilter)
1979 
1980  pathName='dqmofflineOnPAT_step'
1981  for (i,sequence) in enumerate(postSequenceList):
1982  if (i!=0):
1983  pathName='dqmofflineOnPAT_%d_step'%(i)
1984 
1985  setattr(self.process,pathName, cms.EndPath( getattr(self.process, sequence ) ) )
1986  self.schedule.append(getattr(self.process,pathName))
1987 
1988  def prepare_HARVESTING(self, sequence = None):
1989  """ Enrich the process with harvesting step """
1990  self.DQMSaverCFF='Configuration/StandardSequences/DQMSaver'+self._options.harvesting+'_cff'
1991  self.loadAndRemember(self.DQMSaverCFF)
1992 
1993  harvestingConfig = self.loadDefaultOrSpecifiedCFF(sequence,self.HARVESTINGDefaultCFF)
1994  sequence = sequence.split('.')[-1]
1995 
1996  # decide which HARVESTING paths to use
1997  harvestingList = sequence.split("+")
1998  from DQMOffline.Configuration.autoDQM import autoDQM
1999  from Validation.Configuration.autoValidation import autoValidation
2000  import copy
2001  combined_mapping = copy.deepcopy( autoDQM )
2002  combined_mapping.update( autoValidation )
2003  self.expandMapping(harvestingList,combined_mapping,index=-1)
2004 
2005  if len(set(harvestingList))!=len(harvestingList):
2006  harvestingList=list(set(harvestingList))
2007  print("Duplicate entries for HARVESTING, using",harvestingList)
2008 
2009  for name in harvestingList:
2010  if not name in harvestingConfig.__dict__:
2011  print(name,"is not a possible harvesting type. Available are",harvestingConfig.__dict__.keys())
2012  continue
2013  harvestingstream = getattr(harvestingConfig,name)
2014  if isinstance(harvestingstream,cms.Path):
2015  self.schedule.append(harvestingstream)
2016  self.blacklist_paths.append(harvestingstream)
2017  if isinstance(harvestingstream,cms.Sequence):
2018  setattr(self.process,name+"_step",cms.Path(harvestingstream))
2019  self.schedule.append(getattr(self.process,name+"_step"))
2020 
2021  self.scheduleSequence('DQMSaver','dqmsave_step')
2022  return
2023 
2024  def prepare_ALCAHARVEST(self, sequence = None):
2025  """ Enrich the process with AlCaHarvesting step """
2026  harvestingConfig = self.loadAndRemember(self.ALCAHARVESTDefaultCFF)
2027  sequence=sequence.split(".")[-1]
2028 
2029  # decide which AlcaHARVESTING paths to use
2030  harvestingList = sequence.split("+")
2031 
2032 
2033 
2034  from Configuration.AlCa.autoPCL import autoPCL
2035  self.expandMapping(harvestingList,autoPCL)
2036 
2037  for name in harvestingConfig.__dict__:
2038  harvestingstream = getattr(harvestingConfig,name)
2039  if name in harvestingList and isinstance(harvestingstream,cms.Path):
2040  self.schedule.append(harvestingstream)
2041  if isinstance(getattr(harvestingConfig,"ALCAHARVEST" + name + "_dbOutput"), cms.VPSet) and \
2042  isinstance(getattr(harvestingConfig,"ALCAHARVEST" + name + "_metadata"), cms.VPSet):
2043  self.executeAndRemember("process.PoolDBOutputService.toPut.extend(process.ALCAHARVEST" + name + "_dbOutput)")
2044  self.executeAndRemember("process.pclMetadataWriter.recordsToMap.extend(process.ALCAHARVEST" + name + "_metadata)")
2045  else:
2046  self.executeAndRemember("process.PoolDBOutputService.toPut.append(process.ALCAHARVEST" + name + "_dbOutput)")
2047  self.executeAndRemember("process.pclMetadataWriter.recordsToMap.append(process.ALCAHARVEST" + name + "_metadata)")
2048  harvestingList.remove(name)
2049  # append the common part at the end of the sequence
2050  lastStep = getattr(harvestingConfig,"ALCAHARVESTDQMSaveAndMetadataWriter")
2051  self.schedule.append(lastStep)
2052 
2053  if len(harvestingList) != 0 and 'dummyHarvesting' not in harvestingList :
2054  print("The following harvesting could not be found : ", harvestingList)
2055  raise Exception("The following harvesting could not be found : "+str(harvestingList))
2056 
2057 
2058 
2059  def prepare_ENDJOB(self, sequence = 'endOfProcess'):
2060  self.loadDefaultOrSpecifiedCFF(sequence,self.ENDJOBDefaultCFF)
2061  self.scheduleSequenceAtEnd(sequence.split('.')[-1],'endjob_step')
2062  return
2063 
2065  self.process.reconstruction = cms.Path(self.process.reconstructionWithFamos)
2066  self.schedule.append(self.process.reconstruction)
2067 
2068 
2069  def build_production_info(self, evt_type, evtnumber):
2070  """ Add useful info for the production. """
2071  self.process.configurationMetadata=cms.untracked.PSet\
2072  (version=cms.untracked.string("$Revision: 1.19 $"),
2073  name=cms.untracked.string("Applications"),
2074  annotation=cms.untracked.string(evt_type+ " nevts:"+str(evtnumber))
2075  )
2076 
2077  self.addedObjects.append(("Production Info","configurationMetadata"))
2078 
2079 
2080  def create_process(self):
2081  self.pythonCfgCode = "# Auto generated configuration file\n"
2082  self.pythonCfgCode += "# using: \n# "+__version__[1:-1]+"\n# "+__source__[1:-1]+'\n'
2083  self.pythonCfgCode += "# with command line options: "+self._options.arguments+'\n'
2084  self.pythonCfgCode += "import FWCore.ParameterSet.Config as cms\n\n"
2085 
2086  # now set up the modifies
2087  modifiers=[]
2088  modifierStrings=[]
2089  modifierImports=[]
2090 
2091  if hasattr(self._options,"era") and self._options.era :
2092  # Multiple eras can be specified in a comma seperated list
2093  from Configuration.StandardSequences.Eras import eras
2094  for requestedEra in self._options.era.split(",") :
2095  modifierStrings.append(requestedEra)
2096  modifierImports.append(eras.pythonCfgLines[requestedEra])
2097  modifiers.append(getattr(eras,requestedEra))
2098 
2099 
2100  if hasattr(self._options,"procModifiers") and self._options.procModifiers:
2101  import importlib
2102  thingsImported=[]
2103  for pm in self._options.procModifiers.split(','):
2104  modifierStrings.append(pm)
2105  modifierImports.append('from Configuration.ProcessModifiers.'+pm+'_cff import '+pm)
2106  modifiers.append(getattr(importlib.import_module('Configuration.ProcessModifiers.'+pm+'_cff'),pm))
2107 
2108  self.pythonCfgCode += '\n'.join(modifierImports)+'\n\n'
2109  self.pythonCfgCode += "process = cms.Process('"+self._options.name+"'" # Start of the line, finished after the loop
2110 
2111 
2112  if len(modifierStrings)>0:
2113  self.pythonCfgCode+= ','+','.join(modifierStrings)
2114  self.pythonCfgCode+=')\n\n'
2115 
2116  #yes, the cfg code gets out of sync here if a process is passed in. That could be fixed in the future
2117  #assuming there is some way for the fwk to get the list of modifiers (and their stringified name)
2118  if self.process == None:
2119  if len(modifiers)>0:
2120  self.process = cms.Process(self._options.name,*modifiers)
2121  else:
2122  self.process = cms.Process(self._options.name)
2123 
2124 
2125 
2126 
2127  def prepare(self, doChecking = False):
2128  """ Prepare the configuration string and add missing pieces."""
2129 
2130  self.loadAndRemember(self.EVTCONTDefaultCFF) #load the event contents regardless
2131  self.addMaxEvents()
2132  if self.with_input:
2133  self.addSource()
2134  self.addStandardSequences()
2135  ##adding standard sequences might change the inputEventContent option and therefore needs to be finalized after
2136  self.completeInputCommand()
2137  self.addConditions()
2138 
2139 
2140  outputModuleCfgCode=""
2141  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:
2142  outputModuleCfgCode=self.addOutput()
2143 
2144  self.addCommon()
2145 
2146  self.pythonCfgCode += "# import of standard configurations\n"
2147  for module in self.imports:
2148  self.pythonCfgCode += ("process.load('"+module+"')\n")
2149 
2150  # production info
2151  if not hasattr(self.process,"configurationMetadata"):
2152  self.build_production_info(self._options.evt_type, self._options.number)
2153  else:
2154  #the PSet was added via a load
2155  self.addedObjects.append(("Production Info","configurationMetadata"))
2156 
2157  self.pythonCfgCode +="\n"
2158  for comment,object in self.addedObjects:
2159  if comment!="":
2160  self.pythonCfgCode += "\n# "+comment+"\n"
2161  self.pythonCfgCode += dumpPython(self.process,object)
2162 
2163  # dump the output definition
2164  self.pythonCfgCode += "\n# Output definition\n"
2165  self.pythonCfgCode += outputModuleCfgCode
2166 
2167  # dump all additional outputs (e.g. alca or skim streams)
2168  self.pythonCfgCode += "\n# Additional output definition\n"
2169  #I do not understand why the keys are not normally ordered.
2170  nl=sorted(self.additionalOutputs.keys())
2171  for name in nl:
2172  output = self.additionalOutputs[name]
2173  self.pythonCfgCode += "process.%s = %s" %(name, output.dumpPython())
2174  tmpOut = cms.EndPath(output)
2175  setattr(self.process,name+'OutPath',tmpOut)
2176  self.schedule.append(tmpOut)
2177 
2178  # dump all additional commands
2179  self.pythonCfgCode += "\n# Other statements\n"
2180  for command in self.additionalCommands:
2181  self.pythonCfgCode += command + "\n"
2182 
2183  #comma separated list of objects that deserve to be inlined in the configuration (typically from a modified config deep down)
2184  for object in self._options.inlineObjets.split(','):
2185  if not object:
2186  continue
2187  if not hasattr(self.process,object):
2188  print('cannot inline -'+object+'- : not known')
2189  else:
2190  self.pythonCfgCode +='\n'
2191  self.pythonCfgCode +=dumpPython(self.process,object)
2192 
2193  # dump all paths
2194  self.pythonCfgCode += "\n# Path and EndPath definitions\n"
2195  for path in self.process.paths:
2196  if getattr(self.process,path) not in self.blacklist_paths:
2197  self.pythonCfgCode += dumpPython(self.process,path)
2198 
2199  for endpath in self.process.endpaths:
2200  if getattr(self.process,endpath) not in self.blacklist_paths:
2201  self.pythonCfgCode += dumpPython(self.process,endpath)
2202 
2203  # dump the schedule
2204  self.pythonCfgCode += "\n# Schedule definition\n"
2205  result = "process.schedule = cms.Schedule("
2206 
2207  # handling of the schedule
2208  self.process.schedule = cms.Schedule()
2209  for item in self.schedule:
2210  if not isinstance(item, cms.Schedule):
2211  self.process.schedule.append(item)
2212  else:
2213  self.process.schedule.extend(item)
2214 
2215  if hasattr(self.process,"HLTSchedule"):
2216  beforeHLT = self.schedule[:self.schedule.index(self.process.HLTSchedule)]
2217  afterHLT = self.schedule[self.schedule.index(self.process.HLTSchedule)+1:]
2218  pathNames = ['process.'+p.label_() for p in beforeHLT]
2219  result += ','.join(pathNames)+')\n'
2220  result += 'process.schedule.extend(process.HLTSchedule)\n'
2221  pathNames = ['process.'+p.label_() for p in afterHLT]
2222  result += 'process.schedule.extend(['+','.join(pathNames)+'])\n'
2223  else:
2224  pathNames = ['process.'+p.label_() for p in self.schedule]
2225  result ='process.schedule = cms.Schedule('+','.join(pathNames)+')\n'
2226 
2227  self.pythonCfgCode += result
2228 
2229  for labelToAssociate in self.labelsToAssociate:
2230  self.process.schedule.associate(getattr(self.process, labelToAssociate))
2231  self.pythonCfgCode += 'process.schedule.associate(process.' + labelToAssociate + ')\n'
2232 
2233  from PhysicsTools.PatAlgos.tools.helpers import associatePatAlgosToolsTask
2235  self.pythonCfgCode+="from PhysicsTools.PatAlgos.tools.helpers import associatePatAlgosToolsTask\n"
2236  self.pythonCfgCode+="associatePatAlgosToolsTask(process)\n"
2237 
2238  if self._options.nThreads is not "1":
2239  self.pythonCfgCode +="\n"
2240  self.pythonCfgCode +="#Setup FWK for multithreaded\n"
2241  self.pythonCfgCode +="process.options.numberOfThreads=cms.untracked.uint32("+self._options.nThreads+")\n"
2242  self.pythonCfgCode +="process.options.numberOfStreams=cms.untracked.uint32("+self._options.nStreams+")\n"
2243  self.pythonCfgCode +="process.options.numberOfConcurrentLuminosityBlocks=cms.untracked.uint32("+self._options.nConcurrentLumis+")\n"
2244  self.process.options.numberOfThreads=cms.untracked.uint32(int(self._options.nThreads))
2245  self.process.options.numberOfStreams=cms.untracked.uint32(int(self._options.nStreams))
2246  self.process.options.numberOfConcurrentLuminosityBlocks=cms.untracked.uint32(int(self._options.nConcurrentLumis))
2247  #repacked version
2248  if self._options.isRepacked:
2249  self.pythonCfgCode +="\n"
2250  self.pythonCfgCode +="from Configuration.Applications.ConfigBuilder import MassReplaceInputTag\n"
2251  self.pythonCfgCode +="MassReplaceInputTag(process, new=\"rawDataMapperByLabel\", old=\"rawDataCollector\")\n"
2252  MassReplaceInputTag(self.process, new="rawDataMapperByLabel", old="rawDataCollector")
2253 
2254  # special treatment in case of production filter sequence 2/2
2255  if self.productionFilterSequence:
2256  self.pythonCfgCode +='# filter all path with the production filter sequence\n'
2257  self.pythonCfgCode +='for path in process.paths:\n'
2258  if len(self.conditionalPaths):
2259  self.pythonCfgCode +='\tif not path in %s: continue\n'%str(self.conditionalPaths)
2260  if len(self.excludedPaths):
2261  self.pythonCfgCode +='\tif path in %s: continue\n'%str(self.excludedPaths)
2262  self.pythonCfgCode +='\tgetattr(process,path).insert(0, process.%s)\n'%(self.productionFilterSequence,)
2263  pfs = getattr(self.process,self.productionFilterSequence)
2264  for path in self.process.paths:
2265  if not path in self.conditionalPaths: continue
2266  if path in self.excludedPaths: continue
2267  getattr(self.process,path).insert(0, pfs)
2268 
2269 
2270  # dump customise fragment
2271  self.pythonCfgCode += self.addCustomise()
2272 
2273  if self._options.runUnscheduled:
2274  # prune and delete paths
2275  #this is not supporting the blacklist at this point since I do not understand it
2276  self.pythonCfgCode+="#do not add changes to your config after this point (unless you know what you are doing)\n"
2277  self.pythonCfgCode+="from FWCore.ParameterSet.Utilities import convertToUnscheduled\n"
2278  self.pythonCfgCode+="process=convertToUnscheduled(process)\n"
2279 
2280  from FWCore.ParameterSet.Utilities import convertToUnscheduled
2282 
2283  self.pythonCfgCode += self.addCustomise(1)
2284 
2285  self.pythonCfgCode += self.addCustomiseCmdLine()
2286 
2287  if hasattr(self.process,"logErrorHarvester"):
2288  #configure logErrorHarvester to wait for same EDProducers to finish as the OutputModules
2289  self.pythonCfgCode +="\n#Have logErrorHarvester wait for the same EDProducers to finish as those providing data for the OutputModule\n"
2290  self.pythonCfgCode +="from FWCore.Modules.logErrorHarvester_cff import customiseLogErrorHarvesterUsingOutputCommands\n"
2291  self.pythonCfgCode +="process = customiseLogErrorHarvesterUsingOutputCommands(process)\n"
2292  from FWCore.Modules.logErrorHarvester_cff import customiseLogErrorHarvesterUsingOutputCommands
2294 
2295  # Temporary hack to put the early delete customization after
2296  # everything else
2297  #
2298  # FIXME: remove when no longer needed
2299  self.pythonCfgCode += "\n# Add early deletion of temporary data products to reduce peak memory need\n"
2300  self.pythonCfgCode += "from Configuration.StandardSequences.earlyDeleteSettings_cff import customiseEarlyDelete\n"
2301  self.pythonCfgCode += "process = customiseEarlyDelete(process)\n"
2302  self.pythonCfgCode += "# End adding early deletion\n"
2303  from Configuration.StandardSequences.earlyDeleteSettings_cff import customiseEarlyDelete
2304  self.process = customiseEarlyDelete(self.process)
2305 
2306  imports = cms.specialImportRegistry.getSpecialImports()
2307  if len(imports) > 0:
2308  #need to inject this at the top
2309  index = self.pythonCfgCode.find("import FWCore.ParameterSet.Config")
2310  #now find the end of line
2311  index = self.pythonCfgCode.find("\n",index)
2312  self.pythonCfgCode = self.pythonCfgCode[:index]+ "\n" + "\n".join(imports)+"\n" +self.pythonCfgCode[index:]
2313 
2314 
2315  # make the .io file
2316 
2317  if self._options.io:
2318  #io=open(self._options.python_filename.replace('.py','.io'),'w')
2319  if not self._options.io.endswith('.io'): self._option.io+='.io'
2320  io=open(self._options.io,'w')
2321  ioJson={}
2322  if hasattr(self.process.source,"fileNames"):
2323  if len(self.process.source.fileNames.value()):
2324  ioJson['primary']=self.process.source.fileNames.value()
2325  if hasattr(self.process.source,"secondaryFileNames"):
2326  if len(self.process.source.secondaryFileNames.value()):
2327  ioJson['secondary']=self.process.source.secondaryFileNames.value()
2328  if self._options.pileup_input and (self._options.pileup_input.startswith('dbs:') or self._options.pileup_input.startswith('das:')):
2329  ioJson['pileup']=self._options.pileup_input[4:]
2330  for (o,om) in self.process.outputModules_().items():
2331  ioJson[o]=om.fileName.value()
2332  ioJson['GT']=self.process.GlobalTag.globaltag.value()
2333  if self.productionFilterSequence:
2334  ioJson['filter']=self.productionFilterSequence
2335  import json
2336  io.write(json.dumps(ioJson))
2337  return
2338 
def load(self, includeFile)
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:37
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 visit(visitdir)
Retrieve data from a perf suite output (sub) directory, only examines TimeSize at the moment...
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:18
def prepare_ALCAHARVEST(self, sequence=None)
def defineMixing(dict)
Definition: Mixing.py:187
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_NANOGEN(self, sequence="nanoAOD")
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)
double split
Definition: MVATrainer.cc:139
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