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