CMS 3D CMS Logo

confdb.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 
3 from __future__ import absolute_import
4 import sys
5 import re
6 import os
7 from .pipe import pipe as _pipe
8 from .options import globalTag
9 from itertools import islice
10 
11 def splitter(iterator, n):
12  i = iterator.__iter__()
13  while True:
14  l = list(islice(i, n))
15  if l:
16  yield l
17  else:
18  break
19 
20 
22 
23  def __init__(self, configuration):
24  self.config = configuration
25  self.data = None
26  self.source = []
27  self.parent = []
28 
29  self.options = {
30  'essources' : [],
31  'esmodules' : [],
32  'modules' : [],
33  'sequences' : [],
34  'services' : [],
35  'paths' : [],
36  'psets' : [],
37  'blocks' : [],
38  }
39 
40  self.labels = {}
41  if self.config.fragment:
42  self.labels['process'] = 'fragment'
43  self.labels['dict'] = 'fragment.__dict__'
44  else:
45  self.labels['process'] = 'process'
46  self.labels['dict'] = 'process.__dict__'
47 
48  if self.config.prescale and (self.config.prescale.lower() != 'none'):
49  self.labels['prescale'] = self.config.prescale
50 
51  # get the configuration from ConfdB
52  from .confdbOfflineConverter import OfflineConverter
53  self.converter = OfflineConverter(version = self.config.menu.version, database = self.config.menu.database)
54  self.buildPathList()
55  self.buildOptions()
58  self.customize()
59 
61  if not self.config.setup:
62  return
63 
64  if ".py" in self.config.setup:
65  self.config.setupFile = self.config.setup.split(".py")[0]
66  return
67  args = ['--configName', self.config.setup ]
68  args.append('--noedsources')
69  args.append('--nopaths')
70  for key, vals in self.options.items():
71  if vals:
72  args.extend(('--'+key, ','.join(vals)))
73  args.append('--cff')
74  data, err = self.converter.query( *args )
75  if 'ERROR' in err or 'Exhausted Resultset' in err or 'CONFIG_NOT_FOUND' in err:
76  sys.stderr.write("%s: error while retrieving the HLT setup menu\n\n" % os.path.basename(sys.argv[0]))
77  sys.stderr.write(err + "\n\n")
78  sys.exit(1)
79  self.config.setupFile = "setup_"+self.config.setup[1:].replace("/","_")+"_cff"
80  outfile = open(self.config.setupFile+".py","w+")
81  outfile.write("# This file is automatically generated by hltGetConfiguration.\n" + data)
82 
84  if self.config.menu.run:
85  args = ['--runNumber', self.config.menu.run]
86  else:
87  args = ['--configName', self.config.menu.name ]
88  if not self.config.hilton:
89  # keep the original Source when running on Hilton
90  args.append('--noedsources')
91  for key, vals in self.options.items():
92  if vals:
93  args.extend(('--'+key, ','.join(vals)))
94 
95  data, err = self.converter.query( *args )
96  if 'ERROR' in err or 'Exhausted Resultset' in err or 'CONFIG_NOT_FOUND' in err:
97  sys.stderr.write("%s: error while retrieving the HLT menu\n\n" % os.path.basename(sys.argv[0]))
98  sys.stderr.write(err + "\n\n")
99  sys.exit(1)
100  self.data = data
101 
102  def getPathList(self):
103  if self.config.menu.run:
104  args = ['--runNumber', self.config.menu.run]
105  else:
106  args = ['--configName', self.config.menu.name]
107  args.extend( (
108  '--cff',
109  '--noedsources',
110  '--noes',
111  '--noservices',
112  '--nosequences',
113  '--nomodules'
114  ) )
115 
116  data, err = self.converter.query( *args )
117  if 'ERROR' in err or 'Exhausted Resultset' in err or 'CONFIG_NOT_FOUND' in err:
118  sys.stderr.write("%s: error while retrieving the list of paths from the HLT menu\n\n" % os.path.basename(sys.argv[0]))
119  sys.stderr.write(err + "\n\n")
120  sys.exit(1)
121  filter = re.compile(r' *= *cms.(End)?Path.*')
122  paths = [ filter.sub('', line) for line in data.splitlines() if filter.search(line) ]
123  return paths
124 
125 
126  @staticmethod
127  def expandWildcards(globs, collection):
128  # expand a list of unix-style wildcards matching a given collection
129  # wildcards with no matches are silently discarded
130  matches = []
131  for glob in globs:
132  negate = ''
133  if glob[0] == '-':
134  negate = '-'
135  glob = glob[1:]
136  # translate a unix-style glob expression into a regular expression
137  filter = re.compile(r'^' + glob.replace('?', '.').replace('*', '.*').replace('[!', '[^') + r'$')
138  matches.extend( negate + element for element in collection if filter.match(element) )
139  return matches
140 
141 
142  @staticmethod
143  def consolidateNegativeList(elements):
144  # consolidate a list of path exclusions and re-inclusions
145  # the result is the list of paths to be removed from the dump
146  result = set()
147  for element in elements:
148  if element[0] == '-':
149  result.add( element )
150  else:
151  result.discard( '-' + element )
152  return sorted( element for element in result )
153 
154  @staticmethod
155  def consolidatePositiveList(elements):
156  # consolidate a list of path selection and re-exclusions
157  # the result is the list of paths to be included in the dump
158  result = set()
159  for element in elements:
160  if element[0] == '-':
161  result.discard( element[1:] )
162  else:
163  result.add( element )
164  return sorted( element for element in result )
165 
166 
167  # dump the final configuration
168  def dump(self):
169  self.data = self.data % self.labels
170  if self.config.fragment:
171  self.data = re.sub( r'\bprocess\b', 'fragment', self.data )
172  self.data = re.sub( r'\bProcess\b', 'ProcessFragment', self.data )
173  return self.data
174 
175 
176  # add specific customizations
177  def specificCustomize(self):
178  # specific customizations now live in HLTrigger.Configuration.customizeHLTforALL.customizeHLTforAll(.,.)
179  if self.config.fragment:
180  self.data += """
181 # add specific customizations
182 from HLTrigger.Configuration.customizeHLTforALL import customizeHLTforAll
183 fragment = customizeHLTforAll(fragment,"%s")
184 """ % (self.config.type)
185  elif self.config.hilton:
186  # do not apply the STORM-specific customisation
187  pass
188  else:
189  if self.config.type=="Fake":
190  prefix = "run1"
191  elif self.config.type in ("Fake1","Fake2","2018"):
192  prefix = "run2"
193  else:
194  prefix = "run3"
195  _gtData = "auto:"+prefix+"_hlt_"+self.config.type
196  _gtMc = "auto:"+prefix+"_mc_" +self.config.type
197  self.data += """
198 # add specific customizations
199 _customInfo = {}
200 _customInfo['menuType' ]= "%s"
201 _customInfo['globalTags']= {}
202 _customInfo['globalTags'][True ] = "%s"
203 _customInfo['globalTags'][False] = "%s"
204 _customInfo['inputFiles']={}
205 _customInfo['inputFiles'][True] = "file:RelVal_Raw_%s_DATA.root"
206 _customInfo['inputFiles'][False] = "file:RelVal_Raw_%s_MC.root"
207 _customInfo['maxEvents' ]= %s
208 _customInfo['globalTag' ]= "%s"
209 _customInfo['inputFile' ]= %s
210 _customInfo['realData' ]= %s
211 from HLTrigger.Configuration.customizeHLTforALL import customizeHLTforAll
212 %%(process)s = customizeHLTforAll(%%(process)s,"%s",_customInfo)
213 """ % (self.config.type,_gtData,_gtMc,self.config.type,self.config.type,self.config.events,self.config.globaltag,self.source,self.config.data,self.config.type)
214 
215  self.data += """
216 from HLTrigger.Configuration.customizeHLTforCMSSW import customizeHLTforCMSSW
217 %%(process)s = customizeHLTforCMSSW(%%(process)s,"%s")
218 """ % (self.config.type)
219 
220  # Eras-based customisations
221  self.data += """
222 # Eras-based customisations
223 from HLTrigger.Configuration.Eras import modifyHLTforEras
224 modifyHLTforEras(%(process)s)
225 """
226  # add the user-defined customization functions, if any
227  if self.config.customise:
228  self.data += "\n"
229  self.data += "#User-defined customization functions\n"
230  for customise in self.config.customise.split(","):
231  customiseValues = customise.split(".")
232  if len(customiseValues)>=3: raise Exception("--customise option cannot contain more than one dot.")
233  if len(customiseValues)==1:
234  customiseValues.append("customise")
235  customiseValues[0] = customiseValues[0].replace("/",".")
236  self.data += "from "+customiseValues[0]+" import "+customiseValues[1]+"\n"
237  self.data += "process = "+customiseValues[1]+"(process)\n"
238 
239 
240  # customize the configuration according to the options
241  def customize(self):
242 
243  # adapt the source to the current scenario
244  if not self.config.fragment:
245  self.build_source()
246 
247  # manual override some parameters
248  if self.config.type in ('HIon', ):
249  if self.config.data:
250  if not self.config.fragment:
251  self._fix_parameter( type = 'InputTag', value = 'rawDataCollector', replace = 'rawDataRepacker')
252 
253  # if requested, remove the HLT prescales
254  self.fixPrescales()
255 
256  # if requested, override all ED/HLTfilters to always pass ("open" mode)
257  self.instrumentOpenMode()
258 
259  # if requested, change all HLTTriggerTypeFilter EDFilters to accept only error events (SelectedTriggerType = 0)
261 
262  # if requested, instrument the self with the modules and EndPath needed for timing studies
263  self.instrumentTiming()
264 
265  # if requested, override the L1 self from the GlobalTag (Xml)
266  self.overrideL1MenuXml()
267 
268  # if requested, run the L1 emulator
269  self.runL1Emulator()
270 
271  # add process.load("setup_cff")
272  self.loadSetupCff()
273 
274  if self.config.fragment:
275  self.data += """
276 # dummify hltGetConditions in cff's
277 if 'hltGetConditions' in %(dict)s and 'HLTriggerFirstPath' in %(dict)s :
278  %(process)s.hltDummyConditions = cms.EDFilter( "HLTBool",
279  result = cms.bool( True )
280  )
281  %(process)s.HLTriggerFirstPath.replace(%(process)s.hltGetConditions,%(process)s.hltDummyConditions)
282 """
283 
284  # fix the Scouting EndPaths
285  for path in self.all_paths:
286  match = re.match(r'(Scouting\w+)Output$', path)
287  if match:
288  module = 'hltOutput' + match.group(1)
289  self.data = self.data.replace(path+' = cms.EndPath', path+' = cms.Path')
290  self.data = self.data.replace(' + process.'+module, '')
291 
292  else:
293 
294  # override the process name and adapt the relevant filters
295  self.overrideProcessName()
296 
297  # select specific Eras
298  self.addEras()
299 
300  # override the output modules to output root files
301  self.overrideOutput()
302 
303  # add global options
304  self.addGlobalOptions()
305 
306  # if requested or necessary, override the GlobalTag and connection strings (incl. L1!)
307  self.overrideGlobalTag()
308 
309  # request summary informations from the MessageLogger
310  self.updateMessageLogger()
311 
312  # replace DQMStore and DQMRootOutputModule with a configuration suitable for running offline
313  self.instrumentDQM()
314 
315  # add specific customisations
316  self.specificCustomize()
317 
318 
319  def addGlobalOptions(self):
320  # add global options
321  self.data += """
322 # limit the number of events to be processed
323 %%(process)s.maxEvents = cms.untracked.PSet(
324  input = cms.untracked.int32( %d )
325 )
326 """ % self.config.events
327 
328  self.data += """
329 # enable TrigReport, TimeReport and MultiThreading
330 %(process)s.options = cms.untracked.PSet(
331  wantSummary = cms.untracked.bool( True ),
332  numberOfThreads = cms.untracked.uint32( 4 ),
333  numberOfStreams = cms.untracked.uint32( 0 ),
334 )
335 """
336 
337  def _fix_parameter(self, **args):
338  """arguments:
339  name: parameter name (optional)
340  type: parameter type (look for tracked and untracked variants)
341  value: original value
342  replace: replacement value
343  """
344  if 'name' in args:
345  self.data = re.sub(
346  r'%(name)s = cms(?P<tracked>(?:\.untracked)?)\.%(type)s\( (?P<quote>["\']?)%(value)s(?P=quote)' % args,
347  r'%(name)s = cms\g<tracked>.%(type)s( \g<quote>%(replace)s\g<quote>' % args,
348  self.data)
349  else:
350  self.data = re.sub(
351  r'cms(?P<tracked>(?:\.untracked)?)\.%(type)s\( (?P<quote>["\']?)%(value)s(?P=quote)' % args,
352  r'cms\g<tracked>.%(type)s( \g<quote>%(replace)s\g<quote>' % args,
353  self.data)
354 
355 
356  def fixPrescales(self):
357  # update the PrescaleService to match the new list of paths
358  if self.options['paths']:
359  if self.options['paths'][0][0] == '-':
360  # drop requested paths
361  for minuspath in self.options['paths']:
362  path = minuspath[1:]
363  self.data = re.sub(r' cms.PSet\( pathName = cms.string\( "%s" \),\n prescales = cms.vuint32\( .* \)\n \),?\n' % path, '', self.data)
364  else:
365  # keep requested paths
366  for path in self.all_paths:
367  if path not in self.options['paths']:
368  self.data = re.sub(r' cms.PSet\( pathName = cms.string\( "%s" \),\n prescales = cms.vuint32\( .* \)\n \),?\n' % path, '', self.data)
369 
370  if self.config.prescale and (self.config.prescale.lower() != 'none'):
371  # TO DO: check that the requested prescale column is valid
372  self.data += """
373 # force the use of a specific HLT prescale column
374 if 'PrescaleService' in %(dict)s:
375  %(process)s.PrescaleService.forceDefault = True
376  %(process)s.PrescaleService.lvl1DefaultLabel = '%(prescale)s'
377 """
378 
379 
381  if self.config.open:
382  # find all EDfilters
383  filters = [ match[1] for match in re.findall(r'(process\.)?\b(\w+) = cms.EDFilter', self.data) ]
384  re_sequence = re.compile( r'cms\.(Path|Sequence)\((.*)\)' )
385  # remove existing 'cms.ignore' and '~' modifiers
386  self.data = re_sequence.sub( lambda line: re.sub( r'cms\.ignore *\( *((process\.)?\b(\w+)) *\)', r'\1', line.group(0) ), self.data )
387  self.data = re_sequence.sub( lambda line: re.sub( r'~', '', line.group(0) ), self.data )
388  # wrap all EDfilters with "cms.ignore( ... )", 1000 at a time (python 2.6 complains for too-big regular expressions)
389  for some in splitter(filters, 1000):
390  re_filters = re.compile( r'\b((process\.)?(' + r'|'.join(some) + r'))\b' )
391  self.data = re_sequence.sub( lambda line: re_filters.sub( r'cms.ignore( \1 )', line.group(0) ), self.data )
392 
393 
395  if self.config.errortype:
396  # change all HLTTriggerTypeFilter EDFilters to accept only error events (SelectedTriggerType = 0)
397  self._fix_parameter(name = 'SelectedTriggerType', type ='int32', value = '1', replace = '0')
398  self._fix_parameter(name = 'SelectedTriggerType', type ='int32', value = '2', replace = '0')
399  self._fix_parameter(name = 'SelectedTriggerType', type ='int32', value = '3', replace = '0')
400 
401 
402  def overrideGlobalTag(self):
403  # overwrite GlobalTag
404  # the logic is:
405  # - if a GlobalTag is specified on the command line:
406  # - override the global tag
407  # - if the GT is "auto:...", insert the code to read it from Configuration.AlCa.autoCond
408  # - if a GlobalTag is NOT specified on the command line:
409  # - when running on data, do nothing, and keep the global tag in the menu
410  # - when running on mc, take the GT from the configuration.type
411 
412  # override the GlobalTag connection string and pfnPrefix
413 
414  # when running on MC, override the global tag even if not specified on the command line
415  if not self.config.data and not self.config.globaltag:
416  if self.config.type in globalTag:
417  self.config.globaltag = globalTag[self.config.type]
418  else:
419  self.config.globaltag = globalTag['GRun']
420 
421  # if requested, override the L1 menu from the GlobalTag
422  if self.config.l1.override:
423  self.config.l1.tag = self.config.l1.override
424  self.config.l1.record = 'L1TUtmTriggerMenuRcd'
425  self.config.l1.connect = ''
426  self.config.l1.label = ''
427  if not self.config.l1.snapshotTime:
428  self.config.l1.snapshotTime = '9999-12-31 23:59:59.000'
429  self.config.l1cond = '%(tag)s,%(record)s,%(connect)s,%(label)s,%(snapshotTime)s' % self.config.l1.__dict__
430  else:
431  self.config.l1cond = None
432 
433  if self.config.globaltag or self.config.l1cond:
434  text = """
435 # override the GlobalTag, connection string and pfnPrefix
436 if 'GlobalTag' in %(dict)s:
437  from Configuration.AlCa.GlobalTag import GlobalTag as customiseGlobalTag
438  %(process)s.GlobalTag = customiseGlobalTag(%(process)s.GlobalTag"""
439  if self.config.globaltag:
440  text += ", globaltag = %s" % repr(self.config.globaltag)
441  if self.config.l1cond:
442  text += ", conditions = %s" % repr(self.config.l1cond)
443  text += ")\n"
444  self.data += text
445 
446  def overrideL1MenuXml(self):
447  # if requested, override the GlobalTag's L1T menu from an Xml file
448  if self.config.l1Xml.XmlFile:
449  text = """
450 # override the GlobalTag's L1T menu from an Xml file
451 from HLTrigger.Configuration.CustomConfigs import L1XML
452 %%(process)s = L1XML(%%(process)s,"%s")
453 """ % (self.config.l1Xml.XmlFile)
454  self.data += text
455 
456  def runL1Emulator(self):
457  # if requested, run the Full L1T emulator, then repack the data into a new RAW collection, to be used by the HLT
458  if self.config.emulator:
459  text = """
460 # run the Full L1T emulator, then repack the data into a new RAW collection, to be used by the HLT
461 from HLTrigger.Configuration.CustomConfigs import L1REPACK
462 %%(process)s = L1REPACK(%%(process)s,"%s")
463 """ % (self.config.emulator)
464  self.data += text
465 
466  def overrideOutput(self):
467  # if not runnign on Hilton, override the "online" ShmStreamConsumer output modules with "offline" PoolOutputModule's
468  # note for Run3 ShmStreamConsumer has been replaced with EvFOutputModule
469  # so we also do a replace there
470  if not self.config.hilton:
471  self.data = re.sub(
472  r'\b(process\.)?hltOutput(\w+) *= *cms\.OutputModule\( *"(ShmStreamConsumer)" *,',
473  r'%(process)s.hltOutput\2 = cms.OutputModule( "PoolOutputModule",\n fileName = cms.untracked.string( "output\2.root" ),\n fastCloning = cms.untracked.bool( False ),\n dataset = cms.untracked.PSet(\n filterName = cms.untracked.string( "" ),\n dataTier = cms.untracked.string( "RAW" )\n ),',
474  self.data
475  )
476  self.data = re.sub(
477  r'\b(process\.)?hltOutput(\w+) *= *cms\.OutputModule\( *"EvFOutputModule" *,\n use_compression = cms.untracked.bool\( True \),\n compression_algorithm = cms.untracked.string\( "ZLIB" \),\n compression_level = cms.untracked.int32\( 1 \),\n lumiSection_interval = cms.untracked.int32\( 0 \),\n(.+?),\n psetMap = cms.untracked.InputTag\( "hltPSetMap" \)\n',
478  r'\1hltOutput\2 = cms.OutputModule( "PoolOutputModule",\n fileName = cms.untracked.string( "output\2.root" ),\n fastCloning = cms.untracked.bool( False ),\n dataset = cms.untracked.PSet(\n filterName = cms.untracked.string( "" ),\n dataTier = cms.untracked.string( "RAW" )\n ),\n\3\n',
479  self.data,0,re.DOTALL
480  )
481 
482  if not self.config.fragment and self.config.output == 'minimal':
483  # add a single output to keep the TriggerResults and TriggerEvent
484  self.data += """
485 # add a single "keep *" output
486 %(process)s.hltOutputMinimal = cms.OutputModule( "PoolOutputModule",
487  fileName = cms.untracked.string( "output.root" ),
488  fastCloning = cms.untracked.bool( False ),
489  dataset = cms.untracked.PSet(
490  dataTier = cms.untracked.string( 'AOD' ),
491  filterName = cms.untracked.string( '' )
492  ),
493  outputCommands = cms.untracked.vstring( 'drop *',
494  'keep edmTriggerResults_*_*_*',
495  'keep triggerTriggerEvent_*_*_*'
496  )
497 )
498 %(process)s.MinimalOutput = cms.EndPath( %(process)s.hltOutputMinimal )
499 """
500  elif not self.config.fragment and self.config.output == 'full':
501  # add a single "keep *" output
502  self.data += """
503 # add a single "keep *" output
504 %(process)s.hltOutputFull = cms.OutputModule( "PoolOutputModule",
505  fileName = cms.untracked.string( "output.root" ),
506  fastCloning = cms.untracked.bool( False ),
507  dataset = cms.untracked.PSet(
508  dataTier = cms.untracked.string( 'RECO' ),
509  filterName = cms.untracked.string( '' )
510  ),
511  outputCommands = cms.untracked.vstring( 'keep *' )
512 )
513 %(process)s.FullOutput = cms.EndPath( %(process)s.hltOutputFull )
514 """
515 
516  # select specific Eras
517  def addEras(self):
518  if self.config.eras is None:
519  return
520  from Configuration.StandardSequences.Eras import eras
521  erasSplit = self.config.eras.split(',')
522  self.data = re.sub(r'process = cms.Process\( *"\w+"', '\n'.join(eras.pythonCfgLines[era] for era in erasSplit)+'\n\g<0>, '+', '.join(era for era in erasSplit), self.data)
523 
524  # select specific Eras
525  def loadSetupCff(self):
526  if self.config.setup is None:
527  return
528  processLine = self.data.find("\n",self.data.find("cms.Process"))
529  self.data = self.data[:processLine]+'\nprocess.load("%s")'%self.config.setupFile+self.data[processLine:]
530 
531  # override the process name and adapt the relevant filters
533  if self.config.name is None:
534  return
535 
536  # sanitise process name
537  self.config.name = self.config.name.replace("_","")
538  # override the process name
539  quote = '[\'\"]'
540  self.data = re.compile(r'^(process\s*=\s*cms\.Process\(\s*' + quote + r')\w+(' + quote + r'\s*\).*)$', re.MULTILINE).sub(r'\1%s\2' % self.config.name, self.data, 1)
541 
542  # when --setup option is used, remove possible errors from PrescaleService due to missing HLT paths.
543  if self.config.setup: self.data += """
544 # avoid PrescaleService error due to missing HLT paths
545 if 'PrescaleService' in process.__dict__:
546  for pset in reversed(process.PrescaleService.prescaleTable):
547  if not hasattr(process,pset.pathName.value()):
548  process.PrescaleService.prescaleTable.remove(pset)
549 """
550 
551 
553  # request summary informations from the MessageLogger
554  self.data += """
555 if 'MessageLogger' in %(dict)s:
556  %(process)s.MessageLogger.TriggerSummaryProducerAOD = cms.untracked.PSet()
557  %(process)s.MessageLogger.L1GtTrigReport = cms.untracked.PSet()
558  %(process)s.MessageLogger.L1TGlobalSummary = cms.untracked.PSet()
559  %(process)s.MessageLogger.HLTrigReport = cms.untracked.PSet()
560  %(process)s.MessageLogger.FastReport = cms.untracked.PSet()
561  %(process)s.MessageLogger.ThroughputService = cms.untracked.PSet()
562 """
563 
564 
565  def loadAdditionalConditions(self, comment, *conditions):
566  # load additional conditions
567  self.data += """
568 # %s
569 if 'GlobalTag' in %%(dict)s:
570 """ % comment
571  for condition in conditions:
572  self.data += """ %%(process)s.GlobalTag.toGet.append(
573  cms.PSet(
574  record = cms.string( '%(record)s' ),
575  tag = cms.string( '%(tag)s' ),
576  label = cms.untracked.string( '%(label)s' ),
577  )
578  )
579 """ % condition
580 
581 
582  def loadCffCommand(self, module):
583  # load a cfi or cff module
584  if self.config.fragment:
585  return 'from %s import *\n' % module
586  else:
587  return 'process.load( "%s" )\n' % module
588 
589  def loadCff(self, module):
590  self.data += self.loadCffCommand(module)
591 
592 
593  def overrideParameters(self, module, parameters):
594  # override a module's parameter if the module is present in the configuration
595  self.data += "if '%s' in %%(dict)s:\n" % module
596  for (parameter, value) in parameters:
597  self.data += " %%(process)s.%s.%s = %s\n" % (module, parameter, value)
598  self.data += "\n"
599 
600 
601  def instrumentTiming(self):
602 
603  if self.config.timing:
604  self.data += """
605 # instrument the menu with the modules and EndPath needed for timing studies
606 """
607 
608  self.data += '\n# configure the FastTimerService\n'
609  self.loadCff('HLTrigger.Timer.FastTimerService_cfi')
610 
611  self.data += """# print a text summary at the end of the job
612 %(process)s.FastTimerService.printEventSummary = False
613 %(process)s.FastTimerService.printRunSummary = False
614 %(process)s.FastTimerService.printJobSummary = True
615 
616 # enable DQM plots
617 %(process)s.FastTimerService.enableDQM = True
618 
619 # enable per-path DQM plots (starting with CMSSW 9.2.3-patch2)
620 %(process)s.FastTimerService.enableDQMbyPath = True
621 
622 # enable per-module DQM plots
623 %(process)s.FastTimerService.enableDQMbyModule = True
624 
625 # enable per-event DQM plots vs lumisection
626 %(process)s.FastTimerService.enableDQMbyLumiSection = True
627 %(process)s.FastTimerService.dqmLumiSectionsRange = 2500
628 
629 # set the time resolution of the DQM plots
630 %(process)s.FastTimerService.dqmTimeRange = 2000.
631 %(process)s.FastTimerService.dqmTimeResolution = 10.
632 %(process)s.FastTimerService.dqmPathTimeRange = 1000.
633 %(process)s.FastTimerService.dqmPathTimeResolution = 5.
634 %(process)s.FastTimerService.dqmModuleTimeRange = 200.
635 %(process)s.FastTimerService.dqmModuleTimeResolution = 1.
636 
637 # set the base DQM folder for the plots
638 %(process)s.FastTimerService.dqmPath = 'HLT/TimerService'
639 %(process)s.FastTimerService.enableDQMbyProcesses = False
640 """
641 
642 
643  def instrumentDQM(self):
644  if not self.config.hilton:
645  # remove any reference to the hltDQMFileSaver and hltDQMFileSaverPB
646  # note the convert options remove the module itself,
647  # here we are just removing the references in paths,sequences etc
648  if 'hltDQMFileSaverPB' in self.data:
649  self.data = re.sub(r'\b(process\.)?hltDQMFileSaverPB \+ ', '', self.data)
650  self.data = re.sub(r' \+ \b(process\.)?hltDQMFileSaverPB', '', self.data)
651  self.data = re.sub(r'\b(process\.)?hltDQMFileSaverPB', '', self.data)
652 
653  if 'hltDQMFileSaver' in self.data:
654  self.data = re.sub(r'\b(process\.)?hltDQMFileSaver \+ ', '', self.data)
655  self.data = re.sub(r' \+ \b(process\.)?hltDQMFileSaver', '', self.data)
656  self.data = re.sub(r'\b(process\.)?hltDQMFileSaver', '', self.data)
657 
658  # instrument the HLT menu with DQMStore and DQMRootOutputModule suitable for running offline
659  dqmstore = "\n# load the DQMStore and DQMRootOutputModule\n"
660  dqmstore += self.loadCffCommand('DQMServices.Core.DQMStore_cfi')
661  dqmstore += """
662 %(process)s.dqmOutput = cms.OutputModule("DQMRootOutputModule",
663  fileName = cms.untracked.string("DQMIO.root")
664 )
665 """
666 
667  empty_path = re.compile(r'.*\b(process\.)?DQMOutput = cms\.EndPath\( *\).*')
668  other_path = re.compile(r'(.*\b(process\.)?DQMOutput = cms\.EndPath\()(.*)')
669  if empty_path.search(self.data):
670  # replace an empty DQMOutput path
671  self.data = empty_path.sub(dqmstore + '\n%(process)s.DQMOutput = cms.EndPath( %(process)s.dqmOutput )\n', self.data)
672  elif other_path.search(self.data):
673  # prepend the dqmOutput to the DQMOutput path
674  self.data = other_path.sub(dqmstore + r'\g<1> %(process)s.dqmOutput +\g<3>', self.data)
675  else:
676  # ceate a new DQMOutput path with the dqmOutput module
677  self.data += dqmstore
678  self.data += '\n%(process)s.DQMOutput = cms.EndPath( %(process)s.dqmOutput )\n'
679 
680 
681  @staticmethod
682  def dumppaths(paths):
683  sys.stderr.write('Path selection:\n')
684  for path in paths:
685  sys.stderr.write('\t%s\n' % path)
686  sys.stderr.write('\n\n')
687 
688  def buildPathList(self):
689  self.all_paths = self.getPathList()
690 
691  if self.config.paths:
692  # no path list was requested, dump the full table, minus unsupported / unwanted paths
693  paths = self.config.paths.split(',')
694  else:
695  # dump only the requested paths, plus the eventual output endpaths
696  paths = []
697 
698  # 'none' should remove all outputs
699  # 'dqm' should remove all outputs but DQMHistograms
700  # 'minimal' should remove all outputs but DQMHistograms, and add a single output module to keep the TriggerResults and TriggerEvent
701  # 'full' should remove all outputs but DQMHistograms, and add a single output module to "keep *"
702  # See also the `overrideOutput` method
703  if self.config.fragment or self.config.output in ('none', ):
704  if self.config.paths:
705  # keep only the Paths and EndPaths requested explicitly
706  pass
707  else:
708  # drop all output EndPaths but the Scouting ones, and drop the RatesMonitoring and DQMHistograms
709  paths.append( "-*Output" )
710  paths.append( "-RatesMonitoring")
711  paths.append( "-DQMHistograms")
712  if self.config.fragment: paths.append( "Scouting*Output" )
713 
714  elif self.config.output in ('dqm', 'minimal', 'full'):
715  if self.config.paths:
716  # keep only the Paths and EndPaths requested explicitly, and the DQMHistograms
717  paths.append( "DQMHistograms" )
718  else:
719  # drop all output EndPaths but the Scouting ones, and drop the RatesMonitoring
720  paths.append( "-*Output" )
721  paths.append( "-RatesMonitoring")
722  if self.config.fragment: paths.append( "Scouting*Output" )
723 
724  else:
725  if self.config.paths:
726  # keep all output EndPaths, including the DQMHistograms
727  paths.append( "*Output" )
728  paths.append( "DQMHistograms" )
729  else:
730  # keep all Paths and EndPaths
731  pass
732 
733  # drop unwanted paths for profiling (and timing studies)
734  if self.config.profiling:
735  paths.append( "-HLTAnalyzerEndpath" )
736 
737  # this should never be in any dump (nor online menu)
738  paths.append( "-OfflineOutput" )
739 
740  # expand all wildcards
741  paths = self.expandWildcards(paths, self.all_paths)
742 
743  if self.config.paths:
744  # do an "additive" consolidation
745  paths = self.consolidatePositiveList(paths)
746  if not paths:
747  raise RuntimeError('Error: option "--paths %s" does not select any valid paths' % self.config.paths)
748  else:
749  # do a "subtractive" consolidation
750  paths = self.consolidateNegativeList(paths)
751  self.options['paths'] = paths
752 
753  def buildOptions(self):
754  # common configuration for all scenarios
755  self.options['services'].append( "-DQM" )
756  self.options['services'].append( "-FUShmDQMOutputService" )
757  self.options['services'].append( "-MicroStateService" )
758  self.options['services'].append( "-ModuleWebRegistry" )
759  self.options['services'].append( "-TimeProfilerService" )
760 
761  # remove the DAQ modules and the online definition of the DQMStore and DQMFileSaver
762  # unless a hilton-like configuration has been requested
763  if not self.config.hilton:
764  self.options['services'].append( "-EvFDaqDirector" )
765  self.options['services'].append( "-FastMonitoringService" )
766  self.options['services'].append( "-DQMStore" )
767  self.options['modules'].append( "-hltDQMFileSaver" )
768  self.options['modules'].append( "-hltDQMFileSaverPB" )
769 
770  if self.config.fragment:
771  # extract a configuration file fragment
772  self.options['essources'].append( "-GlobalTag" )
773  self.options['essources'].append( "-HepPDTESSource" )
774  self.options['essources'].append( "-XMLIdealGeometryESSource" )
775  self.options['essources'].append( "-eegeom" )
776  self.options['essources'].append( "-es_hardcode" )
777  self.options['essources'].append( "-magfield" )
778 
779  self.options['esmodules'].append( "-SlaveField0" )
780  self.options['esmodules'].append( "-SlaveField20" )
781  self.options['esmodules'].append( "-SlaveField30" )
782  self.options['esmodules'].append( "-SlaveField35" )
783  self.options['esmodules'].append( "-SlaveField38" )
784  self.options['esmodules'].append( "-SlaveField40" )
785  self.options['esmodules'].append( "-VBF0" )
786  self.options['esmodules'].append( "-VBF20" )
787  self.options['esmodules'].append( "-VBF30" )
788  self.options['esmodules'].append( "-VBF35" )
789  self.options['esmodules'].append( "-VBF38" )
790  self.options['esmodules'].append( "-VBF40" )
791  self.options['esmodules'].append( "-CSCGeometryESModule" )
792  self.options['esmodules'].append( "-CaloGeometryBuilder" )
793  self.options['esmodules'].append( "-CaloTowerHardcodeGeometryEP" )
794  self.options['esmodules'].append( "-CastorHardcodeGeometryEP" )
795  self.options['esmodules'].append( "-DTGeometryESModule" )
796  self.options['esmodules'].append( "-EcalBarrelGeometryEP" )
797  self.options['esmodules'].append( "-EcalElectronicsMappingBuilder" )
798  self.options['esmodules'].append( "-EcalEndcapGeometryEP" )
799  self.options['esmodules'].append( "-EcalLaserCorrectionService" )
800  self.options['esmodules'].append( "-EcalPreshowerGeometryEP" )
801  self.options['esmodules'].append( "-HcalHardcodeGeometryEP" )
802  self.options['esmodules'].append( "-HcalTopologyIdealEP" )
803  self.options['esmodules'].append( "-MuonNumberingInitialization" )
804  self.options['esmodules'].append( "-ParametrizedMagneticFieldProducer" )
805  self.options['esmodules'].append( "-RPCGeometryESModule" )
806  self.options['esmodules'].append( "-SiStripGainESProducer" )
807  self.options['esmodules'].append( "-SiStripRecHitMatcherESProducer" )
808  self.options['esmodules'].append( "-SiStripQualityESProducer" )
809  self.options['esmodules'].append( "-StripCPEfromTrackAngleESProducer" )
810  self.options['esmodules'].append( "-TrackerAdditionalParametersPerDetESModule" )
811  self.options['esmodules'].append( "-TrackerDigiGeometryESModule" )
812  self.options['esmodules'].append( "-TrackerGeometricDetESModule" )
813  self.options['esmodules'].append( "-VolumeBasedMagneticFieldESProducer" )
814  self.options['esmodules'].append( "-ZdcHardcodeGeometryEP" )
815  self.options['esmodules'].append( "-hcal_db_producer" )
816  self.options['esmodules'].append( "-L1GtTriggerMaskAlgoTrigTrivialProducer" )
817  self.options['esmodules'].append( "-L1GtTriggerMaskTechTrigTrivialProducer" )
818  self.options['esmodules'].append( "-hltESPEcalTrigTowerConstituentsMapBuilder" )
819  self.options['esmodules'].append( "-hltESPGlobalTrackingGeometryESProducer" )
820  self.options['esmodules'].append( "-hltESPMuonDetLayerGeometryESProducer" )
821  self.options['esmodules'].append( "-hltESPTrackerRecoGeometryESProducer" )
822  self.options['esmodules'].append( "-trackerTopology" )
823 
824  self.options['esmodules'].append( "-CaloTowerGeometryFromDBEP" )
825  self.options['esmodules'].append( "-CastorGeometryFromDBEP" )
826  self.options['esmodules'].append( "-EcalBarrelGeometryFromDBEP" )
827  self.options['esmodules'].append( "-EcalEndcapGeometryFromDBEP" )
828  self.options['esmodules'].append( "-EcalPreshowerGeometryFromDBEP" )
829  self.options['esmodules'].append( "-HcalGeometryFromDBEP" )
830  self.options['esmodules'].append( "-ZdcGeometryFromDBEP" )
831  self.options['esmodules'].append( "-XMLFromDBSource" )
832  self.options['esmodules'].append( "-sistripconn" )
833 
834  self.options['services'].append( "-MessageLogger" )
835 
836  self.options['psets'].append( "-maxEvents" )
837  self.options['psets'].append( "-options" )
838 
839  # remove Scouting OutputModules even though the EndPaths are kept
840  self.options['modules'].append( "-hltOutputScoutingCaloMuon" )
841  self.options['modules'].append( "-hltOutputScoutingPF" )
842 
843  if self.config.fragment or (self.config.prescale and (self.config.prescale.lower() == 'none')):
844  self.options['services'].append( "-PrescaleService" )
845 
846  if self.config.fragment or self.config.timing:
847  self.options['services'].append( "-FastTimerService" )
848 
849 
850  def append_filenames(self, name, filenames):
851  if len(filenames) > 255:
852  token_open = "( *("
853  token_close = ") )"
854  else:
855  token_open = "("
856  token_close = ")"
857 
858  self.data += " %s = cms.untracked.vstring%s\n" % (name, token_open)
859  for line in filenames:
860  self.data += " '%s',\n" % line
861  self.data += " %s,\n" % (token_close)
862 
863 
864  def expand_filenames(self, input):
865  # check if the input is a dataset or a list of files
866  if input[0:8] == 'dataset:':
867  from .dasFileQuery import dasFileQuery
868  # extract the dataset name, and use DAS to fine the list of LFNs
869  dataset = input[8:]
870  files = dasFileQuery(dataset)
871  else:
872  # assume a comma-separated list of input files
873  files = input.split(',')
874  return files
875 
876  def build_source(self):
877  if self.config.hilton:
878  # use the DAQ source
879  return
880 
881  if self.config.input:
882  # if a dataset or a list of input files was given, use it
883  self.source = self.expand_filenames(self.config.input)
884  elif self.config.data:
885  # offline we can run on data...
886  self.source = [ "file:RelVal_Raw_%s_DATA.root" % self.config.type ]
887  else:
888  # ...or on mc
889  self.source = [ "file:RelVal_Raw_%s_MC.root" % self.config.type ]
890 
891  if self.config.parent:
892  # if a dataset or a list of input files was given for the parent data, use it
893  self.parent = self.expand_filenames(self.config.parent)
894 
895  self.data += """
896 %(process)s.source = cms.Source( "PoolSource",
897 """
898  self.append_filenames("fileNames", self.source)
899  if (self.parent):
900  self.append_filenames("secondaryFileNames", self.parent)
901  self.data += """\
902  inputCommands = cms.untracked.vstring(
903  'keep *'
904  )
905 )
906 """
splitter
Definition: splitter.py:1
confdb.HLTProcess.specificCustomize
def specificCustomize(self)
Definition: confdb.py:177
confdb.HLTProcess.loadCffCommand
def loadCffCommand(self, module)
Definition: confdb.py:582
resolutioncreator_cfi.object
object
Definition: resolutioncreator_cfi.py:4
confdb.HLTProcess.getRawConfigurationFromDB
def getRawConfigurationFromDB(self)
Definition: confdb.py:83
confdb.HLTProcess.instrumentDQM
def instrumentDQM(self)
Definition: confdb.py:643
confdb.HLTProcess.dump
def dump(self)
Definition: confdb.py:168
confdb.HLTProcess.addEras
def addEras(self)
Definition: confdb.py:517
confdb.HLTProcess.loadAdditionalConditions
def loadAdditionalConditions(self, comment, *conditions)
Definition: confdb.py:565
confdb.HLTProcess.consolidatePositiveList
def consolidatePositiveList(elements)
Definition: confdb.py:155
join
static std::string join(char **cmd)
Definition: RemoteFile.cc:17
confdb.HLTProcess.converter
converter
Definition: confdb.py:53
confdb.HLTProcess.instrumentOpenMode
def instrumentOpenMode(self)
Definition: confdb.py:380
confdb.HLTProcess.overrideParameters
def overrideParameters(self, module, parameters)
Definition: confdb.py:593
confdb.HLTProcess.buildPathList
def buildPathList(self)
Definition: confdb.py:688
spr::find
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:19
confdb.HLTProcess.options
options
Definition: confdb.py:29
confdb.HLTProcess.build_source
def build_source(self)
Definition: confdb.py:876
confdb.HLTProcess.consolidateNegativeList
def consolidateNegativeList(elements)
Definition: confdb.py:143
mps_monitormerge.items
list items
Definition: mps_monitormerge.py:29
confdb.HLTProcess.append_filenames
def append_filenames(self, name, filenames)
Definition: confdb.py:850
confdb.HLTProcess.all_paths
all_paths
Definition: confdb.py:689
confdb.HLTProcess.expandWildcards
def expandWildcards(globs, collection)
Definition: confdb.py:127
confdb.HLTProcess.labels
labels
Definition: confdb.py:40
query
Definition: query.py:1
confdb.HLTProcess.getSetupConfigurationFromDB
def getSetupConfigurationFromDB(self)
Definition: confdb.py:60
confdb.HLTProcess._fix_parameter
def _fix_parameter(self, **args)
Definition: confdb.py:337
confdb.HLTProcess.overrideProcessName
def overrideProcessName(self)
Definition: confdb.py:532
confdb.splitter
def splitter(iterator, n)
Definition: confdb.py:11
confdb.HLTProcess.buildOptions
def buildOptions(self)
Definition: confdb.py:753
confdb.HLTProcess.parent
parent
Definition: confdb.py:27
confdb.HLTProcess.data
data
Definition: confdb.py:25
confdb.HLTProcess.getPathList
def getPathList(self)
Definition: confdb.py:102
confdb.HLTProcess.instrumentErrorEventType
def instrumentErrorEventType(self)
Definition: confdb.py:394
confdb.HLTProcess.__init__
def __init__(self, configuration)
Definition: confdb.py:23
confdb.HLTProcess.instrumentTiming
def instrumentTiming(self)
Definition: confdb.py:601
Exception
mps_setup.append
append
Definition: mps_setup.py:85
dasFileQuery
Definition: dasFileQuery.py:1
confdb.HLTProcess.overrideOutput
def overrideOutput(self)
Definition: confdb.py:466
confdb.HLTProcess.runL1Emulator
def runL1Emulator(self)
Definition: confdb.py:456
confdb.HLTProcess.fixPrescales
def fixPrescales(self)
Definition: confdb.py:356
confdb.HLTProcess.config
config
Definition: confdb.py:24
confdb.HLTProcess.addGlobalOptions
def addGlobalOptions(self)
Definition: confdb.py:319
confdb.HLTProcess.loadSetupCff
def loadSetupCff(self)
Definition: confdb.py:525
confdb.HLTProcess.expand_filenames
def expand_filenames(self, input)
Definition: confdb.py:864
confdb.HLTProcess.customize
def customize(self)
Definition: confdb.py:241
confdb.HLTProcess.overrideGlobalTag
def overrideGlobalTag(self)
Definition: confdb.py:402
confdb.HLTProcess.overrideL1MenuXml
def overrideL1MenuXml(self)
Definition: confdb.py:446
confdb.HLTProcess
Definition: confdb.py:21
confdb.HLTProcess.loadCff
def loadCff(self, module)
Definition: confdb.py:589
confdb.HLTProcess.updateMessageLogger
def updateMessageLogger(self)
Definition: confdb.py:552
confdb.HLTProcess.dumppaths
def dumppaths(paths)
Definition: confdb.py:682
python.rootplot.root2matplotlib.replace
def replace(string, replacements)
Definition: root2matplotlib.py:444
confdb.HLTProcess.source
source
Definition: confdb.py:26