CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
EgammaHLTValidationUtils.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 import FWCore.ParameterSet.Config as cms
3 import sys, os, re
4 
5 # prefix for printouts
6 msgPrefix = "[" + os.path.basename(__file__) + "]"
7 
8 
9 #----------------------------------------------------------------------
10 
11 def getPathsOfDataSet(process, datasetName):
12  """ returns the names of the trigger paths contained in the
13  given (primary) dataset """
14 
15  return list(getattr(process.datasets, datasetName))
16 
17 #----------------------------------------------------------------------
18 
19 
20 def getProcessName(pdgGen, requiredNumberOfGeneratedObjects):
21  """ returns a process name (such as 'Zee') which can be
22  used in various places (e.g. module names etc.) """
23 
24  if pdgGen == 11:
25 
26  # electron paths
27  if requiredNumberOfGeneratedObjects == 1:
28  return "Wenu"
29  elif requiredNumberOfGeneratedObjects == 2:
30  return "Zee"
31  else:
32  raise Exception("unsupported case, can't guess type of process")
33 
34  elif pdgGen == 22:
35 
36  # photon paths
37  if requiredNumberOfGeneratedObjects == 1:
38  return 'GammaJet'
39  elif requiredNumberOfGeneratedObjects == 2:
40  return 'DiGamma'
41  else:
42  raise Exception("unsupported case, can't guess type of process")
43  else:
44  raise Exception("unsupported case, can't guess type of process")
45 
46 
47 #----------------------------------------------------------------------
48 
49 def makeGeneratedParticleAndFiducialVolumeFilter(process, pdgGen, requiredNumberOfGeneratedObjects):
50  """
51  adds the needed modules to the process object and
52  returns a sequence made of the two filters.
53 
54  returns the name of the created module
55 
56  if process is not None, are added to the process.
57 
58  When using this function from a _cff file, one
59  has to manually add the modules of the returned
60  sequence to globals() (in the calling module, not
61  here, globals() live in a different name space here)
62 
63  """
64 
65  # name of the physics process
66  procName = getProcessName(pdgGen, requiredNumberOfGeneratedObjects)
67 
68  #--------------------
69  # create a module producing a collection with the
70  # desired generated particles
71  #--------------------
72 
73  genPartModuleName = 'genpart' + procName
74 
75 
76  genPartModule = cms.EDFilter("PdgIdAndStatusCandViewSelector",
77  status = cms.vint32(3),
78  src = cms.InputTag("genParticles"),
79  pdgId = cms.vint32(pdgGen),
80  )
81 
82  # genPartModule.setLabel(genPartModuleName)
83  if process != None:
84  setattr(process, genPartModuleName, genPartModule)
85 
86  genPartModule.setLabel(genPartModuleName)
87 
88  #--------------------
89  # create a module requiring the number
90  # of generated particles
91  #--------------------
92 
93  selectorModuleName = "fiducial" + procName
94 
95  selectorModule = cms.EDFilter("EtaPtMinCandViewSelector",
96  src = cms.InputTag(genPartModuleName),
97  etaMin = cms.double(-2.5),
98  etaMax = cms.double(2.5),
99  ptMin = cms.double(2.0)
100  )
101 
102  if process != None:
103  setattr(process, selectorModuleName, selectorModule)
104 
105  # this is needed if we don't have a process to attach this module to
106  selectorModule.setLabel(selectorModuleName)
107 
108  #--------------------
109  # create the sequence
110  #--------------------
111 
112  return cms.Sequence(
113  # getattr(process, genPartModuleName)
114  genPartModule
115 
116  *
117 
118  # getattr(process, selectorModuleName)
119  selectorModule
120  )
121 #----------------------------------------------------------------------
122 
123 import HLTriggerOffline.Egamma.TriggerTypeDefs_cfi as TriggerTypeDefs_cfi
124 
126  """ a class which can be used to produce an analysis path
127  for the EmDQM analyzer """
128 
129  #----------------------------------------
130 
131  def __init__(self, process, pathName, pdgGen, requiredNumberOfGeneratedObjects, cutCollection = None):
132  """
133  pathName is the HLT path to be validated.
134 
135  pdgGen is the PDG id of the corersponding generated particles
136  (11 for electrons, 22 for photons)
137 
138  requiredNumberOfGeneratedObjects should be 1 for single triggers,
139  and 2 for double triggers (e.g. double photon triggers)
140 
141  cutCollection is the name of the collection which should be used
142  to define the acceptance region (at reconstruction level ?).
143  typical values are 'fiducialZee'. If this is set to None,
144  will be determined automatically from pdgGen and requiredNumberOfGeneratedObjects
145 
146  """
147 
148  self.process = process
149  self.pathName = pathName
150 
151  self.path = getattr(process,pathName)
152 
153  # the process whose products should be analyzed
154  self.processName = "HLT"
155 
156  #--------------------
157  # guess the collection for the fiducial volume cut
158  #--------------------
159 
160  if cutCollection == None:
161  cutCollection = "fiducial" + getProcessName(pdgGen, requiredNumberOfGeneratedObjects)
162 
163  #--------------------
164  # find Et threshold of primary object
165  #--------------------
166  mo = re.match("HLT_.*?(\d+).*",pathName)
167 
168  if mo != None:
169  etThreshold = float(mo.group(1))
170  else:
171  etThreshold = -1.0
172 
173  #--------------------
174  # initialize the analyzer we put together here
175  #--------------------
176  self.__result = cms.EDAnalyzer("EmDQM",
177  triggerobject = cms.InputTag("hltTriggerSummaryRAW","","HLT"),
178  genEtaAcc = cms.double(2.5),
179  genEtAcc = cms.double(2.0),
180  reqNum = cms.uint32(requiredNumberOfGeneratedObjects),
181  filters = cms.VPSet(), # will be added later
182  PtMax = cms.untracked.double(100.0),
183  genEtMin = cms.untracked.double(etThreshold),
184  pdgGen = cms.int32(pdgGen),
185  cutcollection = cms.InputTag(cutCollection),
186 
187  # is this a requirement on reconstructed or generated number of objects ?
188  cutnum = cms.int32(requiredNumberOfGeneratedObjects),
189 
190 
191 
192  )
193 
194  #--------------------
195  # get all modules of this path.
196  # dirty hack: assumes that all modules
197  # are concatenated by '+'
198  # but easier than to use a node visitor
199  # and order the modules ourselves afterwards..
200 
201  moduleNames = str(self.path).split('+')
202 
203  # now find out which of these are EDFilters
204  # and what CMSSW class type they are
205 
206  # example:
207  #
208  # CMSSW type module name
209  # --------------------------------------------------------------------------------------------------------------------
210  # HLTTriggerTypeFilter hltTriggerType
211  # HLTLevel1GTSeed hltL1sL1SingleEG8
212  # HLTPrescaler hltPreEle17SWTighterEleIdIsolL1R
213  # HLTEgammaL1MatchFilterRegional hltL1NonIsoHLTNonIsoSingleElectronEt17TighterEleIdIsolL1MatchFilterRegional
214  # HLTEgammaEtFilter hltL1NonIsoHLTNonIsoSingleElectronEt17TighterEleIdIsolEtFilter
215  # HLTEgammaGenericFilter hltL1NonIsoHLTNonIsoSingleElectronEt17TighterEleIdIsolR9ShapeFilter
216  # HLTEgammaGenericFilter hltL1NonIsoHLTNonIsoSingleElectronEt17TighterEleIdIsolClusterShapeFilter
217  # HLTEgammaGenericFilter hltL1NonIsoHLTNonIsoSingleElectronEt17TIghterEleIdIsolEcalIsolFilter
218  # HLTEgammaGenericFilter hltL1NonIsoHLTNonIsoSingleElectronEt17TighterEleIdIsolHEFilter
219  # HLTEgammaGenericFilter hltL1NonIsoHLTNonIsoSingleElectronEt17TighterEleIdIsolHcalIsolFilter
220  # HLTElectronPixelMatchFilter hltL1NonIsoHLTNonIsoSingleElectronEt17TighterEleIdIsolPixelMatchFilter
221  # HLTElectronOneOEMinusOneOPFilterRegional hltL1NonIsoHLTNonIsoSingleElectronEt17TighterEleIdIsolOneOEMinusOneOPFilter
222  # HLTElectronGenericFilter hltL1NonIsoHLTNonIsoSingleElectronEt17TighterEleIdIsolDetaFilter
223  # HLTElectronGenericFilter hltL1NonIsoHLTNonIsoSingleElectronEt17TighterEleIdIsolDphiFilter
224  # HLTElectronGenericFilter hltL1NonIsoHLTNonIsoSingleElectronEt17TighterEleIdIsolTrackIsolFilter
225  # HLTBool hltBoolEnd
226 
227  # it looks like in the MC menu, all modules have a name containing 'L1NonIso' and then
228  # have a parameter IsoCollections (which is mostly cms.Input("none")...)
229 
230  import FWCore.ParameterSet.Modules
231 
232  for moduleName in moduleNames:
233 
234  # add protection to avoid accessing non-existing modules
235  # (not understood why this is needed but happens
236  # in some cases...).
237  #
238  # should also cover the special cases listed afterwards
239  # (i.e. the check after this one could be removed
240  # at some point)
241  if not hasattr(self.process, moduleName):
242  continue
243 
244  # protection for FastSim HLT menu
245  # which seems to reference certain modules in some
246  # paths but these modules are not defined when just
247  # loading the HLT menu into a process object.
248  #
249  # this seems not to happen for the fullsim menu for some
250  # reason...
251  if moduleName in ('simulation',
252  'offlineBeamSpot',
253  'HLTEndSequence'):
254  continue
255 
256 
257 
258  module = getattr(self.process,moduleName)
259 
260  if not isinstance(module, FWCore.ParameterSet.Modules.EDFilter):
261  continue
262 
263  # ignore certain EDFilters
264  if module.type_() in ('HLTTriggerTypeFilter',
265  'HLTPrescaler',
266  'HLTBool'):
267  continue
268 
269  # print "XX", module.type_(), moduleName
270 
271  #--------------------
272  if module.type_() == 'HLTLevel1GTSeed':
273  # L1 seed
274  self.__result.filters.append(self.makePSetForL1SeedFilter(moduleName))
275  continue
276 
277  #--------------------
278  if module.type_() == 'HLTEgammaL1MatchFilterRegional':
279  # L1 seed to supercluster match
280  self.__result.filters.append(self.makePSetForL1SeedToSuperClusterMatchFilter(moduleName))
281  continue
282 
283  #--------------------
284 
285  if module.type_() == "HLTEgammaEtFilter":
286  # minimum Et requirement
287  self.__result.filters.append(self.makePSetForEtFilter(moduleName))
288  continue
289 
290  #--------------------
291 
292  if module.type_() == "HLTElectronOneOEMinusOneOPFilterRegional":
293  self.__result.filters.append(self.makePSetForOneOEMinusOneOPFilter(moduleName))
294  continue
295 
296  #--------------------
297  if module.type_() == "HLTElectronPixelMatchFilter":
298  self.__result.filters.append(self.makePSetForPixelMatchFilter(moduleName))
299  continue
300 
301  #--------------------
302  # generic filters: the module types
303  # aren't enough, we must check on which
304  # input collections they filter on
305  #--------------------
306 
307  if module.type_() == "HLTEgammaGenericFilter":
308 
309  pset = self.makePSetForEgammaGenericFilter(module, moduleName)
310  if pset != None:
311  self.__result.filters.append(pset)
312  continue
313 
314  #--------------------
315 
316  if module.type_() == "HLTElectronGenericFilter":
317 
318  pset = self.makePSetForElectronGenericFilter(module, moduleName)
319  if pset != None:
320  self.__result.filters.append(pset)
321  continue
322 
323  #--------------------
324 
325 ## print >> sys.stderr,msgPrefix,"WARNING: unknown module type", module.type_(), " with name " + moduleName + " in path " + pathName
326 
327  #----------------------------------------
328 
329  def makePSetForL1SeedFilter(self,moduleName):
330  """ generates a PSet to analyze the behaviour of an L1 seed.
331 
332  moduleName is the name of the HLT module which filters
333  on the L1 seed.
334  """
335 
336  return cms.PSet(
337  PlotBounds = cms.vdouble(0.0, 0.0),
338  HLTCollectionLabels = cms.InputTag(moduleName,"",self.processName),
339  IsoCollections = cms.VInputTag(cms.InputTag("none")),
340  theHLTOutputTypes = cms.int32(TriggerTypeDefs_cfi.TriggerL1NoIsoEG)
341  )
342 
343  #----------------------------------------
344 
346  """ generates a PSet to analyze the behaviour of L1 to supercluster match filter.
347 
348  moduleName is the name of the HLT module which requires the match
349  between supercluster and L1 seed.
350  """
351 
352  return cms.PSet(
353  PlotBounds = cms.vdouble(0.0, 0.0),
354  HLTCollectionLabels = cms.InputTag(moduleName,"",self.processName),
355  IsoCollections = cms.VInputTag(cms.InputTag("none")),
356  theHLTOutputTypes = cms.int32(TriggerTypeDefs_cfi.TriggerCluster)
357  )
358 
359  #----------------------------------------
360 
361  def makePSetForEtFilter(self, moduleName):
362  """ generates a PSet for the Egamma DQM analyzer for the Et filter """
363 
364  return cms.PSet(
365  PlotBounds = cms.vdouble(0.0, 0.0),
366  HLTCollectionLabels = cms.InputTag(moduleName,"",self.processName),
367  IsoCollections = cms.VInputTag(cms.InputTag("none")),
368  theHLTOutputTypes = cms.int32(TriggerTypeDefs_cfi.TriggerCluster)
369  )
370 
371  #----------------------------------------
372 
373  def makePSetForOneOEMinusOneOPFilter(self, moduleName):
374 
375  return cms.PSet(
376  PlotBounds = cms.vdouble(0.0, 0.0),
377  HLTCollectionLabels = cms.InputTag(moduleName,"",self.processName),
378  IsoCollections = cms.VInputTag(cms.InputTag("none")),
379  theHLTOutputTypes = cms.int32(TriggerTypeDefs_cfi.TriggerElectron)
380  )
381 
382  #----------------------------------------
383 
384  def makePSetForPixelMatchFilter(self, moduleName):
385  return cms.PSet(
386  PlotBounds = cms.vdouble(0.0, 0.0),
387  HLTCollectionLabels = cms.InputTag(moduleName,"",self.processName),
388  IsoCollections = cms.VInputTag(cms.InputTag("none")),
389  theHLTOutputTypes = cms.int32(TriggerTypeDefs_cfi.TriggerCluster)
390  )
391 
392  #----------------------------------------
393 
394  def makePSetForEgammaGenericFilter(self, module, moduleName):
395 
396  # example usages of HLTEgammaGenericFilter are:
397  # R9 shape filter hltL1NonIsoHLTNonIsoSingleElectronEt17TighterEleIdIsolR9ShapeFilter
398  # cluster shape filter hltL1NonIsoHLTNonIsoSingleElectronEt17TighterEleIdIsolClusterShapeFilter
399  # Ecal isolation filter hltL1NonIsoHLTNonIsoSingleElectronEt17TIghterEleIdIsolEcalIsolFilter
400  # H/E filter hltL1NonIsoHLTNonIsoSingleElectronEt17TighterEleIdIsolHEFilter
401  # HCAL isolation filter hltL1NonIsoHLTNonIsoSingleElectronEt17TighterEleIdIsolHcalIsolFilter
402 
403  # the type of object to look for seems to be the
404  # same for all uses of HLTEgammaGenericFilter
405  theHLTOutputTypes = cms.int32(TriggerTypeDefs_cfi.TriggerCluster)
406 
407  # infer the type of filter by the type of the producer which
408  # generates the collection used to cut on this
409  inputCollectionLabel = module.isoTag.moduleLabel
410 
411  inputType = getattr(self.process, inputCollectionLabel).type_()
412  # print >> sys.stderr, "inputType=",inputType,moduleName
413 
414  #--------------------
415  # sanity check: non-isolated path should be produced by the
416  # same type of module
417  #
418  # first check that the non-iso tag is non-empty
419  assert(module.nonIsoTag.moduleLabel != "")
420 
421  assert(inputType == getattr(self.process, module.nonIsoTag.moduleLabel).type_())
422 
423  #--------------------
424 
425 
426  # the following cases seem to have identical PSets ?
427 
428  #--------------------
429  # R9 shape
430  #--------------------
431 
432  if inputType == 'EgammaHLTR9Producer':
433  return cms.PSet(
434  PlotBounds = cms.vdouble(0.0, 0.0),
435  HLTCollectionLabels = cms.InputTag(moduleName,"",self.processName),
436  IsoCollections = cms.VInputTag(module.isoTag, module.nonIsoTag),
437  theHLTOutputTypes = theHLTOutputTypes
438  )
439 
440  #--------------------
441  # cluster shape
442  #--------------------
443  if inputType == 'EgammaHLTClusterShapeProducer':
444  return cms.PSet(
445  PlotBounds = cms.vdouble(0.0, 0.0),
446  HLTCollectionLabels = cms.InputTag(moduleName,"",self.processName),
447  IsoCollections = cms.VInputTag(module.isoTag, module.nonIsoTag),
448  theHLTOutputTypes = theHLTOutputTypes
449  )
450 
451  #--------------------
452  # ecal isolation
453  #--------------------
454  if inputType == 'EgammaHLTEcalRecIsolationProducer':
455  return cms.PSet(
456  PlotBounds = cms.vdouble(0.0, 0.0),
457  HLTCollectionLabels = cms.InputTag(moduleName,"",self.processName),
458  IsoCollections = cms.VInputTag(module.isoTag, module.nonIsoTag),
459  theHLTOutputTypes = theHLTOutputTypes
460  )
461 
462  #--------------------
463  # HCAL isolation and HE
464  #--------------------
465 
466  if inputType == 'EgammaHLTHcalIsolationProducersRegional':
467  return cms.PSet(
468  PlotBounds = cms.vdouble(0.0, 0.0),
469  HLTCollectionLabels = cms.InputTag(moduleName,"",self.processName),
470  IsoCollections = cms.VInputTag(module.isoTag, module.nonIsoTag),
471  theHLTOutputTypes = theHLTOutputTypes
472  )
473 
474 
475  raise Exception("can't determine what the HLTEgammaGenericFilter '" + moduleName + "' should do: uses a collection produced by a module of C++ type '" + inputType + "'")
476 
477  #----------------------------------------
478 
479  def makePSetForElectronGenericFilter(self, module, moduleName):
480 
481  # example usages of HLTElectronGenericFilter are:
482 
483  # deta filter hltL1NonIsoHLTNonIsoSingleElectronEt17TighterEleIdIsolDetaFilter
484  # dphi filter hltL1NonIsoHLTNonIsoSingleElectronEt17TighterEleIdIsolDphiFilter
485  # track isolation hltL1NonIsoHLTNonIsoSingleElectronEt17TighterEleIdIsolTrackIsolFilter
486 
487  # the type of object to look for seems to be the
488  # same for all uses of HLTEgammaGenericFilter
489  theHLTOutputTypes = cms.int32(TriggerTypeDefs_cfi.TriggerElectron)
490 
491  # infer the type of filter by the type of the producer which
492  # generates the collection used to cut on this
493  inputCollectionLabel = module.isoTag.moduleLabel
494 
495  inputType = getattr(self.process, inputCollectionLabel).type_()
496  # print >> sys.stderr, "inputType=",inputType,moduleName
497 
498  # sanity check: non-isolated path should be produced by the
499  # same type of module
500  assert(inputType == getattr(self.process, module.nonIsoTag.moduleLabel).type_())
501 
502  # the following cases seem to have identical PSets ?
503 
504  #--------------------
505  # deta and dphi filter
506  #--------------------
507 
508  # note that whether deta or dphi is used is determined from
509  # the product instance (not the module label)
510  if inputType == 'EgammaHLTElectronDetaDphiProducer':
511 
512  return cms.PSet(
513  PlotBounds = cms.vdouble(0.0, 0.0),
514  HLTCollectionLabels = cms.InputTag(moduleName,"",self.processName),
515  IsoCollections = cms.VInputTag(module.isoTag, module.nonIsoTag),
516  theHLTOutputTypes = theHLTOutputTypes
517  )
518 
519  #--------------------
520  # track isolation
521  #--------------------
522 
523  if inputType == 'EgammaHLTElectronTrackIsolationProducers':
524 
525  return cms.PSet(
526  PlotBounds = cms.vdouble(0.0, 0.0),
527  HLTCollectionLabels = cms.InputTag(moduleName,"",self.processName),
528  IsoCollections = cms.VInputTag(module.isoTag, module.nonIsoTag),
529  theHLTOutputTypes = theHLTOutputTypes
530  )
531  raise Exception("can't determine what the HLTElectronGenericFilter '" + moduleName + "' should do: uses a collection produced by a module of C++ type '" + inputType + "'")
532 
533  #----------------------------------------
534 
535  def getResult(self):
536  """ returns the composed analyzer module """
537  return self.__result
538 
539  #----------------------------------------
540 
541 #----------------------------------------------------------------------
542 # main
543 #----------------------------------------------------------------------
544 if __name__ == "__main__":
545 
546  import FWCore.ParameterSet.Config as cms
547  process = cms.Process("MYTEST")
548  process.load("HLTrigger.Configuration.HLT_GRun_cff")
549 
550  moduleMaker = EgammaDQMModuleMaker(process, "HLT_Ele17_SW_TighterEleIdIsol_L1R_v3", 11, 1)
551 
552  # print "# ----------------------------------------------------------------------"
553 
554  print moduleMaker.getResult().dumpPython()
555 
556 #----------------------------------------------------------------------
557 
558 def findEgammaPaths(process):
559  """
560  returns a dict:
561 
562  {
563  "singleElectron": [ list of single electron path objects ],
564  "doubleElectron": [ list of double electron path objects ],
565  "singlePhoton": [ list of single photon path objects ],
566  "doublePhoton": [ list of double photon path objects ],
567  }
568 
569  Note that the elements in the lists are path objects, not path names.
570 
571  Note also that this is based on the name of the paths using some
572  heuristics.
573  """
574 
575  retval = { "singleElectron": [],
576  "doubleElectron": [],
577  "singlePhoton": [],
578  "doublePhoton": [],
579  }
580 
581  for path_name, path in process.paths.items():
582 
583  # print "XX",path_name.__class__,path.__class__
584 
585  if path_name.startswith("AlCa_"):
586  continue
587 
588  if path_name.startswith("DQM_"):
589  continue
590 
591  if not path_name.startswith("HLT_"):
592  continue
593 
594  if path_name.startswith("HLT_Ele"):
595  retval['singleElectron'].append(path)
596  continue
597 
598  if path_name.startswith("HLT_Photon"):
599  retval['singlePhoton'].append(path)
600  continue
601 
602  if path_name.startswith("HLT_DoublePhoton"):
603  retval['doublePhoton'].append(path)
604  continue
605 
606  if path_name.startswith("HLT_DoubleEle"):
607  retval['doubleElectron'].append(path)
608  continue
609 
610  # end of loop over paths
611  return retval
612 
613 #----------------------------------------------------------------------
614 
616  """ returns the names of the modules found in the given path.
617 
618  Note that these are not guaranteed to be in any particular
619  order.
620  """
621 
622  # this function could actually call getModulesOfSequence(..)
623  # and then produce a set with the unique names of
624  # the modules
625 
626  import FWCore.ParameterSet.Modules
627  class Visitor:
628 
629  #----------------------------------------
630  def __init__(self):
631  self.module_names_found = set()
632 
633  #----------------------------------------
634  def enter(self,visitee):
635 
636  if isinstance(visitee, FWCore.ParameterSet.Modules._Module):
637  self.module_names_found.add(visitee.label_())
638 
639  #----------------------------------------
640  def leave(self,visitee):
641  pass
642 
643  #----------------------------------------
644 
645  visitor = Visitor()
646  path.visit(visitor)
647 
648  return visitor.module_names_found
649 
650 
651 #----------------------------------------------------------------------
652 def getCXXTypesOfPath(process, path):
653  """ returns the names of (classes) of the C++ types of the modules
654  found in the given path (in no particular order) """
655 
656  moduleNames = getModuleNamesOfPath(path)
657 
658  retval = set()
659 
660  for name in moduleNames:
661 
662  # skip those modules which are in the path
663  # but not in the process object.
664  # not understood why we need to do this
665  # but seems to cause problems in practice...
666  if not hasattr(process,name):
667  continue
668 
669  module = getattr(process, name)
670 
671  retval.add(module.type_())
672 
673  return retval
674 
675 #----------------------------------------------------------------------
676 
677 def getModulesOfSequence(sequence):
678  """ returns the modules found in a sequence.
679 
680  Note that a module can appear more than once.
681  """
682 
683  import FWCore.ParameterSet.Modules
684  class Visitor:
685 
686  #----------------------------------------
687  def __init__(self):
688  self.modules_found = []
689 
690  #----------------------------------------
691  def enter(self,visitee):
692 
693  if isinstance(visitee, FWCore.ParameterSet.Modules._Module):
694  self.modules_found.append(visitee)
695 
696  #----------------------------------------
697  def leave(self,visitee):
698  pass
699 
700  #----------------------------------------
701 
702  visitor = Visitor()
703  sequence.visitNode(visitor)
704 
705  return visitor.modules_found
706 
707 
708 #----------------------------------------------------------------------
def makePSetForL1SeedFilter
print >> sys.stderr,msgPrefix,"WARNING: unknown module type", module.type_(), " with name " + moduleN...
double split
Definition: MVATrainer.cc:139
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