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