CMS 3D CMS Logo

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