CMS 3D CMS Logo

/data/git/CMSSW_5_3_11_patch5/src/HLTriggerOffline/Egamma/python/EgammaHLTValidationUtils.py

Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 import FWCore.ParameterSet.Config as cms
00003 import sys, os, re
00004 
00005 # prefix for printouts
00006 msgPrefix = "[" + os.path.basename(__file__) + "]"
00007 
00008 
00009 #----------------------------------------------------------------------
00010 
00011 def getPathsOfDataSet(process, datasetName):
00012     """ returns the names of the trigger paths contained in the
00013         given (primary) dataset """
00014 
00015     return list(getattr(process.datasets, datasetName))
00016 
00017 #----------------------------------------------------------------------
00018 
00019 
00020 def getProcessName(pdgGen, requiredNumberOfGeneratedObjects):
00021     """ returns a process name (such as 'Zee') which can be
00022      used in various places (e.g. module names etc.) """
00023 
00024     if pdgGen == 11:
00025 
00026         # electron paths
00027         if requiredNumberOfGeneratedObjects == 1:
00028             return "Wenu"
00029         elif requiredNumberOfGeneratedObjects == 2:
00030             return "Zee"
00031         else:
00032             raise Exception("unsupported case, can't guess type of process")
00033 
00034     elif pdgGen == 22:
00035 
00036         # photon paths
00037         if requiredNumberOfGeneratedObjects == 1:
00038             return 'GammaJet'
00039         elif requiredNumberOfGeneratedObjects == 2:
00040             return 'DiGamma'
00041         else:
00042             raise Exception("unsupported case, can't guess type of process")
00043     else:
00044         raise Exception("unsupported case, can't guess type of process")
00045 
00046 
00047 #----------------------------------------------------------------------
00048 
00049 def makeGeneratedParticleAndFiducialVolumeFilter(process, pdgGen, requiredNumberOfGeneratedObjects):
00050     """
00051     adds the needed modules to the process object and
00052     returns a sequence made of the two filters.
00053 
00054     returns the name of the created module
00055 
00056     if process is not None, are added to the process.
00057 
00058     When using this function from a _cff file, one
00059     has to manually add the modules of the returned
00060     sequence to globals() (in the calling module, not
00061     here, globals() live in a different name space here)
00062     
00063     """
00064 
00065     # name of the physics process
00066     procName = getProcessName(pdgGen, requiredNumberOfGeneratedObjects)
00067 
00068     #--------------------
00069     # create a module producing a collection with the 
00070     # desired generated particles
00071     #--------------------
00072 
00073     genPartModuleName = 'genpart' + procName
00074 
00075 
00076     genPartModule = cms.EDFilter("PdgIdAndStatusCandViewSelector",
00077                                  status = cms.vint32(3),
00078                                  src = cms.InputTag("genParticles"),
00079                                  pdgId = cms.vint32(pdgGen),
00080                                  )
00081 
00082     # genPartModule.setLabel(genPartModuleName)
00083     if process != None:
00084         setattr(process, genPartModuleName, genPartModule)
00085 
00086     genPartModule.setLabel(genPartModuleName)
00087 
00088     #--------------------
00089     # create a module requiring the number
00090     # of generated particles
00091     #--------------------
00092 
00093     selectorModuleName = "fiducial" + procName
00094 
00095     selectorModule = cms.EDFilter("EtaPtMinCandViewSelector",
00096                                   src = cms.InputTag(genPartModuleName),
00097                                   etaMin = cms.double(-2.5),  
00098                                   etaMax = cms.double(2.5),   
00099                                   ptMin = cms.double(2.0)
00100                                   )
00101 
00102     if process != None:
00103         setattr(process, selectorModuleName, selectorModule)
00104 
00105     # this is needed if we don't have a process to attach this module to
00106     selectorModule.setLabel(selectorModuleName)
00107 
00108     #--------------------
00109     # create the sequence
00110     #--------------------
00111 
00112     return cms.Sequence(
00113         # getattr(process, genPartModuleName)
00114         genPartModule 
00115 
00116         *
00117 
00118         # getattr(process, selectorModuleName)
00119         selectorModule
00120         )
00121 #----------------------------------------------------------------------
00122 
00123 import HLTriggerOffline.Egamma.TriggerTypeDefs_cfi as TriggerTypeDefs_cfi
00124 
00125 class EgammaDQMModuleMaker:
00126     """ a class which can be used to produce an analysis path
00127         for the EmDQM analyzer """
00128 
00129     #----------------------------------------
00130 
00131     def __init__(self, process, pathName, pdgGen, requiredNumberOfGeneratedObjects, cutCollection = None):
00132         """
00133         pathName is the HLT path to be validated.
00134 
00135         pdgGen is the PDG id of the corersponding generated particles
00136           (11 for electrons, 22 for photons)
00137 
00138         requiredNumberOfGeneratedObjects should be 1 for single triggers,
00139         and 2 for double triggers (e.g. double photon triggers)
00140 
00141         cutCollection is the name of the collection which should be used
00142           to define the acceptance region (at reconstruction level ?).
00143           typical values are 'fiducialZee'. If this is set to None,
00144           will be determined automatically from pdgGen and requiredNumberOfGeneratedObjects
00145 
00146         """
00147 
00148         self.process = process
00149         self.pathName = pathName
00150 
00151         self.path = getattr(process,pathName)
00152 
00153         # the process whose products should be analyzed
00154         self.processName = "HLT"
00155 
00156         #--------------------
00157         # guess the collection for the fiducial volume cut
00158         #--------------------
00159 
00160         if cutCollection == None:
00161             cutCollection = "fiducial" + getProcessName(pdgGen, requiredNumberOfGeneratedObjects)
00162 
00163         #--------------------
00164         # find Et threshold of primary object
00165         #--------------------
00166         mo = re.match("HLT_.*?(\d+).*",pathName)
00167 
00168         if mo != None:
00169             etThreshold = float(mo.group(1))
00170         else:
00171             etThreshold = -1.0
00172 
00173         #--------------------
00174         # initialize the analyzer we put together here
00175         #--------------------
00176         self.__result = cms.EDAnalyzer("EmDQM",
00177                                      triggerobject = cms.InputTag("hltTriggerSummaryRAW","","HLT"),                            
00178                                      genEtaAcc = cms.double(2.5),
00179                                      genEtAcc = cms.double(2.0),
00180                                      reqNum = cms.uint32(requiredNumberOfGeneratedObjects),
00181                                      filters = cms.VPSet(), # will be added later
00182                                      PtMax = cms.untracked.double(100.0),
00183                                      genEtMin = cms.untracked.double(etThreshold),
00184                                      pdgGen = cms.int32(pdgGen),
00185                                      cutcollection = cms.InputTag(cutCollection),
00186 
00187                                      # is this a requirement on reconstructed or generated number of objects ?
00188                                      cutnum = cms.int32(requiredNumberOfGeneratedObjects),
00189 
00190 
00191                                        
00192                                        )
00193 
00194         #--------------------
00195         # get all modules of this path.
00196         # dirty hack: assumes that all modules
00197         #   are concatenated by '+'
00198         # but easier than to use a node visitor
00199         # and order the modules ourselves afterwards..
00200 
00201         moduleNames = str(self.path).split('+')
00202 
00203         # now find out which of these are EDFilters
00204         # and what CMSSW class type they are
00205 
00206         # example:
00207         #
00208         # CMSSW type                               module name
00209         # --------------------------------------------------------------------------------------------------------------------
00210         # HLTTriggerTypeFilter                     hltTriggerType 
00211         # HLTLevel1GTSeed                          hltL1sL1SingleEG8 
00212         # HLTPrescaler                             hltPreEle17SWTighterEleIdIsolL1R 
00213         # HLTEgammaL1MatchFilterRegional           hltL1NonIsoHLTNonIsoSingleElectronEt17TighterEleIdIsolL1MatchFilterRegional 
00214         # HLTEgammaEtFilter                        hltL1NonIsoHLTNonIsoSingleElectronEt17TighterEleIdIsolEtFilter 
00215         # HLTEgammaGenericFilter                   hltL1NonIsoHLTNonIsoSingleElectronEt17TighterEleIdIsolR9ShapeFilter 
00216         # HLTEgammaGenericFilter                   hltL1NonIsoHLTNonIsoSingleElectronEt17TighterEleIdIsolClusterShapeFilter 
00217         # HLTEgammaGenericFilter                   hltL1NonIsoHLTNonIsoSingleElectronEt17TIghterEleIdIsolEcalIsolFilter 
00218         # HLTEgammaGenericFilter                   hltL1NonIsoHLTNonIsoSingleElectronEt17TighterEleIdIsolHEFilter 
00219         # HLTEgammaGenericFilter                   hltL1NonIsoHLTNonIsoSingleElectronEt17TighterEleIdIsolHcalIsolFilter 
00220         # HLTElectronPixelMatchFilter              hltL1NonIsoHLTNonIsoSingleElectronEt17TighterEleIdIsolPixelMatchFilter 
00221         # HLTElectronOneOEMinusOneOPFilterRegional hltL1NonIsoHLTNonIsoSingleElectronEt17TighterEleIdIsolOneOEMinusOneOPFilter 
00222         # HLTElectronGenericFilter                 hltL1NonIsoHLTNonIsoSingleElectronEt17TighterEleIdIsolDetaFilter 
00223         # HLTElectronGenericFilter                 hltL1NonIsoHLTNonIsoSingleElectronEt17TighterEleIdIsolDphiFilter 
00224         # HLTElectronGenericFilter                 hltL1NonIsoHLTNonIsoSingleElectronEt17TighterEleIdIsolTrackIsolFilter 
00225         # HLTBool                                  hltBoolEnd 
00226 
00227         # it looks like in the MC menu, all modules have a name containing 'L1NonIso' and then
00228         # have a parameter IsoCollections (which is mostly cms.Input("none")...)
00229 
00230         import FWCore.ParameterSet.Modules
00231 
00232         for moduleName in moduleNames:
00233 
00234             # add protection to avoid accessing non-existing modules
00235             # (not understood why this is needed but happens
00236             # in some cases...).
00237             #
00238             # should also cover the special cases listed afterwards
00239             # (i.e. the check after this one could be removed
00240             # at some point)
00241             if not hasattr(self.process, moduleName):
00242                 continue
00243 
00244             # protection for FastSim HLT menu
00245             # which seems to reference certain modules in some
00246             # paths but these modules are not defined when just
00247             # loading the HLT menu into a process object.
00248             #
00249             # this seems not to happen for the fullsim menu for some
00250             # reason...
00251             if moduleName in ('simulation',
00252                               'offlineBeamSpot',
00253                               'HLTEndSequence'):
00254                 continue
00255 
00256             
00257 
00258             module = getattr(self.process,moduleName)
00259 
00260             if not isinstance(module, FWCore.ParameterSet.Modules.EDFilter):
00261                 continue
00262 
00263             # ignore certain EDFilters
00264             if module.type_() in ('HLTTriggerTypeFilter',
00265                                   'HLTPrescaler',
00266                                   'HLTBool'):
00267                 continue
00268 
00269             # print "XX", module.type_(), moduleName
00270 
00271             #--------------------
00272             if module.type_() == 'HLTLevel1GTSeed':
00273                 # L1 seed
00274                 self.__result.filters.append(self.makePSetForL1SeedFilter(moduleName))
00275                 continue
00276 
00277             #--------------------
00278             if module.type_() == 'HLTEgammaL1MatchFilterRegional':
00279                 # L1 seed to supercluster match
00280                 self.__result.filters.append(self.makePSetForL1SeedToSuperClusterMatchFilter(moduleName))
00281                 continue
00282 
00283             #--------------------
00284 
00285             if module.type_() == "HLTEgammaEtFilter":
00286                 # minimum Et requirement
00287                 self.__result.filters.append(self.makePSetForEtFilter(moduleName))
00288                 continue
00289 
00290             #--------------------
00291 
00292             if module.type_() == "HLTElectronOneOEMinusOneOPFilterRegional":
00293                 self.__result.filters.append(self.makePSetForOneOEMinusOneOPFilter(moduleName))
00294                 continue
00295 
00296             #--------------------
00297             if module.type_() == "HLTElectronPixelMatchFilter":
00298                 self.__result.filters.append(self.makePSetForPixelMatchFilter(moduleName))
00299                 continue
00300 
00301             #--------------------
00302             # generic filters: the module types
00303             # aren't enough, we must check on which
00304             # input collections they filter on
00305             #--------------------
00306 
00307             if module.type_() == "HLTEgammaGenericFilter":
00308 
00309                 pset = self.makePSetForEgammaGenericFilter(module, moduleName)
00310                 if pset != None:
00311                     self.__result.filters.append(pset)
00312                     continue
00313 
00314             #--------------------
00315 
00316             if module.type_() == "HLTElectronGenericFilter":
00317 
00318                 pset = self.makePSetForElectronGenericFilter(module, moduleName)
00319                 if pset != None:
00320                     self.__result.filters.append(pset)
00321                     continue
00322 
00323             #--------------------
00324 
00325 ##            print >> sys.stderr,msgPrefix,"WARNING: unknown module type", module.type_(), " with name " + moduleName + " in path " + pathName
00326                                          
00327     #----------------------------------------
00328     
00329     def makePSetForL1SeedFilter(self,moduleName):
00330         """ generates a PSet to analyze the behaviour of an L1 seed.
00331 
00332             moduleName is the name of the HLT module which filters
00333             on the L1 seed.
00334         """
00335 
00336         return cms.PSet(
00337             PlotBounds = cms.vdouble(0.0, 0.0),
00338             HLTCollectionLabels = cms.InputTag(moduleName,"",self.processName),
00339             IsoCollections = cms.VInputTag(cms.InputTag("none")),
00340             theHLTOutputTypes = cms.int32(TriggerTypeDefs_cfi.TriggerL1NoIsoEG)
00341         ) 
00342 
00343     #----------------------------------------
00344 
00345     def makePSetForL1SeedToSuperClusterMatchFilter(self,moduleName):
00346         """ generates a PSet to analyze the behaviour of L1 to supercluster match filter.
00347 
00348             moduleName is the name of the HLT module which requires the match
00349             between supercluster and L1 seed.
00350         """
00351 
00352         return cms.PSet(
00353             PlotBounds = cms.vdouble(0.0, 0.0),
00354             HLTCollectionLabels = cms.InputTag(moduleName,"",self.processName),
00355             IsoCollections = cms.VInputTag(cms.InputTag("none")),
00356             theHLTOutputTypes = cms.int32(TriggerTypeDefs_cfi.TriggerCluster)
00357         ) 
00358 
00359     #----------------------------------------
00360 
00361     def makePSetForEtFilter(self, moduleName):
00362         """ generates a PSet for the Egamma DQM analyzer for the Et filter """
00363 
00364         return cms.PSet(
00365             PlotBounds = cms.vdouble(0.0, 0.0),
00366             HLTCollectionLabels = cms.InputTag(moduleName,"",self.processName),
00367             IsoCollections = cms.VInputTag(cms.InputTag("none")),
00368             theHLTOutputTypes = cms.int32(TriggerTypeDefs_cfi.TriggerCluster)
00369         )
00370 
00371     #----------------------------------------
00372 
00373     def makePSetForOneOEMinusOneOPFilter(self, moduleName):
00374 
00375         return cms.PSet(
00376             PlotBounds = cms.vdouble(0.0, 0.0),
00377             HLTCollectionLabels = cms.InputTag(moduleName,"",self.processName),
00378             IsoCollections = cms.VInputTag(cms.InputTag("none")),
00379             theHLTOutputTypes = cms.int32(TriggerTypeDefs_cfi.TriggerElectron)
00380             )
00381 
00382     #----------------------------------------
00383 
00384     def makePSetForPixelMatchFilter(self, moduleName):
00385         return cms.PSet(
00386             PlotBounds = cms.vdouble(0.0, 0.0),
00387             HLTCollectionLabels = cms.InputTag(moduleName,"",self.processName),
00388             IsoCollections = cms.VInputTag(cms.InputTag("none")),
00389             theHLTOutputTypes = cms.int32(TriggerTypeDefs_cfi.TriggerCluster)
00390             )
00391 
00392     #----------------------------------------
00393 
00394     def makePSetForEgammaGenericFilter(self, module, moduleName):
00395 
00396         # example usages of HLTEgammaGenericFilter are:
00397         #   R9 shape filter                        hltL1NonIsoHLTNonIsoSingleElectronEt17TighterEleIdIsolR9ShapeFilter 
00398         #   cluster shape filter                   hltL1NonIsoHLTNonIsoSingleElectronEt17TighterEleIdIsolClusterShapeFilter 
00399         #   Ecal isolation filter                  hltL1NonIsoHLTNonIsoSingleElectronEt17TIghterEleIdIsolEcalIsolFilter
00400         #   H/E filter                             hltL1NonIsoHLTNonIsoSingleElectronEt17TighterEleIdIsolHEFilter
00401         #   HCAL isolation filter                  hltL1NonIsoHLTNonIsoSingleElectronEt17TighterEleIdIsolHcalIsolFilter
00402 
00403         # the type of object to look for seems to be the
00404         # same for all uses of HLTEgammaGenericFilter
00405         theHLTOutputTypes = cms.int32(TriggerTypeDefs_cfi.TriggerCluster)
00406 
00407         # infer the type of filter by the type of the producer which
00408         # generates the collection used to cut on this
00409         inputCollectionLabel = module.isoTag.moduleLabel
00410 
00411         inputType = getattr(self.process, inputCollectionLabel).type_()
00412         # print >> sys.stderr, "inputType=",inputType,moduleName
00413 
00414         #--------------------
00415         # sanity check: non-isolated path should be produced by the
00416         # same type of module
00417         #
00418         # first check that the non-iso tag is non-empty
00419         assert(module.nonIsoTag.moduleLabel != "")
00420 
00421         assert(inputType == getattr(self.process, module.nonIsoTag.moduleLabel).type_())
00422 
00423         #--------------------
00424 
00425 
00426         # the following cases seem to have identical PSets ?
00427 
00428         #--------------------
00429         # R9 shape
00430         #--------------------
00431 
00432         if inputType == 'EgammaHLTR9Producer':
00433             return cms.PSet(
00434                 PlotBounds = cms.vdouble(0.0, 0.0),
00435                 HLTCollectionLabels = cms.InputTag(moduleName,"",self.processName),
00436                 IsoCollections = cms.VInputTag(module.isoTag, module.nonIsoTag),
00437                 theHLTOutputTypes = theHLTOutputTypes
00438                 )
00439 
00440         #--------------------
00441         # cluster shape
00442         #--------------------
00443         if inputType == 'EgammaHLTClusterShapeProducer':
00444             return cms.PSet(
00445                 PlotBounds = cms.vdouble(0.0, 0.0),
00446                 HLTCollectionLabels = cms.InputTag(moduleName,"",self.processName),
00447                 IsoCollections = cms.VInputTag(module.isoTag, module.nonIsoTag),
00448                 theHLTOutputTypes = theHLTOutputTypes
00449                 )
00450 
00451         #--------------------
00452         # ecal isolation
00453         #--------------------
00454         if inputType == 'EgammaHLTEcalRecIsolationProducer':
00455             return cms.PSet(
00456                 PlotBounds = cms.vdouble(0.0, 0.0),
00457                 HLTCollectionLabels = cms.InputTag(moduleName,"",self.processName),
00458                 IsoCollections = cms.VInputTag(module.isoTag, module.nonIsoTag),
00459                 theHLTOutputTypes = theHLTOutputTypes
00460                 )
00461 
00462         #--------------------
00463         # HCAL isolation and HE
00464         #--------------------
00465 
00466         if inputType == 'EgammaHLTHcalIsolationProducersRegional':
00467             return cms.PSet(
00468                 PlotBounds = cms.vdouble(0.0, 0.0),
00469                 HLTCollectionLabels = cms.InputTag(moduleName,"",self.processName),
00470                 IsoCollections = cms.VInputTag(module.isoTag, module.nonIsoTag),
00471                 theHLTOutputTypes = theHLTOutputTypes
00472                 )
00473             
00474         
00475         raise Exception("can't determine what the HLTEgammaGenericFilter '" + moduleName + "' should do: uses a collection produced by a module of C++ type '" + inputType + "'")
00476 
00477     #----------------------------------------
00478 
00479     def makePSetForElectronGenericFilter(self, module, moduleName):
00480 
00481         # example usages of HLTElectronGenericFilter are:
00482 
00483         # deta filter      hltL1NonIsoHLTNonIsoSingleElectronEt17TighterEleIdIsolDetaFilter
00484         # dphi filter      hltL1NonIsoHLTNonIsoSingleElectronEt17TighterEleIdIsolDphiFilter
00485         # track isolation  hltL1NonIsoHLTNonIsoSingleElectronEt17TighterEleIdIsolTrackIsolFilter
00486 
00487         # the type of object to look for seems to be the
00488         # same for all uses of HLTEgammaGenericFilter
00489         theHLTOutputTypes = cms.int32(TriggerTypeDefs_cfi.TriggerElectron)
00490 
00491         # infer the type of filter by the type of the producer which
00492         # generates the collection used to cut on this
00493         inputCollectionLabel = module.isoTag.moduleLabel
00494 
00495         inputType = getattr(self.process, inputCollectionLabel).type_()
00496         # print >> sys.stderr, "inputType=",inputType,moduleName
00497 
00498         # sanity check: non-isolated path should be produced by the
00499         # same type of module
00500         assert(inputType == getattr(self.process, module.nonIsoTag.moduleLabel).type_())
00501 
00502         # the following cases seem to have identical PSets ?
00503 
00504         #--------------------
00505         # deta and dphi filter
00506         #--------------------
00507 
00508         # note that whether deta or dphi is used is determined from
00509         # the product instance (not the module label)
00510         if inputType == 'EgammaHLTElectronDetaDphiProducer':
00511 
00512             return cms.PSet(
00513                 PlotBounds = cms.vdouble(0.0, 0.0),
00514                 HLTCollectionLabels = cms.InputTag(moduleName,"",self.processName),
00515                 IsoCollections = cms.VInputTag(module.isoTag, module.nonIsoTag),
00516                 theHLTOutputTypes = theHLTOutputTypes
00517                 )
00518 
00519         #--------------------
00520         # track isolation
00521         #--------------------
00522 
00523         if inputType == 'EgammaHLTElectronTrackIsolationProducers':
00524 
00525             return cms.PSet(
00526                 PlotBounds = cms.vdouble(0.0, 0.0),
00527                 HLTCollectionLabels = cms.InputTag(moduleName,"",self.processName),
00528                 IsoCollections = cms.VInputTag(module.isoTag, module.nonIsoTag),
00529                 theHLTOutputTypes = theHLTOutputTypes
00530                 )
00531         raise Exception("can't determine what the HLTElectronGenericFilter '" + moduleName + "' should do: uses a collection produced by a module of C++ type '" + inputType + "'")
00532 
00533     #----------------------------------------
00534 
00535     def getResult(self):
00536         """ returns the composed analyzer module """
00537         return self.__result
00538 
00539     #----------------------------------------    
00540 
00541 #----------------------------------------------------------------------
00542 # main
00543 #----------------------------------------------------------------------
00544 if __name__ == "__main__":
00545 
00546     import FWCore.ParameterSet.Config as cms
00547     process = cms.Process("MYTEST")
00548     process.load("HLTrigger.Configuration.HLT_GRun_cff")
00549 
00550     moduleMaker = EgammaDQMModuleMaker(process, "HLT_Ele17_SW_TighterEleIdIsol_L1R_v3", 11, 1)
00551 
00552     # print "# ----------------------------------------------------------------------"
00553 
00554     print moduleMaker.getResult().dumpPython()
00555 
00556 #----------------------------------------------------------------------
00557 
00558 def findEgammaPaths(process):
00559     """
00560     returns a dict:
00561 
00562      {
00563        "singleElectron": [ list of single electron path objects ],
00564        "doubleElectron": [ list of double electron path objects ],
00565        "singlePhoton":   [ list of single photon path objects ],
00566        "doublePhoton":   [ list of double photon path objects ],
00567      }
00568 
00569      Note that the elements in the lists are path objects, not path names.
00570 
00571      Note also that this is based on the name of the paths using some
00572      heuristics.
00573      """
00574 
00575     retval = { "singleElectron": [],
00576                "doubleElectron": [],
00577                "singlePhoton":   [],
00578                "doublePhoton":   [],
00579                }
00580     
00581     for path_name, path in process.paths.items():
00582 
00583         # print "XX",path_name.__class__,path.__class__
00584 
00585         if path_name.startswith("AlCa_"):
00586             continue
00587 
00588         if path_name.startswith("DQM_"):
00589             continue
00590 
00591         if not path_name.startswith("HLT_"):
00592             continue
00593 
00594         if path_name.startswith("HLT_Ele"):
00595             retval['singleElectron'].append(path)
00596             continue
00597         
00598         if path_name.startswith("HLT_Photon"):
00599             retval['singlePhoton'].append(path)
00600             continue
00601 
00602         if path_name.startswith("HLT_DoublePhoton"):
00603             retval['doublePhoton'].append(path)
00604             continue
00605 
00606         if path_name.startswith("HLT_DoubleEle"):
00607             retval['doubleElectron'].append(path)
00608             continue
00609 
00610     # end of loop over paths
00611     return retval
00612 
00613 #----------------------------------------------------------------------
00614 
00615 def getModuleNamesOfPath(path):
00616     """ returns the names of the modules found in the given path.
00617 
00618     Note that these are not guaranteed to be in any particular
00619     order.
00620     """
00621 
00622     # this function could actually call getModulesOfSequence(..)
00623     # and then produce a set with the unique names of
00624     # the modules
00625 
00626     import FWCore.ParameterSet.Modules
00627     class Visitor:
00628 
00629         #----------------------------------------
00630         def __init__(self):
00631             self.module_names_found = set()
00632 
00633         #----------------------------------------
00634         def enter(self,visitee):
00635 
00636             if isinstance(visitee, FWCore.ParameterSet.Modules._Module):
00637                 self.module_names_found.add(visitee.label_())
00638 
00639         #----------------------------------------
00640         def leave(self,visitee):
00641             pass
00642 
00643         #----------------------------------------
00644                 
00645     visitor = Visitor()
00646     path.visit(visitor)
00647 
00648     return visitor.module_names_found
00649 
00650 
00651 #----------------------------------------------------------------------
00652 def getCXXTypesOfPath(process, path):
00653     """ returns the names of (classes) of the C++ types of the modules
00654     found in the given path (in no particular order) """
00655 
00656     moduleNames = getModuleNamesOfPath(path)
00657 
00658     retval = set()
00659 
00660     for name in moduleNames:
00661 
00662         # skip those modules which are in the path
00663         # but not in the process object.
00664         # not understood why we need to do this
00665         # but seems to cause problems in practice...
00666         if not hasattr(process,name):
00667             continue
00668 
00669         module = getattr(process, name)
00670 
00671         retval.add(module.type_())
00672 
00673     return retval
00674 
00675 #----------------------------------------------------------------------
00676 
00677 def getModulesOfSequence(sequence):
00678     """ returns the modules found in a sequence.
00679 
00680     Note that a module can appear more than once.
00681     """
00682 
00683     import FWCore.ParameterSet.Modules
00684     class Visitor:
00685 
00686         #----------------------------------------
00687         def __init__(self):
00688             self.modules_found = []
00689 
00690         #----------------------------------------
00691         def enter(self,visitee):
00692 
00693             if isinstance(visitee, FWCore.ParameterSet.Modules._Module):
00694                 self.modules_found.append(visitee)
00695 
00696         #----------------------------------------
00697         def leave(self,visitee):
00698             pass
00699 
00700         #----------------------------------------
00701                 
00702     visitor = Visitor()
00703     sequence.visitNode(visitor)
00704 
00705     return visitor.modules_found
00706 
00707 
00708 #----------------------------------------------------------------------