test
CMS 3D CMS Logo

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