CMS 3D CMS Logo

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