00001
00002 import FWCore.ParameterSet.Config as cms
00003 import sys, os, re
00004
00005
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
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
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
00066 procName = getProcessName(pdgGen, requiredNumberOfGeneratedObjects)
00067
00068
00069
00070
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
00083 if process != None:
00084 setattr(process, genPartModuleName, genPartModule)
00085
00086 genPartModule.setLabel(genPartModuleName)
00087
00088
00089
00090
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
00106 selectorModule.setLabel(selectorModuleName)
00107
00108
00109
00110
00111
00112 return cms.Sequence(
00113
00114 genPartModule
00115
00116 *
00117
00118
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
00154 self.processName = "HLT"
00155
00156
00157
00158
00159
00160 if cutCollection == None:
00161 cutCollection = "fiducial" + getProcessName(pdgGen, requiredNumberOfGeneratedObjects)
00162
00163
00164
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
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(),
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
00188 cutnum = cms.int32(requiredNumberOfGeneratedObjects),
00189
00190
00191
00192 )
00193
00194
00195
00196
00197
00198
00199
00200
00201 moduleNames = str(self.path).split('+')
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230 import FWCore.ParameterSet.Modules
00231
00232 for moduleName in moduleNames:
00233
00234
00235
00236
00237
00238
00239
00240
00241 if not hasattr(self.process, moduleName):
00242 continue
00243
00244
00245
00246
00247
00248
00249
00250
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
00264 if module.type_() in ('HLTTriggerTypeFilter',
00265 'HLTPrescaler',
00266 'HLTBool'):
00267 continue
00268
00269
00270
00271
00272 if module.type_() == 'HLTLevel1GTSeed':
00273
00274 self.__result.filters.append(self.makePSetForL1SeedFilter(moduleName))
00275 continue
00276
00277
00278 if module.type_() == 'HLTEgammaL1MatchFilterRegional':
00279
00280 self.__result.filters.append(self.makePSetForL1SeedToSuperClusterMatchFilter(moduleName))
00281 continue
00282
00283
00284
00285 if module.type_() == "HLTEgammaEtFilter":
00286
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
00303
00304
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
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
00397
00398
00399
00400
00401
00402
00403
00404
00405 theHLTOutputTypes = cms.int32(TriggerTypeDefs_cfi.TriggerCluster)
00406
00407
00408
00409 inputCollectionLabel = module.isoTag.moduleLabel
00410
00411 inputType = getattr(self.process, inputCollectionLabel).type_()
00412
00413
00414
00415
00416
00417
00418
00419 assert(module.nonIsoTag.moduleLabel != "")
00420
00421 assert(inputType == getattr(self.process, module.nonIsoTag.moduleLabel).type_())
00422
00423
00424
00425
00426
00427
00428
00429
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
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
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
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
00482
00483
00484
00485
00486
00487
00488
00489 theHLTOutputTypes = cms.int32(TriggerTypeDefs_cfi.TriggerElectron)
00490
00491
00492
00493 inputCollectionLabel = module.isoTag.moduleLabel
00494
00495 inputType = getattr(self.process, inputCollectionLabel).type_()
00496
00497
00498
00499
00500 assert(inputType == getattr(self.process, module.nonIsoTag.moduleLabel).type_())
00501
00502
00503
00504
00505
00506
00507
00508
00509
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
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
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
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
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
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
00623
00624
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
00663
00664
00665
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