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  else:
1845  _seqToSchedule.append(_subSeq)
1846  self.scheduleSequence('+'.join(_seqToSchedule), 'nanoAOD_step')
1847 
1848  # add the customisations
1849  for custom in _nanoCustoms:
1850  custom_path = custom if '.' in custom else '.'.join([_nanoCff,custom])
1851  # customization order can be important for NANO, here later specified customise take precedence
1852  self._options.customisation_file.append(custom_path)
1853  if self._options.hltProcess:
1854  if len(self._options.customise_commands) > 1:
1855  self._options.customise_commands = self._options.customise_commands + " \n"
1856  self._options.customise_commands = self._options.customise_commands + "process.unpackedPatTrigger.triggerResults= cms.InputTag( 'TriggerResults::"+self._options.hltProcess+"' )\n"
1857 
1858  def prepare_NANOGEN(self, stepSpec = "nanoAOD"):
1859  ''' Enrich the schedule with NANOGEN '''
1860  # TODO: Need to modify this based on the input file type
1861  fromGen = any([x in self.stepMap for x in ['LHE', 'GEN', 'AOD']])
1862  _,_nanogenSeq,_nanogenCff = self.loadDefaultOrSpecifiedCFF(stepSpec,self.NANOGENDefaultCFF)
1863  self.scheduleSequence(_nanogenSeq,'nanoAOD_step')
1864  custom = "customizeNanoGEN" if fromGen else "customizeNanoGENFromMini"
1865  if self._options.runUnscheduled:
1866  self._options.customisation_file_unsch.insert(0, '.'.join([_nanogenCff, custom]))
1867  else:
1868  self._options.customisation_file.insert(0, '.'.join([_nanogenCff, custom]))
1869 
1870  def prepare_SKIM(self, stepSpec = "all"):
1871  ''' Enrich the schedule with skimming fragments'''
1872  skimConfig,sequence,_ = self.loadDefaultOrSpecifiedCFF(stepSpec,self.SKIMDefaultCFF)
1873 
1874  stdHLTProcName = 'HLT'
1875  newHLTProcName = self._options.hltProcess
1876  customiseForReHLT = (newHLTProcName or (stdHLTProcName in self.stepMap)) and (newHLTProcName != stdHLTProcName)
1877  if customiseForReHLT:
1878  print("replacing %s process name - step SKIM:%s will use '%s'" % (stdHLTProcName, sequence, newHLTProcName))
1879 
1880 
1881  from Configuration.Skimming.autoSkim import autoSkim
1882  skimlist = sequence.split('+')
1883  self.expandMapping(skimlist,autoSkim)
1884 
1885  #print("dictionary for skims:", skimConfig.__dict__)
1886  for skim in skimConfig.__dict__:
1887  skimstream = getattr(skimConfig, skim)
1888 
1889  # blacklist AlCa paths so that they do not appear in the cfg
1890  if isinstance(skimstream, cms.Path):
1891  self.blacklist_paths.append(skimstream)
1892  # if enabled, apply "hltProcess" renaming to Sequences
1893  elif isinstance(skimstream, cms.Sequence):
1894  if customiseForReHLT:
1895  self.renameHLTprocessInSequence(skim, proc = newHLTProcName, HLTprocess = stdHLTProcName, verbosityLevel = 0)
1896 
1897  if not isinstance(skimstream, cms.FilteredStream):
1898  continue
1899 
1900  shortname = skim.replace('SKIMStream','')
1901  if (sequence=="all"):
1902  self.addExtraStream(skim,skimstream)
1903  elif (shortname in skimlist):
1904  self.addExtraStream(skim,skimstream)
1905  #add a DQM eventcontent for this guy
1906  if self._options.datatier=='DQM':
1907  self.process.load(self.EVTCONTDefaultCFF)
1908  skimstreamDQM = cms.FilteredStream(
1909  responsible = skimstream.responsible,
1910  name = skimstream.name+'DQM',
1911  paths = skimstream.paths,
1912  selectEvents = skimstream.selectEvents,
1913  content = self._options.datatier+'EventContent',
1914  dataTier = cms.untracked.string(self._options.datatier)
1915  )
1916  self.addExtraStream(skim+'DQM',skimstreamDQM)
1917  for i in range(skimlist.count(shortname)):
1918  skimlist.remove(shortname)
1919 
1920  if (skimlist.__len__()!=0 and sequence!="all"):
1921  print('WARNING, possible typo with SKIM:'+'+'.join(skimlist))
1922  raise Exception('WARNING, possible typo with SKIM:'+'+'.join(skimlist))
1923 
1924 
1925  def prepare_USER(self, stepSpec = None):
1926  ''' Enrich the schedule with a user defined sequence '''
1927  _,_userSeq,_ = self.loadDefaultOrSpecifiedCFF(stepSpec,self.USERDefaultCFF)
1928  self.scheduleSequence(_userSeq,'user_step')
1929  return
1930 
1931  def prepare_POSTRECO(self, stepSpec = None):
1932  """ Enrich the schedule with the postreco step """
1934  self.scheduleSequence('postreco_generator','postreco_step')
1935  return
1936 
1937 
1938  def prepare_VALIDATION(self, stepSpec = 'validation'):
1939  print(f"{stepSpec} in preparing validation")
1940  _,sequence,_ = self.loadDefaultOrSpecifiedCFF(stepSpec,self.VALIDATIONDefaultCFF)
1941  from Validation.Configuration.autoValidation import autoValidation
1942  #in case VALIDATION:something:somethingelse -> something,somethingelse
1943  if sequence.find(',')!=-1:
1944  prevalSeqName=sequence.split(',')[0].split('+')
1945  valSeqName=sequence.split(',')[1].split('+')
1946  self.expandMapping(prevalSeqName,autoValidation,index=0)
1947  self.expandMapping(valSeqName,autoValidation,index=1)
1948  else:
1949  if '@' in sequence:
1950  prevalSeqName=sequence.split('+')
1951  valSeqName=sequence.split('+')
1952  self.expandMapping(prevalSeqName,autoValidation,index=0)
1953  self.expandMapping(valSeqName,autoValidation,index=1)
1954  else:
1955  postfix=''
1956  if sequence:
1957  postfix='_'+sequence
1958  prevalSeqName=['prevalidation'+postfix]
1959  valSeqName=['validation'+postfix]
1960  if not hasattr(self.process,valSeqName[0]):
1961  prevalSeqName=['']
1962  valSeqName=[sequence]
1963 
1964  def NFI(index):
1965 
1966  if index==0:
1967  return ''
1968  else:
1969  return '%s'%index
1970 
1971 
1972  #rename the HLT process in validation steps
1973  if ('HLT' in self.stepMap and not self._options.fast) or self._options.hltProcess:
1974  for s in valSeqName+prevalSeqName:
1975  if s:
1977  for (i,s) in enumerate(prevalSeqName):
1978  if s:
1979  setattr(self.process,'prevalidation_step%s'%NFI(i), cms.Path( getattr(self.process, s)) )
1980  self.schedule.append(getattr(self.process,'prevalidation_step%s'%NFI(i)))
1981 
1982  for (i,s) in enumerate(valSeqName):
1983  setattr(self.process,'validation_step%s'%NFI(i), cms.EndPath( getattr(self.process, s)))
1984  self.schedule.append(getattr(self.process,'validation_step%s'%NFI(i)))
1985 
1986  #needed in case the miniAODValidation sequence is run starting from AODSIM
1987  if 'PAT' in self.stepMap and not 'RECO' in self.stepMap:
1988  return
1989 
1990  if not 'DIGI' in self.stepMap and not self._options.fast and not any(map( lambda s : s.startswith('genvalid'), valSeqName)):
1991  if self._options.restoreRNDSeeds==False and not self._options.restoreRNDSeeds==True:
1992  self._options.restoreRNDSeeds=True
1993 
1994  if not 'DIGI' in self.stepMap and not self._options.isData and not self._options.fast:
1995  self.executeAndRemember("process.mix.playback = True")
1996  self.executeAndRemember("process.mix.digitizers = cms.PSet()")
1997  self.executeAndRemember("for a in process.aliases: delattr(process, a)")
1998  self._options.customisation_file.append("SimGeneral/MixingModule/fullMixCustomize_cff.setCrossingFrameOn")
1999 
2000  if hasattr(self.process,"genstepfilter") and len(self.process.genstepfilter.triggerConditions):
2001  #will get in the schedule, smoothly
2002  for (i,s) in enumerate(valSeqName):
2003  getattr(self.process,'validation_step%s'%NFI(i)).insert(0, self.process.genstepfilter)
2004 
2005  return
2006 
2007 
2009  """Visitor that travels within a cms.Sequence, looks for a parameter and replace its value
2010  It will climb down within PSets, VPSets and VInputTags to find its target"""
2011  def __init__(self, paramSearch, paramReplace, verbose=False, whitelist=()):
2012  self._paramReplace = paramReplace
2013  self._paramSearch = paramSearch
2014  self._verbose = verbose
2015  self._whitelist = whitelist
2017  def doIt(self, pset, base):
2018  if isinstance(pset, cms._Parameterizable):
2019  for name in pset.parameters_().keys():
2020  # skip whitelisted parameters
2021  if name in self._whitelist:
2022  continue
2023  # if I use pset.parameters_().items() I get copies of the parameter values
2024  # so I can't modify the nested pset
2025  value = getattr(pset, name)
2026  valueType = type(value)
2027  if valueType in [cms.PSet, cms.untracked.PSet, cms.EDProducer]:
2028  self.doIt(value,base+"."+name)
2029  elif valueType in [cms.VPSet, cms.untracked.VPSet]:
2030  for (i,ps) in enumerate(value): self.doIt(ps, "%s.%s[%d]"%(base,name,i) )
2031  elif valueType in [cms.string, cms.untracked.string]:
2032  if value.value() == self._paramSearch:
2033  if self._verbose: print("set string process name %s.%s %s ==> %s"% (base, name, value, self._paramReplace))
2034  setattr(pset, name,self._paramReplace)
2035  elif valueType in [cms.VInputTag, cms.untracked.VInputTag]:
2036  for (i,n) in enumerate(value):
2037  if not isinstance(n, cms.InputTag):
2038  n=cms.InputTag(n)
2039  if n.processName == self._paramSearch:
2040  # VInputTag can be declared as a list of strings, so ensure that n is formatted correctly
2041  if self._verbose:print("set process name %s.%s[%d] %s ==> %s " % (base, name, i, n, self._paramReplace))
2042  setattr(n,"processName",self._paramReplace)
2043  value[i]=n
2044  elif valueType in [cms.vstring, cms.untracked.vstring]:
2045  for (i,n) in enumerate(value):
2046  if n==self._paramSearch:
2047  getattr(pset,name)[i]=self._paramReplace
2048  elif valueType in [cms.InputTag, cms.untracked.InputTag]:
2049  if value.processName == self._paramSearch:
2050  if self._verbose: print("set process name %s.%s %s ==> %s " % (base, name, value, self._paramReplace))
2051  setattr(getattr(pset, name),"processName",self._paramReplace)
2052 
2053  def enter(self,visitee):
2054  label = ''
2055  try:
2056  label = visitee.label()
2057  except AttributeError:
2058  label = '<Module not in a Process>'
2059  except:
2060  label = 'other execption'
2061  self.doIt(visitee, label)
2062 
2063  def leave(self,visitee):
2064  pass
2065 
2066  #visit a sequence to repalce all input tags
2067  def renameInputTagsInSequence(self,sequence,oldT="rawDataCollector",newT="rawDataRepacker"):
2068  print("Replacing all InputTag %s => %s"%(oldT,newT))
2069  from PhysicsTools.PatAlgos.tools.helpers import massSearchReplaceAnyInputTag
2070  massSearchReplaceAnyInputTag(getattr(self.process,sequence),oldT,newT)
2071  loadMe='from PhysicsTools.PatAlgos.tools.helpers import massSearchReplaceAnyInputTag'
2072  if not loadMe in self.additionalCommands:
2073  self.additionalCommands.append(loadMe)
2074  self.additionalCommands.append('massSearchReplaceAnyInputTag(process.%s,"%s","%s",False,True)'%(sequence,oldT,newT))
2075 
2076  #change the process name used to address HLT results in any sequence
2077  def renameHLTprocessInSequence(self, sequence, proc=None, HLTprocess='HLT', verbosityLevel=1):
2078  if proc == None:
2079  proc = self._options.hltProcess if self._options.hltProcess else self.process.name_()
2080  if proc == HLTprocess:
2081  return
2082  # look up all module in sequence
2083  if verbosityLevel > 0:
2084  print("replacing %s process name - sequence %s will use '%s'" % (HLTprocess, sequence, proc))
2085  verboseVisit = (verbosityLevel > 1)
2086  getattr(self.process,sequence).visit(
2087  ConfigBuilder.MassSearchReplaceProcessNameVisitor(HLTprocess, proc, whitelist = ("subSystemFolder",), verbose = verboseVisit))
2088  if 'from Configuration.Applications.ConfigBuilder import ConfigBuilder' not in self.additionalCommands:
2089  self.additionalCommands.append('from Configuration.Applications.ConfigBuilder import ConfigBuilder')
2091  'process.%s.visit(ConfigBuilder.MassSearchReplaceProcessNameVisitor("%s", "%s", whitelist = ("subSystemFolder",), verbose = %s))'
2092  % (sequence, HLTprocess, proc, verboseVisit))
2093 
2094  def expandMapping(self,seqList,mapping,index=None):
2095  maxLevel=30
2096  level=0
2097  while '@' in repr(seqList) and level<maxLevel:
2098  level+=1
2099  for specifiedCommand in seqList:
2100  if specifiedCommand.startswith('@'):
2101  location=specifiedCommand[1:]
2102  if not location in mapping:
2103  raise Exception("Impossible to map "+location+" from "+repr(mapping))
2104  mappedTo=mapping[location]
2105  if index!=None:
2106  mappedTo=mappedTo[index]
2107  seqList.remove(specifiedCommand)
2108  seqList.extend(mappedTo.split('+'))
2109  break;
2110  if level==maxLevel:
2111  raise Exception("Could not fully expand "+repr(seqList)+" from "+repr(mapping))
2112 
2113  def prepare_DQM(self, stepSpec = 'DQMOffline'):
2114  # this one needs replacement
2115 
2116  # any 'DQM' job should use DQMStore in non-legacy mode (but not HARVESTING)
2117  self.loadAndRemember("DQMServices/Core/DQMStoreNonLegacy_cff")
2118  _,_dqmSeq,_ = self.loadDefaultOrSpecifiedCFF(stepSpec,self.DQMOFFLINEDefaultCFF)
2119  sequenceList=_dqmSeq.split('+')
2120  postSequenceList=_dqmSeq.split('+')
2121  from DQMOffline.Configuration.autoDQM import autoDQM
2122  self.expandMapping(sequenceList,autoDQM,index=0)
2123  self.expandMapping(postSequenceList,autoDQM,index=1)
2124 
2125  if len(set(sequenceList))!=len(sequenceList):
2126  sequenceList=list(OrderedSet(sequenceList))
2127  print("Duplicate entries for DQM:, using",sequenceList)
2128 
2129  pathName='dqmoffline_step'
2130  for (i,_sequence) in enumerate(sequenceList):
2131  if (i!=0):
2132  pathName='dqmoffline_%d_step'%(i)
2133 
2134  if 'HLT' in self.stepMap.keys() or self._options.hltProcess:
2135  self.renameHLTprocessInSequence(_sequence)
2136 
2137  setattr(self.process,pathName, cms.EndPath( getattr(self.process,_sequence ) ) )
2138  self.schedule.append(getattr(self.process,pathName))
2139 
2140  if hasattr(self.process,"genstepfilter") and len(self.process.genstepfilter.triggerConditions):
2141  #will get in the schedule, smoothly
2142  getattr(self.process,pathName).insert(0,self.process.genstepfilter)
2143 
2144 
2145  pathName='dqmofflineOnPAT_step'
2146  for (i,_sequence) in enumerate(postSequenceList):
2147  #Fix needed to avoid duplication of sequences not defined in autoDQM or without a PostDQM
2148  if (sequenceList[i]==postSequenceList[i]):
2149  continue
2150  if (i!=0):
2151  pathName='dqmofflineOnPAT_%d_step'%(i)
2152 
2153  setattr(self.process,pathName, cms.EndPath( getattr(self.process, _sequence ) ) )
2154  self.schedule.append(getattr(self.process,pathName))
2155 
2156  def prepare_HARVESTING(self, stepSpec = None):
2157  """ Enrich the process with harvesting step """
2158  self.DQMSaverCFF='Configuration/StandardSequences/DQMSaver'+self._options.harvesting+'_cff'
2160 
2161  harvestingConfig,sequence,_ = self.loadDefaultOrSpecifiedCFF(stepSpec,self.HARVESTINGDefaultCFF)
2162 
2163  # decide which HARVESTING paths to use
2164  harvestingList = sequence.split("+")
2165  from DQMOffline.Configuration.autoDQM import autoDQM
2166  from Validation.Configuration.autoValidation import autoValidation
2167  import copy
2168  combined_mapping = copy.deepcopy( autoDQM )
2169  combined_mapping.update( autoValidation )
2170  self.expandMapping(harvestingList,combined_mapping,index=-1)
2171 
2172  if len(set(harvestingList))!=len(harvestingList):
2173  harvestingList=list(OrderedSet(harvestingList))
2174  print("Duplicate entries for HARVESTING, using",harvestingList)
2175 
2176  for name in harvestingList:
2177  if not name in harvestingConfig.__dict__:
2178  print(name,"is not a possible harvesting type. Available are",harvestingConfig.__dict__.keys())
2179  # trigger hard error, like for other sequence types
2180  getattr(self.process, name)
2181  continue
2182  harvestingstream = getattr(harvestingConfig,name)
2183  if isinstance(harvestingstream,cms.Path):
2184  self.schedule.append(harvestingstream)
2185  self.blacklist_paths.append(harvestingstream)
2186  if isinstance(harvestingstream,cms.Sequence):
2187  setattr(self.process,name+"_step",cms.Path(harvestingstream))
2188  self.schedule.append(getattr(self.process,name+"_step"))
2189 
2190  # # NOTE: the "hltProcess" option currently does nothing in the HARVEST step
2191  # if self._options.hltProcess or ('HLT' in self.stepMap):
2192  # pass
2193 
2194  self.scheduleSequence('DQMSaver','dqmsave_step')
2195  return
2196 
2197  def prepare_ALCAHARVEST(self, stepSpec = None):
2198  """ Enrich the process with AlCaHarvesting step """
2199  harvestingConfig = self.loadAndRemember(self.ALCAHARVESTDefaultCFF)
2200  sequence=stepSpec.split(".")[-1]
2201 
2202  # decide which AlcaHARVESTING paths to use
2203  harvestingList = sequence.split("+")
2204 
2205 
2206 
2207  from Configuration.AlCa.autoPCL import autoPCL
2208  self.expandMapping(harvestingList,autoPCL)
2209 
2210  for name in harvestingConfig.__dict__:
2211  harvestingstream = getattr(harvestingConfig,name)
2212  if name in harvestingList and isinstance(harvestingstream,cms.Path):
2213  self.schedule.append(harvestingstream)
2214  if isinstance(getattr(harvestingConfig,"ALCAHARVEST" + name + "_dbOutput"), cms.VPSet) and \
2215  isinstance(getattr(harvestingConfig,"ALCAHARVEST" + name + "_metadata"), cms.VPSet):
2216  self.executeAndRemember("process.PoolDBOutputService.toPut.extend(process.ALCAHARVEST" + name + "_dbOutput)")
2217  self.executeAndRemember("process.pclMetadataWriter.recordsToMap.extend(process.ALCAHARVEST" + name + "_metadata)")
2218  else:
2219  self.executeAndRemember("process.PoolDBOutputService.toPut.append(process.ALCAHARVEST" + name + "_dbOutput)")
2220  self.executeAndRemember("process.pclMetadataWriter.recordsToMap.append(process.ALCAHARVEST" + name + "_metadata)")
2221  harvestingList.remove(name)
2222  # append the common part at the end of the sequence
2223  lastStep = getattr(harvestingConfig,"ALCAHARVESTDQMSaveAndMetadataWriter")
2224  self.schedule.append(lastStep)
2225 
2226  if len(harvestingList) != 0 and 'dummyHarvesting' not in harvestingList :
2227  print("The following harvesting could not be found : ", harvestingList)
2228  raise Exception("The following harvesting could not be found : "+str(harvestingList))
2229 
2230 
2231 
2232  def prepare_ENDJOB(self, stepSpec = 'endOfProcess'):
2233  _,_endjobSeq,_=self.loadDefaultOrSpecifiedCFF(stepSpec,self.ENDJOBDefaultCFF)
2234  self.scheduleSequenceAtEnd(_endjobSeq,'endjob_step')
2235  return
2236 
2237  def finalizeFastSimHLT(self):
2238  self.process.reconstruction = cms.Path(self.process.reconstructionWithFamos)
2239  self.schedule.append(self.process.reconstruction)
2240 
2241 
2242  def build_production_info(self, evt_type, evtnumber):
2243  """ Add useful info for the production. """
2244  self.process.configurationMetadata=cms.untracked.PSet\
2245  (version=cms.untracked.string("$Revision: 1.19 $"),
2246  name=cms.untracked.string("Applications"),
2247  annotation=cms.untracked.string(evt_type+ " nevts:"+str(evtnumber))
2248  )
2249 
2250  self.addedObjects.append(("Production Info","configurationMetadata"))
2251 
2252 
2253  def create_process(self):
2254  self.pythonCfgCode = "# Auto generated configuration file\n"
2255  self.pythonCfgCode += "# using: \n# "+__version__[1:-1]+"\n# "+__source__[1:-1]+'\n'
2256  self.pythonCfgCode += "# with command line options: "+self._options.arguments+'\n'
2257  self.pythonCfgCode += "import FWCore.ParameterSet.Config as cms\n\n"
2258 
2259  # now set up the modifies
2260  modifiers=[]
2261  modifierStrings=[]
2262  modifierImports=[]
2263 
2264  if hasattr(self._options,"era") and self._options.era :
2265  # Multiple eras can be specified in a comma seperated list
2266  from Configuration.StandardSequences.Eras import eras
2267  for requestedEra in self._options.era.split(",") :
2268  modifierStrings.append(requestedEra)
2269  modifierImports.append(eras.pythonCfgLines[requestedEra])
2270  modifiers.append(getattr(eras,requestedEra))
2271 
2272 
2273  if hasattr(self._options,"procModifiers") and self._options.procModifiers:
2274  import importlib
2275  thingsImported=[]
2276  for c in self._options.procModifiers:
2277  thingsImported.extend(c.split(","))
2278  for pm in thingsImported:
2279  modifierStrings.append(pm)
2280  modifierImports.append('from Configuration.ProcessModifiers.'+pm+'_cff import '+pm)
2281  modifiers.append(getattr(importlib.import_module('Configuration.ProcessModifiers.'+pm+'_cff'),pm))
2282 
2283  self.pythonCfgCode += '\n'.join(modifierImports)+'\n\n'
2284  self.pythonCfgCode += "process = cms.Process('"+self._options.name+"'" # Start of the line, finished after the loop
2285 
2286 
2287  if len(modifierStrings)>0:
2288  self.pythonCfgCode+= ','+','.join(modifierStrings)
2289  self.pythonCfgCode+=')\n\n'
2290 
2291  #yes, the cfg code gets out of sync here if a process is passed in. That could be fixed in the future
2292  #assuming there is some way for the fwk to get the list of modifiers (and their stringified name)
2293  if self.process == None:
2294  if len(modifiers)>0:
2295  self.process = cms.Process(self._options.name,*modifiers)
2296  else:
2297  self.process = cms.Process(self._options.name)
2298 
2299 
2300 
2301 
2302  def prepare(self, doChecking = False):
2303  """ Prepare the configuration string and add missing pieces."""
2304 
2305  self.loadAndRemember(self.EVTCONTDefaultCFF) #load the event contents regardless
2306  self.addMaxEvents()
2307  if self.with_input:
2308  self.addSource()
2309  self.addStandardSequences()
2310 
2311  self.completeInputCommand()
2312  self.addConditions()
2313 
2314 
2315  outputModuleCfgCode=""
2316  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:
2317  outputModuleCfgCode=self.addOutput()
2318 
2319  self.addCommon()
2320 
2321  self.pythonCfgCode += "# import of standard configurations\n"
2322  for module in self.imports:
2323  self.pythonCfgCode += ("process.load('"+module+"')\n")
2324 
2325  # production info
2326  if not hasattr(self.process,"configurationMetadata"):
2327  self.build_production_info(self._options.evt_type, self._options.number)
2328  else:
2329  #the PSet was added via a load
2330  self.addedObjects.append(("Production Info","configurationMetadata"))
2331 
2332  self.pythonCfgCode +="\n"
2333  for comment,object in self.addedObjects:
2334  if comment!="":
2335  self.pythonCfgCode += "\n# "+comment+"\n"
2336  self.pythonCfgCode += dumpPython(self.process,object)
2337 
2338  # dump the output definition
2339  self.pythonCfgCode += "\n# Output definition\n"
2340  self.pythonCfgCode += outputModuleCfgCode
2341 
2342  # dump all additional outputs (e.g. alca or skim streams)
2343  self.pythonCfgCode += "\n# Additional output definition\n"
2344  #I do not understand why the keys are not normally ordered.
2345  nl=sorted(self.additionalOutputs.keys())
2346  for name in nl:
2347  output = self.additionalOutputs[name]
2348  self.pythonCfgCode += "process.%s = %s" %(name, output.dumpPython())
2349  tmpOut = cms.EndPath(output)
2350  setattr(self.process,name+'OutPath',tmpOut)
2351  self.schedule.append(tmpOut)
2352 
2353  # dump all additional commands
2354  self.pythonCfgCode += "\n# Other statements\n"
2355  for command in self.additionalCommands:
2356  self.pythonCfgCode += command + "\n"
2357 
2358  #comma separated list of objects that deserve to be inlined in the configuration (typically from a modified config deep down)
2359  for object in self._options.inlineObjects.split(','):
2360  if not object:
2361  continue
2362  if not hasattr(self.process,object):
2363  print('cannot inline -'+object+'- : not known')
2364  else:
2365  self.pythonCfgCode +='\n'
2366  self.pythonCfgCode +=dumpPython(self.process,object)
2367 
2368  if self._options.pileup=='HiMixEmbGEN':
2369  self.pythonCfgCode += "\nprocess.generator.embeddingMode=cms.int32(1)\n"
2370 
2371  # dump all paths
2372  self.pythonCfgCode += "\n# Path and EndPath definitions\n"
2373  for path in self.process.paths:
2374  if getattr(self.process,path) not in self.blacklist_paths:
2375  self.pythonCfgCode += dumpPython(self.process,path)
2376 
2377  for endpath in self.process.endpaths:
2378  if getattr(self.process,endpath) not in self.blacklist_paths:
2379  self.pythonCfgCode += dumpPython(self.process,endpath)
2380 
2381  # dump the schedule
2382  self.pythonCfgCode += "\n# Schedule definition\n"
2383 
2384  # handling of the schedule
2385  pathNames = ['process.'+p.label_() for p in self.schedule]
2386  if self.process.schedule == None:
2387  self.process.schedule = cms.Schedule()
2388  for item in self.schedule:
2389  self.process.schedule.append(item)
2390  result = 'process.schedule = cms.Schedule('+','.join(pathNames)+')\n'
2391  else:
2392  if not isinstance(self.scheduleIndexOfFirstHLTPath, int):
2393  raise Exception('the schedule was imported from a cff in HLTrigger.Configuration, but the final index of the first HLT path is undefined')
2394 
2395  for index, item in enumerate(self.schedule):
2396  if index < self.scheduleIndexOfFirstHLTPath:
2397  self.process.schedule.insert(index, item)
2398  else:
2399  self.process.schedule.append(item)
2400 
2401  result = "# process.schedule imported from cff in HLTrigger.Configuration\n"
2402  for index, item in enumerate(pathNames[:self.scheduleIndexOfFirstHLTPath]):
2403  result += 'process.schedule.insert('+str(index)+', '+item+')\n'
2404  if self.scheduleIndexOfFirstHLTPath < len(pathNames):
2405  result += 'process.schedule.extend(['+','.join(pathNames[self.scheduleIndexOfFirstHLTPath:])+'])\n'
2406 
2407  self.pythonCfgCode += result
2408 
2409  for labelToAssociate in self.labelsToAssociate:
2410  self.process.schedule.associate(getattr(self.process, labelToAssociate))
2411  self.pythonCfgCode += 'process.schedule.associate(process.' + labelToAssociate + ')\n'
2412 
2413  from PhysicsTools.PatAlgos.tools.helpers import associatePatAlgosToolsTask
2415  self.pythonCfgCode+="from PhysicsTools.PatAlgos.tools.helpers import associatePatAlgosToolsTask\n"
2416  self.pythonCfgCode+="associatePatAlgosToolsTask(process)\n"
2417 
2418  overrideThreads = (self._options.nThreads != 1)
2419  overrideConcurrentLumis = (self._options.nConcurrentLumis != defaultOptions.nConcurrentLumis)
2420  overrideConcurrentIOVs = (self._options.nConcurrentIOVs != defaultOptions.nConcurrentIOVs)
2421 
2422  if overrideThreads or overrideConcurrentLumis or overrideConcurrentIOVs:
2423  self.pythonCfgCode +="\n"
2424  self.pythonCfgCode +="#Setup FWK for multithreaded\n"
2425  if overrideThreads:
2426  self.pythonCfgCode +="process.options.numberOfThreads = {}\n".format(self._options.nThreads)
2427  self.pythonCfgCode +="process.options.numberOfStreams = {}\n".format(self._options.nStreams)
2428  self.process.options.numberOfThreads = self._options.nThreads
2429  self.process.options.numberOfStreams = self._options.nStreams
2430  if overrideConcurrentLumis:
2431  self.pythonCfgCode +="process.options.numberOfConcurrentLuminosityBlocks = {}\n".format(self._options.nConcurrentLumis)
2432  self.process.options.numberOfConcurrentLuminosityBlocks = self._options.nConcurrentLumis
2433  if overrideConcurrentIOVs:
2434  self.pythonCfgCode +="process.options.eventSetup.numberOfConcurrentIOVs = {}\n".format(self._options.nConcurrentIOVs)
2435  self.process.options.eventSetup.numberOfConcurrentIOVs = self._options.nConcurrentIOVs
2436 
2437  if self._options.accelerators is not None:
2438  accelerators = self._options.accelerators.split(',')
2439  self.pythonCfgCode += "\n"
2440  self.pythonCfgCode += "# Enable only these accelerator backends\n"
2441  self.pythonCfgCode += "process.load('Configuration.StandardSequences.Accelerators_cff')\n"
2442  self.pythonCfgCode += "process.options.accelerators = ['" + "', '".join(accelerators) + "']\n"
2443  self.process.load('Configuration.StandardSequences.Accelerators_cff')
2444  self.process.options.accelerators = accelerators
2445 
2446  #repacked version
2447  if self._options.isRepacked:
2448  self.pythonCfgCode +="\n"
2449  self.pythonCfgCode +="from Configuration.Applications.ConfigBuilder import MassReplaceInputTag\n"
2450  self.pythonCfgCode +="MassReplaceInputTag(process, new=\"rawDataMapperByLabel\", old=\"rawDataCollector\")\n"
2451  MassReplaceInputTag(self.process, new="rawDataMapperByLabel", old="rawDataCollector")
2452 
2453  # special treatment in case of production filter sequence 2/2
2454  if self.productionFilterSequence and not (self._options.pileup=='HiMixEmbGEN'):
2455  self.pythonCfgCode +='# filter all path with the production filter sequence\n'
2456  self.pythonCfgCode +='for path in process.paths:\n'
2457  if len(self.conditionalPaths):
2458  self.pythonCfgCode +='\tif not path in %s: continue\n'%str(self.conditionalPaths)
2459  if len(self.excludedPaths):
2460  self.pythonCfgCode +='\tif path in %s: continue\n'%str(self.excludedPaths)
2461  self.pythonCfgCode +='\tgetattr(process,path).insert(0, process.%s)\n'%(self.productionFilterSequence,)
2462  pfs = getattr(self.process,self.productionFilterSequence)
2463  for path in self.process.paths:
2464  if not path in self.conditionalPaths: continue
2465  if path in self.excludedPaths: continue
2466  getattr(self.process,path).insert(0, pfs)
2467 
2468 
2469  # dump customise fragment
2470  self.pythonCfgCode += self.addCustomise()
2471 
2472  if self._options.runUnscheduled:
2473  print("--runUnscheduled is deprecated and not necessary anymore, and will be removed soon. Please update your command line.")
2474  # Keep the "unscheduled customise functions" separate for now,
2475  # there are customize functions given by users (in our unit
2476  # tests) that need to be run before the "unscheduled customise
2477  # functions"
2478  self.pythonCfgCode += self.addCustomise(1)
2479 
2480  self.pythonCfgCode += self.addCustomiseCmdLine()
2481 
2482  if hasattr(self.process,"logErrorHarvester"):
2483  #configure logErrorHarvester to wait for same EDProducers to finish as the OutputModules
2484  self.pythonCfgCode +="\n#Have logErrorHarvester wait for the same EDProducers to finish as those providing data for the OutputModule\n"
2485  self.pythonCfgCode +="from FWCore.Modules.logErrorHarvester_cff import customiseLogErrorHarvesterUsingOutputCommands\n"
2486  self.pythonCfgCode +="process = customiseLogErrorHarvesterUsingOutputCommands(process)\n"
2487  from FWCore.Modules.logErrorHarvester_cff import customiseLogErrorHarvesterUsingOutputCommands
2489 
2490  # Temporary hack to put the early delete customization after
2491  # everything else
2492  #
2493  # FIXME: remove when no longer needed
2494  self.pythonCfgCode += "\n# Add early deletion of temporary data products to reduce peak memory need\n"
2495  self.pythonCfgCode += "from Configuration.StandardSequences.earlyDeleteSettings_cff import customiseEarlyDelete\n"
2496  self.pythonCfgCode += "process = customiseEarlyDelete(process)\n"
2497  self.pythonCfgCode += "# End adding early deletion\n"
2498  from Configuration.StandardSequences.earlyDeleteSettings_cff import customiseEarlyDelete
2499  self.process = customiseEarlyDelete(self.process)
2500 
2501  imports = cms.specialImportRegistry.getSpecialImports()
2502  if len(imports) > 0:
2503  #need to inject this at the top
2504  index = self.pythonCfgCode.find("import FWCore.ParameterSet.Config")
2505  #now find the end of line
2506  index = self.pythonCfgCode.find("\n",index)
2507  self.pythonCfgCode = self.pythonCfgCode[:index]+ "\n" + "\n".join(imports)+"\n" +self.pythonCfgCode[index:]
2508 
2509 
2510  # make the .io file
2511 
2512  if self._options.io:
2513  #io=open(self._options.python_filename.replace('.py','.io'),'w')
2514  if not self._options.io.endswith('.io'): self._option.io+='.io'
2515  io=open(self._options.io,'w')
2516  ioJson={}
2517  if hasattr(self.process.source,"fileNames"):
2518  if len(self.process.source.fileNames.value()):
2519  ioJson['primary']=self.process.source.fileNames.value()
2520  if hasattr(self.process.source,"secondaryFileNames"):
2521  if len(self.process.source.secondaryFileNames.value()):
2522  ioJson['secondary']=self.process.source.secondaryFileNames.value()
2523  if self._options.pileup_input and (self._options.pileup_input.startswith('dbs:') or self._options.pileup_input.startswith('das:')):
2524  ioJson['pileup']=self._options.pileup_input[4:]
2525  for (o,om) in self.process.outputModules_().items():
2526  ioJson[o]=om.fileName.value()
2527  ioJson['GT']=self.process.GlobalTag.globaltag.value()
2528  if self.productionFilterSequence:
2529  ioJson['filter']=self.productionFilterSequence
2530  import json
2531  io.write(json.dumps(ioJson))
2532  return
2533 
2534 
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