From ce23dddcfbec11d6241997b32ce9e251ed96d2e7 Mon Sep 17 00:00:00 2001 From: Andrea Date: Thu, 12 Feb 2015 14:08:55 +0100 Subject: [PATCH 01/18] add cmsRun preprocessor --- .../Heppy/python/utils/cmsswPreprocessor.py | 38 ++++++++ PhysicsTools/Heppy/test/example_autofill.py | 7 +- .../Heppy/test/example_autofill_wCmsRun.py | 89 +++++++++++++++++++ PhysicsTools/Heppy/test/makeAK5Jets.py | 28 ++++++ .../HeppyCore/python/framework/config.py | 3 +- .../python/framework/eventsfwlite.py | 14 ++- .../HeppyCore/python/framework/eventstfile.py | 2 +- .../HeppyCore/python/framework/looper.py | 9 +- 8 files changed, 181 insertions(+), 9 deletions(-) create mode 100644 PhysicsTools/Heppy/python/utils/cmsswPreprocessor.py create mode 100644 PhysicsTools/Heppy/test/example_autofill_wCmsRun.py create mode 100644 PhysicsTools/Heppy/test/makeAK5Jets.py diff --git a/PhysicsTools/Heppy/python/utils/cmsswPreprocessor.py b/PhysicsTools/Heppy/python/utils/cmsswPreprocessor.py new file mode 100644 index 00000000000..3d1145fc084 --- /dev/null +++ b/PhysicsTools/Heppy/python/utils/cmsswPreprocessor.py @@ -0,0 +1,38 @@ +import os +import re +import imp +from PhysicsTools.HeppyCore.framework.config import CFG +class CmsswPreprocessor : + def __init__(self,configFile,command="cmsRun") : + self.configFile=configFile + self.command=command + + def run(self,component,wd,firstEvent,nEvents): + print wd,firstEvent,nEvents + if nEvents is None: + nEvents = -1 + cmsswConfig = imp.load_source("cmsRunProcess",self.configFile) + inputfiles= [] + for fn in component.files : + if not re.match("file:.*",fn) and not re.match("root:.*",fn) : + fn="file:"+fn + inputfiles.append(fn) + cmsswConfig.process.source.fileNames = inputfiles + cmsswConfig.process.maxEvents.input=nEvents + #fixme: implement skipEvent / firstevent + + outfilename=wd+"/cmsswPreProcessing.root" + for outName in cmsswConfig.process.endpath.moduleNames() : + out = getattr(cmsswConfig.process,outName) + out.fileName = outfilename + if not hasattr(component,"options"): + component.options = CFG(inputFiles= component.files, name="postCmsrunOptions") + component.options.secondaryInputFiles=[outfilename] + configfile=wd+"/cmsRun_config.py" + f = open(configfile, 'w') + f.write(cmsswConfig.process.dumpPython()) + f.close() + runstring="%s %s >& %s/cmsRun.log" % (self.command,configfile,wd) + print "Running pre-processor: %s " %runstring + os.system(runstring) + return component diff --git a/PhysicsTools/Heppy/test/example_autofill.py b/PhysicsTools/Heppy/test/example_autofill.py index a1aae3228f7..464d68ac0b9 100644 --- a/PhysicsTools/Heppy/test/example_autofill.py +++ b/PhysicsTools/Heppy/test/example_autofill.py @@ -59,11 +59,10 @@ sequence = [VertexAna,LepAna,TauAna,PhoAna,JetAna,TrigAna,treeProducer] - from PhysicsTools.Heppy.utils.miniAodFiles import miniAodFiles sample = cfg.Component( - # files = "/scratch/arizzi/heppy/CMSSW_7_2_0_pre8/src/PhysicsTools/Heppy/test/E21AD523-E548-E411-8DF6-00261894388F.root", - files = miniAodFiles(), + files = ["/scratch/arizzi/Hbb/CMSSW_7_2_2_patch2/src/VHbbAnalysis/Heppy/test/ZLL-8A345C56-6665-E411-9C25-1CC1DE04DF20.root"], + #files = miniAodFiles(), name="ATEST", isMC=False,isEmbed=False ) @@ -78,6 +77,6 @@ # and the following runs the process directly if __name__ == '__main__': from PhysicsTools.HeppyCore.framework.looper import Looper - looper = Looper( 'Loop', config, nPrint = 5) + looper = Looper( 'Loop', config, nPrint = 5,nEvents=300) looper.loop() looper.write() diff --git a/PhysicsTools/Heppy/test/example_autofill_wCmsRun.py b/PhysicsTools/Heppy/test/example_autofill_wCmsRun.py new file mode 100644 index 00000000000..e39a1d3237f --- /dev/null +++ b/PhysicsTools/Heppy/test/example_autofill_wCmsRun.py @@ -0,0 +1,89 @@ +#! /usr/bin/env python +import ROOT +import PhysicsTools.HeppyCore.framework.config as cfg + +from PhysicsTools.Heppy.analyzers.core.AutoFillTreeProducer import * +treeProducer= cfg.Analyzer( + class_object=AutoFillTreeProducer, + verbose=False, + vectorTree = True, + collections = { + #copying input collection p4 information + "slimmedMuons" : ( AutoHandle( ("slimmedMuons",), "std::vector" ), + NTupleCollection("mu", particleType, 4, help="patMuons, directly from MINIAOD") ), + "slimmedElectron" : ( AutoHandle( ("slimmedElectrons",), "std::vector" ), + NTupleCollection("ele", particleType, 4, help="patElectron, directly from MINIAOD") ), + + #standard dumping of objects + "selectedLeptons" : NTupleCollection("leptons", leptonType, 8, help="Leptons after the preselection"), + "selectedTaus" : NTupleCollection("TauGood", tauType, 3, help="Taus after the preselection"), + "cleanJets" : NTupleCollection("Jet", jetType, 8, sortDescendingBy = lambda jet : jet.btag('combinedSecondaryVertexBJetTags'), help="Cental jets after full selection and cleaning, sorted by b-tag"), + #read product of preprocessor-cmsRun + "jetsAK5" : ( AutoHandle( ("ak5PFJetsCHS",), "std::vector" ), + NTupleCollection("JetAk5", particleType, 8, help="AK5 jets")), + #dump of gen objects + "gentopquarks" : NTupleCollection("GenTop", genParticleType, 2, help="Generated top quarks from hard scattering"), + "genbquarks" : NTupleCollection("GenBQuark", genParticleType, 2, help="Generated bottom quarks from top quark decays"), + "genwzquarks" : NTupleCollection("GenQuark", genParticleType, 6, help="Generated quarks from W/Z decays"), + "genleps" : NTupleCollection("GenLep", genParticleType, 6, help="Generated leptons from W/Z decays"), + "gentauleps" : NTupleCollection("GenLepFromTau", genParticleType, 6, help="Generated leptons from decays of taus from W/Z/h decays"), + + } + ) + +# Lepton Analyzer, take its default config +from PhysicsTools.Heppy.analyzers.objects.LeptonAnalyzer import LeptonAnalyzer +LepAna = LeptonAnalyzer.defaultConfig +#replace one parameter +LepAna.loose_muon_pt = 10 + +from PhysicsTools.Heppy.analyzers.objects.VertexAnalyzer import VertexAnalyzer +VertexAna = VertexAnalyzer.defaultConfig + +from PhysicsTools.Heppy.analyzers.objects.PhotonAnalyzer import PhotonAnalyzer +PhoAna = PhotonAnalyzer.defaultConfig + +from PhysicsTools.Heppy.analyzers.objects.TauAnalyzer import TauAnalyzer +TauAna = TauAnalyzer.defaultConfig + +from PhysicsTools.Heppy.analyzers.objects.JetAnalyzer import JetAnalyzer +JetAna = JetAnalyzer.defaultConfig + +from PhysicsTools.Heppy.analyzers.core.TriggerBitAnalyzer import TriggerBitAnalyzer +TrigAna= cfg.Analyzer( + verbose=False, + class_object=TriggerBitAnalyzer, + triggerBits={'any':'HLT_.*'}, +# processName='HLT', +# outprefix='HLT' + ) + + +sequence = [VertexAna,LepAna,TauAna,PhoAna,JetAna,TrigAna,treeProducer] + +from PhysicsTools.Heppy.utils.cmsswPreprocessor import CmsswPreprocessor + +preprocessor = CmsswPreprocessor("makeAK5Jets.py") + +from PhysicsTools.Heppy.utils.miniAodFiles import miniAodFiles +sample = cfg.Component( + files = ["/scratch/arizzi/Hbb/CMSSW_7_2_2_patch2/src/VHbbAnalysis/Heppy/test/ZLL-8A345C56-6665-E411-9C25-1CC1DE04DF20.root"], + #files = miniAodFiles(), + name="ATEST", isMC=False,isEmbed=False + ) + +# the following is declared in case this cfg is used in input to the heppy.py script +selectedComponents = [sample] +from PhysicsTools.HeppyCore.framework.eventsfwlite import Events +config = cfg.Config( components = selectedComponents, + sequence = sequence, + services = [], + events_class = Events, + preprocessor=preprocessor) + +# and the following runs the process directly +if __name__ == '__main__': + from PhysicsTools.HeppyCore.framework.looper import Looper + looper = Looper( 'Loop', config, nPrint = 5,nEvents=300) + looper.loop() + looper.write() diff --git a/PhysicsTools/Heppy/test/makeAK5Jets.py b/PhysicsTools/Heppy/test/makeAK5Jets.py new file mode 100644 index 00000000000..a5e01505c7d --- /dev/null +++ b/PhysicsTools/Heppy/test/makeAK5Jets.py @@ -0,0 +1,28 @@ +import FWCore.ParameterSet.Config as cms + + +process = cms.Process("EX") +process.source = cms.Source("PoolSource", + fileNames = cms.untracked.vstring("file:../ZLL-8A345C56-6665-E411-9C25-1CC1DE04DF20.root") +) +process.maxEvents = cms.untracked.PSet( input = cms.untracked.int32(1000) ) + +process.OUT = cms.OutputModule("PoolOutputModule", + fileName = cms.untracked.string('test.root'), + outputCommands = cms.untracked.vstring(['drop *']) +) +process.endpath= cms.EndPath(process.OUT) + +from RecoJets.JetProducers.ak5PFJets_cfi import ak5PFJets + +# Select candidates that would pass CHS requirements +process.chs = cms.EDFilter("CandPtrSelector", src = cms.InputTag("packedPFCandidates"), cut = cms.string("fromPV")) + +#makes chs ak5 jets (instead of ak4 that are default in miniAOD 70X) +process.ak5PFJetsCHS = ak5PFJets.clone(src = 'chs') +process.OUT.outputCommands.append("keep *_ak5PFJetsCHS_*_EX") + +process.options = cms.untracked.PSet( + wantSummary = cms.untracked.bool(True), # while the timing of this is not reliable in unscheduled mode, it still helps understanding what was actually run + allowUnscheduled = cms.untracked.bool(True) +) diff --git a/PhysicsTools/HeppyCore/python/framework/config.py b/PhysicsTools/HeppyCore/python/framework/config.py index 66d6c288f98..efd9274d472 100644 --- a/PhysicsTools/HeppyCore/python/framework/config.py +++ b/PhysicsTools/HeppyCore/python/framework/config.py @@ -182,7 +182,8 @@ def getWeight( self, intLumi = None): class Config( object ): '''Main configuration object, holds a sequence of analyzers, and a list of components.''' - def __init__(self, components, sequence, services, events_class): + def __init__(self, components, sequence, services, events_class,**kwargs): + self.__dict__.update( **kwargs ) self.components = components self.sequence = sequence self.services = services diff --git a/PhysicsTools/HeppyCore/python/framework/eventsfwlite.py b/PhysicsTools/HeppyCore/python/framework/eventsfwlite.py index a0c530646fa..753311354f7 100644 --- a/PhysicsTools/HeppyCore/python/framework/eventsfwlite.py +++ b/PhysicsTools/HeppyCore/python/framework/eventsfwlite.py @@ -1,8 +1,18 @@ from DataFormats.FWLite import Events as FWLiteEvents class Events(object): - def __init__(self, files, tree_name): - self.events = FWLiteEvents(files) + def __init__(self, files, tree_name, **kwargs): + if "options" in kwargs : + options=kwargs["options"] + if not hasattr(options,"inputFiles"): + options.inputFiles=files + if not hasattr(options,"maxEvents"): + options.maxEvents = 0 + if not hasattr(options,"secondaryInputFiles"): + options.secondaryInputFiles = [] + self.events = FWLiteEvents(options=options) + else : + self.events = FWLiteEvents(files) def __len__(self): return self.events.size() diff --git a/PhysicsTools/HeppyCore/python/framework/eventstfile.py b/PhysicsTools/HeppyCore/python/framework/eventstfile.py index 03869461174..b409c5bb179 100644 --- a/PhysicsTools/HeppyCore/python/framework/eventstfile.py +++ b/PhysicsTools/HeppyCore/python/framework/eventstfile.py @@ -6,7 +6,7 @@ class Events(object): '''Event list from a tree in a root file. ''' - def __init__(self, filename, treename): + def __init__(self, filename, treename, **kwargs): self.file = TFile(filename) if self.file.IsZombie(): raise ValueError('file {fnam} does not exist'.format(fnam=filename)) diff --git a/PhysicsTools/HeppyCore/python/framework/looper.py b/PhysicsTools/HeppyCore/python/framework/looper.py index 6403a74db5c..4c7a4d4609b 100644 --- a/PhysicsTools/HeppyCore/python/framework/looper.py +++ b/PhysicsTools/HeppyCore/python/framework/looper.py @@ -89,7 +89,14 @@ def __init__( self, name, if len(self.cfg_comp.files)==0: errmsg = 'please provide at least an input file in the files attribute of this component\n' + str(self.cfg_comp) raise ValueError( errmsg ) - self.events = config.events_class(self.cfg_comp.files, tree_name) + if hasattr(config,"preprocessor") : + self.cfg_comp = config.preprocessor.run(self.cfg_comp,self.outDir,firstEvent,nEvents) + if hasattr(self.cfg_comp,"options"): + print self.cfg_comp.files,self.cfg_comp.options + self.events = config.events_class(self.cfg_comp.files, tree_name,options=self.cfg_comp.options) + else : + self.events = config.events_class(self.cfg_comp.files, tree_name) + if hasattr(self.cfg_comp, 'fineSplit'): fineSplitIndex, fineSplitFactor = self.cfg_comp.fineSplit if fineSplitFactor > 1: From 451ae2696303cde8f090d6af4e165fdc4ddf99e9 Mon Sep 17 00:00:00 2001 From: Andrea Date: Thu, 12 Feb 2015 14:16:50 +0100 Subject: [PATCH 02/18] clean up and fix file hierarchy --- PhysicsTools/Heppy/python/utils/cmsswPreprocessor.py | 12 ++++++++++-- PhysicsTools/Heppy/test/example_autofill.py | 3 +-- PhysicsTools/Heppy/test/example_autofill_wCmsRun.py | 4 ++-- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/PhysicsTools/Heppy/python/utils/cmsswPreprocessor.py b/PhysicsTools/Heppy/python/utils/cmsswPreprocessor.py index 3d1145fc084..c5165c93051 100644 --- a/PhysicsTools/Heppy/python/utils/cmsswPreprocessor.py +++ b/PhysicsTools/Heppy/python/utils/cmsswPreprocessor.py @@ -26,8 +26,16 @@ def run(self,component,wd,firstEvent,nEvents): out = getattr(cmsswConfig.process,outName) out.fileName = outfilename if not hasattr(component,"options"): - component.options = CFG(inputFiles= component.files, name="postCmsrunOptions") - component.options.secondaryInputFiles=[outfilename] + component.options = CFG(name="postCmsrunOptions") + #use original as primary and new as secondary + #component.options.inputFiles= component.files + #component.options.secondaryInputFiles=[outfilename] + + #use new as primary and original as secondary + component.options.secondaryInputFiles= component.files + component.options.inputFiles=[outfilename] + component.files=[outfilename] + configfile=wd+"/cmsRun_config.py" f = open(configfile, 'w') f.write(cmsswConfig.process.dumpPython()) diff --git a/PhysicsTools/Heppy/test/example_autofill.py b/PhysicsTools/Heppy/test/example_autofill.py index 464d68ac0b9..f171c53ab1f 100644 --- a/PhysicsTools/Heppy/test/example_autofill.py +++ b/PhysicsTools/Heppy/test/example_autofill.py @@ -61,8 +61,7 @@ from PhysicsTools.Heppy.utils.miniAodFiles import miniAodFiles sample = cfg.Component( - files = ["/scratch/arizzi/Hbb/CMSSW_7_2_2_patch2/src/VHbbAnalysis/Heppy/test/ZLL-8A345C56-6665-E411-9C25-1CC1DE04DF20.root"], - #files = miniAodFiles(), + files = miniAodFiles(), name="ATEST", isMC=False,isEmbed=False ) diff --git a/PhysicsTools/Heppy/test/example_autofill_wCmsRun.py b/PhysicsTools/Heppy/test/example_autofill_wCmsRun.py index e39a1d3237f..488751174af 100644 --- a/PhysicsTools/Heppy/test/example_autofill_wCmsRun.py +++ b/PhysicsTools/Heppy/test/example_autofill_wCmsRun.py @@ -67,8 +67,8 @@ from PhysicsTools.Heppy.utils.miniAodFiles import miniAodFiles sample = cfg.Component( - files = ["/scratch/arizzi/Hbb/CMSSW_7_2_2_patch2/src/VHbbAnalysis/Heppy/test/ZLL-8A345C56-6665-E411-9C25-1CC1DE04DF20.root"], - #files = miniAodFiles(), +# files = ["/scratch/arizzi/Hbb/CMSSW_7_2_2_patch2/src/VHbbAnalysis/Heppy/test/ZLL-8A345C56-6665-E411-9C25-1CC1DE04DF20.root"], + files = miniAodFiles(), name="ATEST", isMC=False,isEmbed=False ) From 80b1992cf9bf86af2f5ee130bc07156d95eeff6e Mon Sep 17 00:00:00 2001 From: Andrea Date: Thu, 12 Feb 2015 15:26:01 +0100 Subject: [PATCH 03/18] remove kwargs --- PhysicsTools/HeppyCore/python/framework/config.py | 4 ++-- PhysicsTools/HeppyCore/python/framework/eventsfwlite.py | 5 ++--- PhysicsTools/HeppyCore/python/framework/eventstfile.py | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/PhysicsTools/HeppyCore/python/framework/config.py b/PhysicsTools/HeppyCore/python/framework/config.py index efd9274d472..d06d87f5f2e 100644 --- a/PhysicsTools/HeppyCore/python/framework/config.py +++ b/PhysicsTools/HeppyCore/python/framework/config.py @@ -182,8 +182,8 @@ def getWeight( self, intLumi = None): class Config( object ): '''Main configuration object, holds a sequence of analyzers, and a list of components.''' - def __init__(self, components, sequence, services, events_class,**kwargs): - self.__dict__.update( **kwargs ) + def __init__(self, components, sequence, services, events_class,preprocessor=None): + self.preprocessor = preprocessor self.components = components self.sequence = sequence self.services = services diff --git a/PhysicsTools/HeppyCore/python/framework/eventsfwlite.py b/PhysicsTools/HeppyCore/python/framework/eventsfwlite.py index 753311354f7..a8dc2b106e2 100644 --- a/PhysicsTools/HeppyCore/python/framework/eventsfwlite.py +++ b/PhysicsTools/HeppyCore/python/framework/eventsfwlite.py @@ -1,9 +1,8 @@ from DataFormats.FWLite import Events as FWLiteEvents class Events(object): - def __init__(self, files, tree_name, **kwargs): - if "options" in kwargs : - options=kwargs["options"] + def __init__(self, files, tree_name, options=None): + if options is not None : if not hasattr(options,"inputFiles"): options.inputFiles=files if not hasattr(options,"maxEvents"): diff --git a/PhysicsTools/HeppyCore/python/framework/eventstfile.py b/PhysicsTools/HeppyCore/python/framework/eventstfile.py index b409c5bb179..e577da31e6f 100644 --- a/PhysicsTools/HeppyCore/python/framework/eventstfile.py +++ b/PhysicsTools/HeppyCore/python/framework/eventstfile.py @@ -6,7 +6,7 @@ class Events(object): '''Event list from a tree in a root file. ''' - def __init__(self, filename, treename, **kwargs): + def __init__(self, filename, treename, options=None): self.file = TFile(filename) if self.file.IsZombie(): raise ValueError('file {fnam} does not exist'.format(fnam=filename)) From b7a82c2d146b5f467b3c10b382c52abd8dd3f9b4 Mon Sep 17 00:00:00 2001 From: Andrea Date: Tue, 27 Jan 2015 16:11:10 +0100 Subject: [PATCH 04/18] Heppy: fixes in PileUpAnalyzer, adding default config --- .../Heppy/python/analyzers/core/PileUpAnalyzer.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/PhysicsTools/Heppy/python/analyzers/core/PileUpAnalyzer.py b/PhysicsTools/Heppy/python/analyzers/core/PileUpAnalyzer.py index 0e6564e5f24..d09dbb62e7e 100644 --- a/PhysicsTools/Heppy/python/analyzers/core/PileUpAnalyzer.py +++ b/PhysicsTools/Heppy/python/analyzers/core/PileUpAnalyzer.py @@ -4,6 +4,8 @@ from PhysicsTools.Heppy.analyzers.core.AutoHandle import AutoHandle from PhysicsTools.HeppyCore.statistics.average import Average from PhysicsTools.Heppy.physicsutils.PileUpSummaryInfo import PileUpSummaryInfo +import PhysicsTools.HeppyCore.framework.config as cfg + from ROOT import TFile, TH1F class PileUpAnalyzer( Analyzer ): @@ -57,7 +59,7 @@ def __init__(self, cfg_ana, cfg_comp, looperName): self.cfg_comp.puFileData = None if self.cfg_comp.isMC or self.cfg_comp.isEmbed: - if self.cfg_comp.puFileMC is None and self.cfg_comp.puFileData is None: + if not hasattr(self.cfg_comp,"puFileMC") or (self.cfg_comp.puFileMC is None and self.cfg_comp.puFileData is None): self.enable = False else: assert( os.path.isfile(self.cfg_comp.puFileMC) ) @@ -145,3 +147,12 @@ def write(self, setup): super(PileUpAnalyzer, self).write(setup) if self.cfg_comp.isMC and self.doHists: self.rawmcpileup.write() + + +setattr(PileUpAnalyzer,"defaultConfig", cfg.Analyzer( + class_object = PileUpAnalyzer, + true = True, # use number of true interactions for reweighting + makeHists=False +) +) + From 18203e7a28d9758d3584f9621a69a23e4472086c Mon Sep 17 00:00:00 2001 From: Andrea Date: Fri, 13 Feb 2015 08:55:16 +0100 Subject: [PATCH 05/18] Heppy : fix LHE analyzer pedning a better fix in FWLite --- .../Heppy/python/analyzers/gen/LHEAnalyzer.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/PhysicsTools/Heppy/python/analyzers/gen/LHEAnalyzer.py b/PhysicsTools/Heppy/python/analyzers/gen/LHEAnalyzer.py index 1b8c03905df..46e1862cf0d 100644 --- a/PhysicsTools/Heppy/python/analyzers/gen/LHEAnalyzer.py +++ b/PhysicsTools/Heppy/python/analyzers/gen/LHEAnalyzer.py @@ -8,6 +8,7 @@ class LHEAnalyzer( Analyzer ): """ """ def __init__(self, cfg_ana, cfg_comp, looperName ): super(LHEAnalyzer,self).__init__(cfg_ana,cfg_comp,looperName) + self.lheh=Handle('LHEEventProduct') def declareHandles(self): super(LHEAnalyzer, self).declareHandles() @@ -24,12 +25,14 @@ def process(self, event): event.lheHT=0 event.lheNj=0 event.lheV_pt = 0 - h=Handle('LHEEventProduct') - event.input.getByLabel( 'externalLHEProducer',h) - if not h.isValid() : + try: + event.input.getByLabel( 'externalLHEProducer',self.lheh) + except : + return True + if not self.lheh.isValid() : return True self.readCollections( event.input ) - hepeup=h.product().hepeup() + hepeup=self.lheh.product().hepeup() pup=hepeup.PUP l=None lBar=None From 92c92cf079b58964398c980831eb37738d766e7a Mon Sep 17 00:00:00 2001 From: Andrea Date: Fri, 13 Feb 2015 09:36:59 +0100 Subject: [PATCH 06/18] bug fix for running without preprocessor --- PhysicsTools/HeppyCore/python/framework/looper.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PhysicsTools/HeppyCore/python/framework/looper.py b/PhysicsTools/HeppyCore/python/framework/looper.py index 4c7a4d4609b..bfe9da15ada 100644 --- a/PhysicsTools/HeppyCore/python/framework/looper.py +++ b/PhysicsTools/HeppyCore/python/framework/looper.py @@ -89,7 +89,7 @@ def __init__( self, name, if len(self.cfg_comp.files)==0: errmsg = 'please provide at least an input file in the files attribute of this component\n' + str(self.cfg_comp) raise ValueError( errmsg ) - if hasattr(config,"preprocessor") : + if hasattr(config,"preprocessor") and config.preprocessor is not None : self.cfg_comp = config.preprocessor.run(self.cfg_comp,self.outDir,firstEvent,nEvents) if hasattr(self.cfg_comp,"options"): print self.cfg_comp.files,self.cfg_comp.options From 65ce01f7cb1f5c74f90ca843bf634c9800bf2ee6 Mon Sep 17 00:00:00 2001 From: Andrea Date: Fri, 13 Feb 2015 09:39:16 +0100 Subject: [PATCH 07/18] more complete and commented examples --- PhysicsTools/Heppy/test/example_autofill.py | 94 +++++++++++---- .../Heppy/test/example_autofill_wCmsRun.py | 108 +++++++++++++----- 2 files changed, 147 insertions(+), 55 deletions(-) diff --git a/PhysicsTools/Heppy/test/example_autofill.py b/PhysicsTools/Heppy/test/example_autofill.py index f171c53ab1f..4938da7c0aa 100644 --- a/PhysicsTools/Heppy/test/example_autofill.py +++ b/PhysicsTools/Heppy/test/example_autofill.py @@ -2,80 +2,126 @@ import ROOT import PhysicsTools.HeppyCore.framework.config as cfg +# The content of the output tree is defined here +# the definitions of the NtupleObjects are located under PhysicsTools/Heppy/pythonanalyzers/objects/autophobj.py + from PhysicsTools.Heppy.analyzers.core.AutoFillTreeProducer import * treeProducer= cfg.Analyzer( class_object=AutoFillTreeProducer, verbose=False, vectorTree = True, + #here the list of simple event variables (floats, int) can be specified + globalVariables = [ + NTupleVariable("rho", lambda ev: ev.rho, float, help="jets rho"), + ], + #here one can specify compound objects + globalObjects = { + "met" : NTupleObject("met", metType, help="PF E_{T}^{miss}, after default type 1 corrections"), + }, collections = { - #copying input collection p4 information - "slimmedMuons" : ( AutoHandle( ("slimmedMuons",), "std::vector" ), - NTupleCollection("mu", particleType, 4, help="patMuons, directly from MINIAOD") ), - "slimmedElectron" : ( AutoHandle( ("slimmedElectrons",), "std::vector" ), - NTupleCollection("ele", particleType, 4, help="patElectron, directly from MINIAOD") ), + #The following would just store the electrons and muons from miniaod without any selection or cleaning + # only the basice particle information is saved + #"slimmedMuons" : ( AutoHandle( ("slimmedMuons",), "std::vector" ), + # NTupleCollection("mu", particleType, 4, help="patMuons, directly from MINIAOD") ), + #"slimmedElectron" : ( AutoHandle( ("slimmedElectrons",), "std::vector" ), + # NTupleCollection("ele", particleType, 4, help="patElectron, directly from MINIAOD") ), #standard dumping of objects "selectedLeptons" : NTupleCollection("leptons", leptonType, 8, help="Leptons after the preselection"), "selectedTaus" : NTupleCollection("TauGood", tauType, 3, help="Taus after the preselection"), - "cleanJets" : NTupleCollection("Jet", jetType, 8, sortDescendingBy = lambda jet : jet.btag('combinedSecondaryVertexBJetTags'), - help="Cental jets after full selection and cleaning, sorted by b-tag"), + "cleanJets" : NTupleCollection("Jet", jetType, 8, help="Cental jets after full selection and cleaning, sorted by b-tag"), #dump of gen objects "gentopquarks" : NTupleCollection("GenTop", genParticleType, 2, help="Generated top quarks from hard scattering"), "genbquarks" : NTupleCollection("GenBQuark", genParticleType, 2, help="Generated bottom quarks from top quark decays"), - "genwzquarks" : NTupleCollection("GenQuark", genParticleType, 6, help="Generated quarks from W/Z decays"), - "genleps" : NTupleCollection("GenLep", genParticleType, 6, help="Generated leptons from W/Z decays"), + "genwzquarks" : NTupleCollection("GenQuark", genParticleType, 6, help="Generated quarks from W/Z decays"), + "genleps" : NTupleCollection("GenLep", genParticleType, 6, help="Generated leptons from W/Z decays"), "gentauleps" : NTupleCollection("GenLepFromTau", genParticleType, 6, help="Generated leptons from decays of taus from W/Z/h decays"), } ) -# Lepton Analyzer, take its default config +# Import standard analyzers and take their default config from PhysicsTools.Heppy.analyzers.objects.LeptonAnalyzer import LeptonAnalyzer LepAna = LeptonAnalyzer.defaultConfig -#replace one parameter -LepAna.loose_muon_pt = 10 - from PhysicsTools.Heppy.analyzers.objects.VertexAnalyzer import VertexAnalyzer VertexAna = VertexAnalyzer.defaultConfig - from PhysicsTools.Heppy.analyzers.objects.PhotonAnalyzer import PhotonAnalyzer PhoAna = PhotonAnalyzer.defaultConfig - from PhysicsTools.Heppy.analyzers.objects.TauAnalyzer import TauAnalyzer TauAna = TauAnalyzer.defaultConfig - from PhysicsTools.Heppy.analyzers.objects.JetAnalyzer import JetAnalyzer JetAna = JetAnalyzer.defaultConfig +from PhysicsTools.Heppy.analyzers.gen.LHEAnalyzer import LHEAnalyzer +LHEAna = LHEAnalyzer.defaultConfig +from PhysicsTools.Heppy.analyzers.gen.GeneratorAnalyzer import GeneratorAnalyzer +GenAna = GeneratorAnalyzer.defaultConfig +from PhysicsTools.Heppy.analyzers.objects.METAnalyzer import METAnalyzer +METAna = METAnalyzer.defaultConfig +from PhysicsTools.Heppy.analyzers.core.PileUpAnalyzer import PileUpAnalyzer +PUAna = PileUpAnalyzer.defaultConfig +from PhysicsTools.Heppy.analyzers.core.TriggerBitAnalyzer import TriggerBitAnalyzer +FlagsAna = TriggerBitAnalyzer.defaultEventFlagsConfig +# Configure trigger bit analyzer from PhysicsTools.Heppy.analyzers.core.TriggerBitAnalyzer import TriggerBitAnalyzer TrigAna= cfg.Analyzer( verbose=False, class_object=TriggerBitAnalyzer, - triggerBits={'any':'HLT_.*'}, + #grouping several paths into a single flag + # v* can be used to ignore the version of a path + triggerBits={ + 'ELE':["HLT_Ele23_Ele12_CaloId_TrackId_Iso_v*","HLT_Ele32_eta2p1_WP85_Gsf_v*","HLT_Ele32_eta2p1_WP85_Gsf_v*"], + 'MU': ["HLT_Mu17_TrkIsoVVL_TkMu8_TrkIsoVVL_v*","HLT_Mu17_TrkIsoVVL_Mu8_TrkIsoVVL_v*","HLT_IsoTkMu24_eta2p1_IterTrk02_v*","HLT_IsoTkMu24_IterTrk02_v*"], + }, # processName='HLT', # outprefix='HLT' + #setting 'unrollbits' to true will not only store the OR for each set of trigger bits but also the individual bits + #caveat: this does not unroll the version numbers + unrollbits=True ) -sequence = [VertexAna,LepAna,TauAna,PhoAna,JetAna,TrigAna,treeProducer] +#replace some parameters +LepAna.loose_muon_pt = 10 + +sequence = [LHEAna,FlagsAna, GenAna, PUAna,TrigAna,VertexAna,LepAna,TauAna,PhoAna,JetAna,METAna,treeProducer] + +#use tfile service to provide a single TFile to all modules where they +#can write any root object. If the name is 'outputfile' or the one specified in treeProducer +#also the treeProducer uses this file +from PhysicsTools.HeppyCore.framework.services.tfile import TFileService +output_service = cfg.Service( + TFileService, + 'outputfile', + name="outputfile", + fname='tree.root', + option='recreate' + ) + +# the following two lines are just for automatic testing +# they are not needed for running on your own samples from PhysicsTools.Heppy.utils.miniAodFiles import miniAodFiles +testfiles=miniAodFiles() + sample = cfg.Component( - files = miniAodFiles(), - name="ATEST", isMC=False,isEmbed=False +#specify the file you want to run on + files = ["/scratch/arizzi/Hbb/CMSSW_7_2_2_patch2/src/VHbbAnalysis/Heppy/test/ZLL-8A345C56-6665-E411-9C25-1CC1DE04DF20.root"], +# files = testfiles, + name="SingleSample", isMC=False,isEmbed=False ) # the following is declared in case this cfg is used in input to the heppy.py script -selectedComponents = [sample] from PhysicsTools.HeppyCore.framework.eventsfwlite import Events +selectedComponents = [sample] config = cfg.Config( components = selectedComponents, sequence = sequence, - services = [], + services = [output_service], events_class = Events) -# and the following runs the process directly +# and the following runs the process directly if running as with python filename.py if __name__ == '__main__': from PhysicsTools.HeppyCore.framework.looper import Looper - looper = Looper( 'Loop', config, nPrint = 5,nEvents=300) + looper = Looper( 'Loop', config, nPrint = 5,nEvents=300) looper.loop() looper.write() diff --git a/PhysicsTools/Heppy/test/example_autofill_wCmsRun.py b/PhysicsTools/Heppy/test/example_autofill_wCmsRun.py index 488751174af..a9026596f15 100644 --- a/PhysicsTools/Heppy/test/example_autofill_wCmsRun.py +++ b/PhysicsTools/Heppy/test/example_autofill_wCmsRun.py @@ -2,88 +2,134 @@ import ROOT import PhysicsTools.HeppyCore.framework.config as cfg +# The content of the output tree is defined here +# the definitions of the NtupleObjects are located under PhysicsTools/Heppy/pythonanalyzers/objects/autophobj.py + from PhysicsTools.Heppy.analyzers.core.AutoFillTreeProducer import * treeProducer= cfg.Analyzer( class_object=AutoFillTreeProducer, verbose=False, vectorTree = True, + #here the list of simple event variables (floats, int) can be specified + globalVariables = [ + NTupleVariable("rho", lambda ev: ev.rho, float, help="jets rho"), + ], + #here one can specify compound objects + globalObjects = { + "met" : NTupleObject("met", metType, help="PF E_{T}^{miss}, after default type 1 corrections"), + }, collections = { - #copying input collection p4 information - "slimmedMuons" : ( AutoHandle( ("slimmedMuons",), "std::vector" ), - NTupleCollection("mu", particleType, 4, help="patMuons, directly from MINIAOD") ), - "slimmedElectron" : ( AutoHandle( ("slimmedElectrons",), "std::vector" ), - NTupleCollection("ele", particleType, 4, help="patElectron, directly from MINIAOD") ), + #The following would just store the electrons and muons from miniaod without any selection or cleaning + # only the basice particle information is saved + #"slimmedMuons" : ( AutoHandle( ("slimmedMuons",), "std::vector" ), + # NTupleCollection("mu", particleType, 4, help="patMuons, directly from MINIAOD") ), + #"slimmedElectron" : ( AutoHandle( ("slimmedElectrons",), "std::vector" ), + # NTupleCollection("ele", particleType, 4, help="patElectron, directly from MINIAOD") ), + + #read product of preprocessor-cmsRun + "jetsAK5" : ( AutoHandle( ("ak5PFJetsCHS",), "std::vector" ), + NTupleCollection("JetAk5", particleType, 8, help="AK5 jets")), #standard dumping of objects "selectedLeptons" : NTupleCollection("leptons", leptonType, 8, help="Leptons after the preselection"), "selectedTaus" : NTupleCollection("TauGood", tauType, 3, help="Taus after the preselection"), - "cleanJets" : NTupleCollection("Jet", jetType, 8, sortDescendingBy = lambda jet : jet.btag('combinedSecondaryVertexBJetTags'), help="Cental jets after full selection and cleaning, sorted by b-tag"), - #read product of preprocessor-cmsRun - "jetsAK5" : ( AutoHandle( ("ak5PFJetsCHS",), "std::vector" ), - NTupleCollection("JetAk5", particleType, 8, help="AK5 jets")), + "cleanJets" : NTupleCollection("Jet", jetType, 8, help="Cental jets after full selection and cleaning, sorted by b-tag"), #dump of gen objects "gentopquarks" : NTupleCollection("GenTop", genParticleType, 2, help="Generated top quarks from hard scattering"), "genbquarks" : NTupleCollection("GenBQuark", genParticleType, 2, help="Generated bottom quarks from top quark decays"), - "genwzquarks" : NTupleCollection("GenQuark", genParticleType, 6, help="Generated quarks from W/Z decays"), - "genleps" : NTupleCollection("GenLep", genParticleType, 6, help="Generated leptons from W/Z decays"), + "genwzquarks" : NTupleCollection("GenQuark", genParticleType, 6, help="Generated quarks from W/Z decays"), + "genleps" : NTupleCollection("GenLep", genParticleType, 6, help="Generated leptons from W/Z decays"), "gentauleps" : NTupleCollection("GenLepFromTau", genParticleType, 6, help="Generated leptons from decays of taus from W/Z/h decays"), } ) -# Lepton Analyzer, take its default config +# Import standard analyzers and take their default config from PhysicsTools.Heppy.analyzers.objects.LeptonAnalyzer import LeptonAnalyzer LepAna = LeptonAnalyzer.defaultConfig -#replace one parameter -LepAna.loose_muon_pt = 10 - from PhysicsTools.Heppy.analyzers.objects.VertexAnalyzer import VertexAnalyzer VertexAna = VertexAnalyzer.defaultConfig - from PhysicsTools.Heppy.analyzers.objects.PhotonAnalyzer import PhotonAnalyzer PhoAna = PhotonAnalyzer.defaultConfig - from PhysicsTools.Heppy.analyzers.objects.TauAnalyzer import TauAnalyzer TauAna = TauAnalyzer.defaultConfig - from PhysicsTools.Heppy.analyzers.objects.JetAnalyzer import JetAnalyzer JetAna = JetAnalyzer.defaultConfig +from PhysicsTools.Heppy.analyzers.gen.LHEAnalyzer import LHEAnalyzer +LHEAna = LHEAnalyzer.defaultConfig +from PhysicsTools.Heppy.analyzers.gen.GeneratorAnalyzer import GeneratorAnalyzer +GenAna = GeneratorAnalyzer.defaultConfig +from PhysicsTools.Heppy.analyzers.objects.METAnalyzer import METAnalyzer +METAna = METAnalyzer.defaultConfig +from PhysicsTools.Heppy.analyzers.core.PileUpAnalyzer import PileUpAnalyzer +PUAna = PileUpAnalyzer.defaultConfig +from PhysicsTools.Heppy.analyzers.core.TriggerBitAnalyzer import TriggerBitAnalyzer +FlagsAna = TriggerBitAnalyzer.defaultEventFlagsConfig +# Configure trigger bit analyzer from PhysicsTools.Heppy.analyzers.core.TriggerBitAnalyzer import TriggerBitAnalyzer TrigAna= cfg.Analyzer( verbose=False, class_object=TriggerBitAnalyzer, - triggerBits={'any':'HLT_.*'}, + #grouping several paths into a single flag + # v* can be used to ignore the version of a path + triggerBits={ + 'ELE':["HLT_Ele23_Ele12_CaloId_TrackId_Iso_v*","HLT_Ele32_eta2p1_WP85_Gsf_v*","HLT_Ele32_eta2p1_WP85_Gsf_v*"], + 'MU': ["HLT_Mu17_TrkIsoVVL_TkMu8_TrkIsoVVL_v*","HLT_Mu17_TrkIsoVVL_Mu8_TrkIsoVVL_v*","HLT_IsoTkMu24_eta2p1_IterTrk02_v*","HLT_IsoTkMu24_IterTrk02_v*"], + }, # processName='HLT', # outprefix='HLT' + #setting 'unrollbits' to true will not only store the OR for each set of trigger bits but also the individual bits + #caveat: this does not unroll the version numbers + unrollbits=True ) -sequence = [VertexAna,LepAna,TauAna,PhoAna,JetAna,TrigAna,treeProducer] -from PhysicsTools.Heppy.utils.cmsswPreprocessor import CmsswPreprocessor +#replace some parameters +LepAna.loose_muon_pt = 10 -preprocessor = CmsswPreprocessor("makeAK5Jets.py") +sequence = [LHEAna,FlagsAna, GenAna, PUAna,TrigAna,VertexAna,LepAna,TauAna,PhoAna,JetAna,METAna,treeProducer] + +#use tfile service to provide a single TFile to all modules where they +#can write any root object. If the name is 'outputfile' or the one specified in treeProducer +#also the treeProducer uses this file +from PhysicsTools.HeppyCore.framework.services.tfile import TFileService +output_service = cfg.Service( + TFileService, + 'outputfile', + name="outputfile", + fname='tree.root', + option='recreate' + ) +# the following two lines are just for automatic testing +# they are not needed for running on your own samples from PhysicsTools.Heppy.utils.miniAodFiles import miniAodFiles +testfiles=miniAodFiles() + sample = cfg.Component( -# files = ["/scratch/arizzi/Hbb/CMSSW_7_2_2_patch2/src/VHbbAnalysis/Heppy/test/ZLL-8A345C56-6665-E411-9C25-1CC1DE04DF20.root"], - files = miniAodFiles(), - name="ATEST", isMC=False,isEmbed=False +#specify the file you want to run on + files = ["/scratch/arizzi/Hbb/CMSSW_7_2_2_patch2/src/VHbbAnalysis/Heppy/test/ZLL-8A345C56-6665-E411-9C25-1CC1DE04DF20.root"], +# files = testfiles, + name="SingleSample", isMC=False,isEmbed=False ) +from PhysicsTools.Heppy.utils.cmsswPreprocessor import CmsswPreprocessor +preprocessor = CmsswPreprocessor("makeAK5Jets.py") + # the following is declared in case this cfg is used in input to the heppy.py script -selectedComponents = [sample] from PhysicsTools.HeppyCore.framework.eventsfwlite import Events +selectedComponents = [sample] config = cfg.Config( components = selectedComponents, sequence = sequence, - services = [], - events_class = Events, - preprocessor=preprocessor) + services = [output_service], + preprocessor=preprocessor, #this would run cmsRun makeAK5Jets.py before running Heppy + events_class = Events) -# and the following runs the process directly +# and the following runs the process directly if running as with python filename.py if __name__ == '__main__': from PhysicsTools.HeppyCore.framework.looper import Looper - looper = Looper( 'Loop', config, nPrint = 5,nEvents=300) + looper = Looper( 'Loop', config, nPrint = 5,nEvents=300) looper.loop() looper.write() From 2303f3c33ccd69ee90bfa8b8fb900524072f70b7 Mon Sep 17 00:00:00 2001 From: Giovanni Date: Mon, 2 Feb 2015 17:13:46 +0100 Subject: [PATCH 08/18] Heppy: tool to recompute lepton isolation in C++; weights for neutrals not validated --- .../Heppy/interface/IsolationComputer.h | 63 ++++++ PhysicsTools/Heppy/src/IsolationComputer.cc | 188 ++++++++++++++++++ PhysicsTools/Heppy/src/classes.h | 1 + PhysicsTools/Heppy/src/classes_def.xml | 1 + 4 files changed, 253 insertions(+) create mode 100644 PhysicsTools/Heppy/interface/IsolationComputer.h create mode 100644 PhysicsTools/Heppy/src/IsolationComputer.cc diff --git a/PhysicsTools/Heppy/interface/IsolationComputer.h b/PhysicsTools/Heppy/interface/IsolationComputer.h new file mode 100644 index 00000000000..d23b1a01fae --- /dev/null +++ b/PhysicsTools/Heppy/interface/IsolationComputer.h @@ -0,0 +1,63 @@ +#ifndef PhysicsTools_Heppy_IsolationComputer_h +#define PhysicsTools_Heppy_IsolationComputer_h + +#include +#include "DataFormats/PatCandidates/interface/PackedCandidate.h" + +namespace heppy { +class IsolationComputer { + public: + /// Create the calculator; optionally specify a cone for computing deltaBeta weights + IsolationComputer(float weightCone=-1) : weightCone_(weightCone) {} + + /// Self-veto policy + enum SelfVetoPolicy { + selfVetoNone=0, selfVetoAll=1, selfVetoFirst=2 + }; + /// Initialize with the list of packed candidates (note: clears also all vetos) + void setPackedCandidates(const std::vector & all) ; + + /// veto footprint from this candidate, for the isolation of all candidates and also for calculation of neutral weights (if used) + void addVetos(const reco::Candidate &cand) ; + + /// clear all vetos + void clearVetos() ; + + /// Isolation from charged from the PV + float chargedAbsIso(const reco::Candidate &cand, float dR, float innerR=0, float threshold=0, SelfVetoPolicy selfVeto=selfVetoAll) const ; + + /// Isolation from charged from PU + float puAbsIso(const reco::Candidate &cand, float dR, float innerR=0, float threshold=0, SelfVetoPolicy selfVeto=selfVetoAll) const ; + + /// Isolation from all neutrals (uncorrected) + float neutralAbsIsoRaw(const reco::Candidate &cand, float dR, float innerR=0, float threshold=0, SelfVetoPolicy selfVeto=selfVetoAll) const ; + + /// Isolation from neutral hadrons (uncorrected) + float neutralHadAbsIsoRaw(const reco::Candidate &cand, float dR, float innerR=0, float threshold=0, SelfVetoPolicy selfVeto=selfVetoAll) const ; + + /// Isolation from photons (uncorrected) + float photonAbsIsoRaw(const reco::Candidate &cand, float dR, float innerR=0, float threshold=0, SelfVetoPolicy selfVeto=selfVetoAll) const ; + + /// Isolation from all neutrals (with weights) + float neutralAbsIsoWeighted(const reco::Candidate &cand, float dR, float innerR=0, float threshold=0, SelfVetoPolicy selfVeto=selfVetoAll) const ; + + /// Isolation from neutral hadrons (with weights) + float neutralHadAbsIsoWeighted(const reco::Candidate &cand, float dR, float innerR=0, float threshold=0, SelfVetoPolicy selfVeto=selfVetoAll) const ; + + /// Isolation from photons (with weights) + float photonAbsIsoWeighted(const reco::Candidate &cand, float dR, float innerR=0, float threshold=0, SelfVetoPolicy selfVeto=selfVetoAll) const ; + protected: + const std::vector * allcands_; + float weightCone_; + // collections of objects, sorted in eta + std::vector charged_, neutral_, pileup_; + mutable std::vector weights_; + std::vector vetos_; + + float isoSumRaw(const std::vector & cands, const reco::Candidate &cand, float dR, float innerR, float threshold, SelfVetoPolicy selfVeto, int pdgId=-1) const ; + float isoSumNeutralsWeighted(const reco::Candidate &cand, float dR, float innerR, float threshold, SelfVetoPolicy selfVeto, int pdgId=-1) const ; +}; + +} + +#endif diff --git a/PhysicsTools/Heppy/src/IsolationComputer.cc b/PhysicsTools/Heppy/src/IsolationComputer.cc new file mode 100644 index 00000000000..87b77b85a07 --- /dev/null +++ b/PhysicsTools/Heppy/src/IsolationComputer.cc @@ -0,0 +1,188 @@ +#include "PhysicsTools/Heppy/interface/IsolationComputer.h" +#include "DataFormats/Math/interface/deltaR.h" + +#include +namespace { + struct ByEta { + bool operator()(const pat::PackedCandidate *c1, const pat::PackedCandidate *c2) const { + return c1->eta() < c2->eta(); + } + bool operator()(float c1eta, const pat::PackedCandidate *c2) const { + return c1eta < c2->eta(); + } + bool operator()(const pat::PackedCandidate *c1, float c2eta) const { + return c1->eta() < c2eta; + } + }; +} +void heppy::IsolationComputer::setPackedCandidates(const std::vector & all) +{ + allcands_ = &all; + charged_.clear(); neutral_.clear(); pileup_.clear(); + + for (const pat::PackedCandidate &p : all) { + if (p.charge() == 0) { + neutral_.push_back(&p); + } else if (abs(p.pdgId()) == 211) { + if (p.fromPV() > 1) { + charged_.push_back(&p); + } else { + pileup_.push_back(&p); + } + } + } + if (weightCone_ > 0) weights_.resize(neutral_.size()); + std::fill(weights_.begin(), weights_.end(), -1.f); + std::sort(charged_.begin(), charged_.end(), ByEta()); + std::sort(neutral_.begin(), neutral_.end(), ByEta()); + std::sort(pileup_.begin(), pileup_.end(), ByEta()); + clearVetos(); +} + +/// veto footprint from this candidate +void heppy::IsolationComputer::addVetos(const reco::Candidate &cand) { + for (unsigned int i = 0, n = cand.numberOfSourceCandidatePtrs(); i < n; ++i) { + const reco::CandidatePtr &cp = cand.sourceCandidatePtr(i); + if (cp.isNonnull() && cp.isAvailable()) vetos_.push_back(&*cp); + } +} + +/// clear all vetos +void heppy::IsolationComputer::clearVetos() { + vetos_.clear(); +} + +/// Isolation from charged from the PV +float heppy::IsolationComputer::chargedAbsIso(const reco::Candidate &cand, float dR, float innerR, float threshold, SelfVetoPolicy selfVeto) const { + return isoSumRaw(charged_, cand, dR, innerR, threshold, selfVeto); +} + +/// Isolation from charged from PU +float heppy::IsolationComputer::puAbsIso(const reco::Candidate &cand, float dR, float innerR, float threshold, SelfVetoPolicy selfVeto) const { + return isoSumRaw(pileup_, cand, dR, innerR, threshold, selfVeto); +} + +float heppy::IsolationComputer::neutralAbsIsoRaw(const reco::Candidate &cand, float dR, float innerR, float threshold, SelfVetoPolicy selfVeto) const { + return isoSumRaw(neutral_, cand, dR, innerR, threshold, selfVeto); +} + +float heppy::IsolationComputer::neutralAbsIsoWeighted(const reco::Candidate &cand, float dR, float innerR, float threshold, SelfVetoPolicy selfVeto) const { + return isoSumNeutralsWeighted(cand, dR, innerR, threshold, selfVeto); +} + +float heppy::IsolationComputer::neutralHadAbsIsoRaw(const reco::Candidate &cand, float dR, float innerR, float threshold, SelfVetoPolicy selfVeto) const { + return isoSumRaw(neutral_, cand, dR, innerR, threshold, selfVeto, 130); +} + +float heppy::IsolationComputer::neutralHadAbsIsoWeighted(const reco::Candidate &cand, float dR, float innerR, float threshold, SelfVetoPolicy selfVeto) const { + return isoSumNeutralsWeighted(cand, dR, innerR, threshold, selfVeto, 130); +} + +float heppy::IsolationComputer::photonAbsIsoRaw(const reco::Candidate &cand, float dR, float innerR, float threshold, SelfVetoPolicy selfVeto) const { + return isoSumRaw(neutral_, cand, dR, innerR, threshold, selfVeto, 22); +} + +float heppy::IsolationComputer::photonAbsIsoWeighted(const reco::Candidate &cand, float dR, float innerR, float threshold, SelfVetoPolicy selfVeto) const { + return isoSumNeutralsWeighted(cand, dR, innerR, threshold, selfVeto, 22); +} + +float heppy::IsolationComputer::isoSumRaw(const std::vector & cands, const reco::Candidate &cand, float dR, float innerR, float threshold, SelfVetoPolicy selfVeto, int pdgId) const +{ + float dR2 = dR*dR, innerR2 = innerR*innerR; + + std::vector vetos(vetos_); + for (unsigned int i = 0, n = cand.numberOfSourceCandidatePtrs(); i < n; ++i) { + if (selfVeto == selfVetoNone) break; + const reco::CandidatePtr &cp = cand.sourceCandidatePtr(i); + if (cp.isNonnull() && cp.isAvailable()) { + vetos.push_back(&*cp); + if (selfVeto == selfVetoFirst) break; + } + } + + typedef std::vector::const_iterator IT; + IT candsbegin = std::lower_bound(cands.begin(), cands.end(), cand.eta() - dR, ByEta()); + IT candsend = std::upper_bound(candsbegin, cands.end(), cand.eta() + dR, ByEta()); + + double isosum = 0; + for (IT icharged = candsbegin; icharged < candsend; ++icharged) { + // pdgId + if (pdgId > 0 && abs((*icharged)->pdgId()) != pdgId) continue; + // threshold + if (threshold > 0 && (*icharged)->pt() < threshold) continue; + // cone + float mydr2 = reco::deltaR2(**icharged, cand); + if (mydr2 >= dR2 || mydr2 < innerR2) continue; + // veto + if (std::find(vetos.begin(), vetos.end(), *icharged) != vetos.end()) { + continue; + } + // add to sum + isosum += (*icharged)->pt(); + } + return isosum; +} + +float heppy::IsolationComputer::isoSumNeutralsWeighted(const reco::Candidate &cand, float dR, float innerR, float threshold, SelfVetoPolicy selfVeto, int pdgId) const +{ + if (weightCone_ <= 0) throw cms::Exception("LogicError", "you must set a valid weight cone to use this method"); + float dR2 = dR*dR, innerR2 = innerR*innerR, weightCone2 = weightCone_*weightCone_; + + std::vector vetos(vetos_); + for (unsigned int i = 0, n = cand.numberOfSourceCandidatePtrs(); i < n; ++i) { + if (selfVeto == selfVetoNone) break; + const reco::CandidatePtr &cp = cand.sourceCandidatePtr(i); + if (cp.isNonnull() && cp.isAvailable()) { + vetos.push_back(&*cp); + if (selfVeto == selfVetoFirst) break; + } + } + + typedef std::vector::const_iterator IT; + IT charged_begin = std::lower_bound(charged_.begin(), charged_.end(), cand.eta() - dR - weightCone_, ByEta()); + IT charged_end = std::upper_bound(charged_begin, charged_.end(), cand.eta() + dR + weightCone_, ByEta()); + IT pileup_begin = std::lower_bound(pileup_.begin(), pileup_.end(), cand.eta() - dR - weightCone_, ByEta()); + IT pileup_end = std::upper_bound(pileup_begin, pileup_.end(), cand.eta() + dR + weightCone_, ByEta()); + IT neutral_begin = std::lower_bound(neutral_.begin(), neutral_.end(), cand.eta() - dR, ByEta()); + IT neutral_end = std::upper_bound(neutral_begin, neutral_.end(), cand.eta() + dR, ByEta()); + + double isosum = 0.0; + for (IT ineutral = neutral_begin; ineutral < neutral_end; ++ineutral) { + // pdgId + if (pdgId > 0 && abs((*ineutral)->pdgId()) != pdgId) continue; + // threshold + if (threshold > 0 && (*ineutral)->pt() < threshold) continue; + // cone + float mydr2 = reco::deltaR2(**ineutral, cand); + if (mydr2 >= dR2 || mydr2 < innerR2) continue; + // veto + if (std::find(vetos.begin(), vetos.end(), *ineutral) != vetos.end()) { + continue; + } + // weight + float &w = weights_[ineutral-neutral_.begin()]; + if (w == -1.f) { + double sumc = 0, sump = 0.0; + for (IT icharged = charged_begin; icharged < charged_end; ++icharged) { + float hisdr2 = std::max(reco::deltaR2(**icharged, **ineutral), 0.01f); + if (hisdr2 > weightCone2) continue; + if (std::find(vetos_.begin(), vetos_.end(), *icharged) != vetos_.end()) { + continue; + } + sumc += std::log( (*icharged)->pt() / std::sqrt(hisdr2) ); + } + for (IT ipileup = pileup_begin; ipileup < pileup_end; ++ipileup) { + float hisdr2 = std::max(reco::deltaR2(**ipileup, **ineutral), 0.01f); + if (hisdr2 > weightCone2) continue; + if (std::find(vetos_.begin(), vetos_.end(), *ipileup) != vetos_.end()) { + continue; + } + sumc += std::log( (*ipileup)->pt() / std::sqrt(hisdr2) ); + } + w = (sump == 0 ? 1 : sumc/(sump+sumc)); + } + // add to sum + isosum += w * (*ineutral)->pt(); + } + return isosum; +} diff --git a/PhysicsTools/Heppy/src/classes.h b/PhysicsTools/Heppy/src/classes.h index 4bad222dba2..42a3049b908 100644 --- a/PhysicsTools/Heppy/src/classes.h +++ b/PhysicsTools/Heppy/src/classes.h @@ -11,6 +11,7 @@ #include "PhysicsTools/Heppy/interface/Hemisphere.h" #include "PhysicsTools/Heppy/interface/AlphaT.h" #include "PhysicsTools/Heppy/interface/ReclusterJets.h" +#include "PhysicsTools/Heppy/interface/IsolationComputer.h" #include "EgammaAnalysis/ElectronTools/interface/SimpleElectron.h" #include "EgammaAnalysis/ElectronTools/interface/ElectronEPcombinator.h" diff --git a/PhysicsTools/Heppy/src/classes_def.xml b/PhysicsTools/Heppy/src/classes_def.xml index 18bbe3b32ad..2ade80f5b9d 100644 --- a/PhysicsTools/Heppy/src/classes_def.xml +++ b/PhysicsTools/Heppy/src/classes_def.xml @@ -12,6 +12,7 @@ + From 6d0eabeb402631af436f28c74185cdeed5f89709 Mon Sep 17 00:00:00 2001 From: Giovanni Date: Mon, 2 Feb 2015 17:14:07 +0100 Subject: [PATCH 09/18] Heppy Lepton analyzer: miniIsolation and improvements: * allow specifying an arbitrary isolation cut function (isoCut), to cover choices of radii, relative vs absolute iso, etc. * allow computation of miniIsolation, as presented in https://indico.cern.ch/event/368826/ * rearrange code to first compute all inclusive leptons, then compute loose ones. this allows e.g. vetoing inclusive leptons in isolation cones of other leptons --- .../analyzers/objects/LeptonAnalyzer.py | 132 ++++++++++++++---- 1 file changed, 108 insertions(+), 24 deletions(-) diff --git a/PhysicsTools/Heppy/python/analyzers/objects/LeptonAnalyzer.py b/PhysicsTools/Heppy/python/analyzers/objects/LeptonAnalyzer.py index 14b2809dd69..40a0da5c024 100644 --- a/PhysicsTools/Heppy/python/analyzers/objects/LeptonAnalyzer.py +++ b/PhysicsTools/Heppy/python/analyzers/objects/LeptonAnalyzer.py @@ -36,8 +36,35 @@ def __init__(self, cfg_ana, cfg_comp, looperName ): self.electronEnergyCalibrator = EmbeddedElectronCalibrator() # if hasattr(cfg_comp,'efficiency'): # self.efficiency= EfficiencyCorrector(cfg_comp.efficiency) + # Isolation cut + if hasattr(cfg_ana, 'loose_electron_isoCut'): + self.eleIsoCut = cfg_ana.loose_electron_isoCut + else: + self.eleIsoCut = lambda ele : ( + ele.relIso03 <= self.cfg_ana.loose_electron_relIso and + ele.absIso03 < getattr(self.cfg_ana,'loose_electron_absIso',9e99)) + if hasattr(cfg_ana, 'loose_muon_isoCut'): + self.muIsoCut = cfg_ana.loose_muon_isoCut + else: + self.muIsoCut = lambda mu : ( + mu.relIso03 <= self.cfg_ana.loose_muon_relIso and + mu.absIso03 < getattr(self.cfg_ana,'loose_muon_absIso',9e99)) + + + self.eleEffectiveArea = getattr(cfg_ana, 'ele_effectiveAreas', "Phys14_25ns_v1") self.muEffectiveArea = getattr(cfg_ana, 'mu_effectiveAreas', "Phys14_25ns_v1") + # MiniIsolation + self.doMiniIsolation = getattr(cfg_ana, 'doMiniIsolation', False) + if self.doMiniIsolation: + self.miniIsolationPUCorr = self.cfg_ana.miniIsolationPUCorr + self.miniIsolationVetoLeptons = self.cfg_ana.miniIsolationVetoLeptons + if self.miniIsolationVetoLeptons not in [ None, 'any', 'inclusive' ]: + raise RuntimeError, "miniIsolationVetoLeptons should be None, or 'any' (all reco leptons), or 'inclusive' (all inclusive leptons)" + if self.miniIsolationPUCorr == "weights": + self.IsolationComputer = heppy.IsolationComputer(0.4) + else: + self.IsolationComputer = heppy.IsolationComputer() #---------------------------------------- # DECLARATION OF HANDLES OF LEPTONS STUFF #---------------------------------------- @@ -55,6 +82,8 @@ def declareHandles(self): #rho for electrons self.handles['rhoEle'] = AutoHandle( self.cfg_ana.rhoElectron, 'double') + if self.doMiniIsolation: + self.handles['packedCandidates'] = AutoHandle( self.cfg_ana.packedCandidates, 'std::vector') def beginLoop(self, setup): super(LeptonAnalyzer,self).beginLoop(setup) self.counters.addCounter('events') @@ -76,52 +105,67 @@ def makeLeptons(self, event): event.selectedElectrons = [] event.otherLeptons = [] + if self.doMiniIsolation: + self.IsolationComputer.setPackedCandidates(self.handles['packedCandidates'].product()) + if self.miniIsolationVetoLeptons == "any": + for lep in self.handles['muons'].product(): + self.IsolationComputer.addVeto(lep) + for lep in self.handles['electrons'].product(): + self.IsolationComputer.addVeto(lep) + #muons allmuons = self.makeAllMuons(event) + #electrons + allelectrons = self.makeAllElectrons(event) + + #make inclusive leptons + inclusiveMuons = [] + inclusiveElectrons = [] for mu in allmuons: - # inclusive, very loose, selection if (mu.track().isNonnull() and mu.muonID(self.cfg_ana.inclusive_muon_id) and mu.pt()>self.cfg_ana.inclusive_muon_pt and abs(mu.eta())self.cfg_ana.inclusive_electron_pt and abs(ele.eta()) self.cfg_ana.loose_muon_pt and abs(mu.eta()) < self.cfg_ana.loose_muon_eta and abs(mu.dxy()) < self.cfg_ana.loose_muon_dxy and abs(mu.dz()) < self.cfg_ana.loose_muon_dz and - mu.relIso03 < self.cfg_ana.loose_muon_relIso and - mu.absIso03 < (self.cfg_ana.loose_muon_absIso if hasattr(self.cfg_ana,'loose_muon_absIso') else 9e99)): + self.muIsoCut(mu)): mu.looseIdSusy = True event.selectedLeptons.append(mu) event.selectedMuons.append(mu) else: mu.looseIdSusy = False event.otherLeptons.append(mu) - - #electrons - allelectrons = self.makeAllElectrons(event) - looseMuons = event.selectedLeptons[:] - for ele in allelectrons: - ## remove muons if muForEleCrossCleaning is not empty - ## apply selection - if ( ele.electronID(self.cfg_ana.inclusive_electron_id) and - ele.pt()>self.cfg_ana.inclusive_electron_pt and abs(ele.eta())self.cfg_ana.loose_electron_pt and abs(ele.eta()) (self.cfg_ana.min_dr_electron_muon**2)) )): + ( True if getattr(self.cfg_ana,'notCleaningElectrons',False) else (bestMatch(ele, looseMuons)[1] > (self.cfg_ana.min_dr_electron_muon**2)) )): event.selectedLeptons.append(ele) event.selectedElectrons.append(ele) ele.looseIdSusy = True - else: + else: event.otherLeptons.append(ele) ele.looseIdSusy = False @@ -204,7 +248,6 @@ def makeAllMuons(self, event): raise RuntimeError, "Unsupported mu_isoCorr name '" + str(self.cfg_ana.mu_isoCorr) + "'! For now only 'rhoArea' and 'deltaBeta' are supported." mu.relIso03 = mu.absIso03/mu.pt() mu.relIso04 = mu.absIso04/mu.pt() - return allmuons def makeAllElectrons(self, event): @@ -292,6 +335,42 @@ def makeAllElectrons(self, event): return allelectrons + def attachMiniIsolation(self, mu): + mu.miniIsoR = 10.0/min(max(mu.pt(), 50),200) + # -- version with increasing cone at low pT, gives slightly better performance for tight cuts and low pt leptons + # mu.miniIsoR = 10.0/min(max(mu.pt(), 50),200) if mu.pt() > 20 else 4.0/min(max(mu.pt(),10),20) + what = "mu" if (abs(mu.pdgId()) == 13) else ("eleB" if mu.isEB() else "eleE") + mu.miniAbsIsoCharged = self.IsolationComputer.chargedAbsIso(mu.physObj, mu.miniIsoR, {"mu":0.0001,"eleB":0,"eleE":0.015}[what], 0.0); + if self.miniIsolationPUCorr == "weights": + if what == "mu": + mu.miniAbsIsoNeutral = self.IsolationComputer.neutralAbsIsoWeighted(mu.physObj, mu.miniIsoR, 0.01, 0.5); + else: + mu.miniAbsIsoNeutral = ( self.IsolationComputer.photonAbsIsoWeighted( mu.physObj, mu.miniIsoR, 0.08 if what == "eleE" else 0.0, 0.0, self.IsolationComputer.selfVetoNone) + + self.IsolationComputer.neutralHadAbsIsoWeighted(mu.physObj, mu.miniIsoR, 0.0, 0.0, self.IsolationComputer.selfVetoNone) ) + else: + if what == "mu": + mu.miniAbsIsoNeutral = self.IsolationComputer.neutralAbsIsoRaw(mu.physObj, mu.miniIsoR, 0.01, 0.5); + else: + mu.miniAbsIsoPho = self.IsolationComputer.photonAbsIsoRaw( mu.physObj, mu.miniIsoR, 0.08 if what == "eleE" else 0.0, 0.0, self.IsolationComputer.selfVetoNone) + mu.miniAbsIsoNHad = self.IsolationComputer.neutralHadAbsIsoRaw(mu.physObj, mu.miniIsoR, 0.0, 0.0, self.IsolationComputer.selfVetoNone) + mu.miniAbsIsoNeutral = mu.miniAbsIsoPho + mu.miniAbsIsoNHad + # -- version relying on PF candidate vetos; apparently less performant, and the isolation computed at RECO level doesn't have them + #mu.miniAbsIsoPhoSV = self.IsolationComputer.photonAbsIsoRaw( mu.physObj, mu.miniIsoR, 0.0, 0.0) + #mu.miniAbsIsoNHadSV = self.IsolationComputer.neutralHadAbsIsoRaw(mu.physObj, mu.miniIsoR, 0.0, 0.0) + #mu.miniAbsIsoNeutral = mu.miniAbsIsoPhoSV + mu.miniAbsIsoNHadSV + if self.miniIsolationPUCorr == "rhoArea": + mu.miniAbsIsoNeutral = max(0.0, mu.miniAbsIsoNeutral - mu.rho * mu.EffectiveArea03 * (mu.miniIsoR/0.3)**2) + elif self.miniIsolationPUCorr == "deltaBeta": + if what == "mu": + mu.miniAbsIsoPU = self.IsolationComputer.puAbsIso(mu.physObj, mu.miniIsoR, 0.01, 0.5); + else: + mu.miniAbsIsoPU = self.IsolationComputer.puAbsIso(mu.physObj, mu.miniIsoR, 0.015 if what == "eleE" else 0.0, 0.0); + mu.miniAbsIsoNeutral = max(0.0, mu.miniAbsIsoNeutral - 0.5*mu.miniAbsIsoPU) + elif self.miniIsolationPUCorr != 'raw': + raise RuntimeError, "Unsupported miniIsolationCorr name '" + str(self.cfg_ana.miniIsolationCorr) + "'! For now only 'rhoArea', 'deltaBeta', 'raw', 'weights' are supported (and 'weights' is not tested)." + mu.miniAbsIso = mu.miniAbsIsoCharged + mu.miniAbsIsoNeutral + mu.miniRelIso = mu.miniAbsIso/mu.pt() + def matchLeptons(self, event): def plausible(rec,gen): if abs(rec.pdgId()) == 11 and abs(gen.pdgId()) != 11: return False @@ -407,6 +486,11 @@ def process(self, event): ele_tightId = "Cuts_2012" , # minimum deltaR between a loose electron and a loose muon (on overlaps, discard the electron) min_dr_electron_muon = 0.02, + # Mini-isolation, with pT dependent cone: will fill in the miniRelIso, miniRelIsoCharged, miniRelIsoNeutral variables of the leptons (see https://indico.cern.ch/event/368826/ ) + doMiniIsolation = False, # off by default since it requires access to all PFCandidates + packedCandidates = 'packedPFCandidates', + miniIsolationPUCorr = 'rhoArea', # Allowed options: 'rhoArea' (EAs for 03 cone scaled by R^2), 'deltaBeta', 'raw' (uncorrected), 'weights' (delta beta weights; not validated) + miniIsolationVetoLeptons = None, # use 'inclusive' to veto inclusive leptons and their footprint in all isolation cones # do MC matching do_mc_match = True, # note: it will in any case try it only on MC, not on data match_inclusiveLeptons = False, # match to all inclusive leptons From cc47e6d5d89217cbe977c53f2cb518dbc57534e8 Mon Sep 17 00:00:00 2001 From: Giovanni Date: Tue, 3 Feb 2015 17:54:22 +0100 Subject: [PATCH 10/18] Heppy JetAnalyzer: improvements in cleaning\nallow choosing whether to keep the lepton or the jet during cleaning, save discarded objects, and make more consistent cleaning of genJets --- .../python/analyzers/objects/JetAnalyzer.py | 39 ++++++++++++++++--- 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/PhysicsTools/Heppy/python/analyzers/objects/JetAnalyzer.py b/PhysicsTools/Heppy/python/analyzers/objects/JetAnalyzer.py index 9c93d3b6d0c..f40122cea0e 100644 --- a/PhysicsTools/Heppy/python/analyzers/objects/JetAnalyzer.py +++ b/PhysicsTools/Heppy/python/analyzers/objects/JetAnalyzer.py @@ -20,6 +20,27 @@ def cleanNearestJetOnly(jets,leptons,deltaR): if ibest != -1: good[ibest] = False return [ j for (i,j) in enumerate(jets) if good[i] == True ] +def cleanJetsAndLeptons(jets,leptons,deltaR,arbitration): + dr2 = deltaR**2 + goodjet = [ True for j in jets ] + goodlep = [ True for l in leptons ] + for il, l in enumerate(leptons): + ibest, d2m = -1, dr2 + for i,j in enumerate(jets): + d2i = deltaR2(l.eta(),l.phi(), j.eta(),j.phi()) + if d2i < dr2: + if arbitration(j,l) == j: + # if the two match, and we prefer the jet, then drop the lepton and be done + goodlep[il] = False + break + if d2i < d2m: + ibest, d2m = i, d2i + # this lepton has been killed by a jet, then we clean the jet that best matches it + if not goodlep[il]: continue + if ibest != -1: goodjet[ibest] = False + return ( [ j for (i ,j) in enumerate(jets) if goodjet[i ] == True ], + [ l for (il,l) in enumerate(leptons) if goodlep[il] == True ] ) + class JetAnalyzer( Analyzer ): """Taken from RootTools.JetAnalyzer, simplified, modified, added corrections """ @@ -38,10 +59,11 @@ def __init__(self, cfg_ana, cfg_comp, looperName): self.jetReCalibrator = JetReCalibrator(mcGT,"AK4PFchs", False,cfg_ana.jecPath) else: self.jetReCalibrator = JetReCalibrator(dataGT,"AK4PFchs", True,cfg_ana.jecPath) - self.doPuId = self.cfg_ana.doPuId if hasattr(self.cfg_ana, 'doPuId') else True - self.jetLepDR = self.cfg_ana.jetLepDR if hasattr(self.cfg_ana, 'jetLepDR') else 0.5 - self.lepPtMin = self.cfg_ana.minLepPt if hasattr(self.cfg_ana, 'minLepPt') else -1 - self.jetGammaDR = self.cfg_ana.jetGammaDR if hasattr(self.cfg_ana, 'jetGammaDR') else 0.4 + self.doPuId = getattr(self.cfg_ana, 'doPuId', True) + self.jetLepDR = getattr(self.cfg_ana, 'jetLepDR', 0.4) + self.jetLepArbitration = getattr(self.cfg_ana, 'jetLepArbitration', lambda jet,lepton: lepton) + self.lepPtMin = getattr(self.cfg_ana, 'minLepPt', -1) + self.jetGammaDR = getattr(self.cfg_ana, 'jetGammaDR', 0.4) if(self.cfg_ana.doQG): self.qglcalc = QGLikelihoodCalculator("/afs/cern.ch/user/t/tomc/public/QG_pdfs_13TeV_2014-10-12/pdfQG_AK4chs_antib_NoQC_13TeV.root") @@ -105,9 +127,13 @@ def process(self, event): leptons = leptons[:] + event.selectedTaus if self.cfg_ana.cleanJetsFromIsoTracks and hasattr(event, 'selectedIsoCleanTrack'): leptons = leptons[:] + event.selectedIsoCleanTrack - event.cleanJetsAll = cleanNearestJetOnly(event.jets, leptons, self.jetLepDR) + event.cleanJetsAll, cleanLeptons = cleanJetsAndLeptons(event.jets, leptons, self.jetLepDR, self.jetLepArbitration) event.cleanJets = [j for j in event.cleanJetsAll if abs(j.eta()) < self.cfg_ana.jetEtaCentral ] event.cleanJetsFwd = [j for j in event.cleanJetsAll if abs(j.eta()) >= self.cfg_ana.jetEtaCentral ] + event.discardedJets = [j for j in event.jets if j not in event.cleanJetsAll] + if hasattr(event, 'selectedLeptons'): + event.discardedLeptons = [ l for l in leptons if l not in cleanLeptons ] + event.selectedLeptons = [ l for l in event.selectedLeptons if l not in event.discardedLeptons ] ## Clean Jets from photons photons = [] @@ -139,7 +165,7 @@ def process(self, event): if hasattr(j, 'deltaMetFromJetSmearing'): event.deltaMetFromJetSmearing[0] += j.deltaMetFromJetSmearing[0] event.deltaMetFromJetSmearing[1] += j.deltaMetFromJetSmearing[1] - event.cleanGenJets = cleanNearestJetOnly(event.genJets, event.selectedLeptons, 0.5) + event.cleanGenJets = cleanNearestJetOnly(event.genJets, leptons, self.jetLepDR) #event.nGenJets25 = 0 #event.nGenJets25Cen = 0 @@ -322,6 +348,7 @@ def smearJets(self, event, jets): jetEta = 4.7, jetEtaCentral = 2.4, jetLepDR = 0.4, + jetLepArbitration = (lambda jet,lepton : lepton), # you can decide which to keep in case of overlaps; e.g. if the jet is b-tagged you might want to keep the jet minLepPt = 10, relaxJetId = False, doPuId = False, # Not commissioned in 7.0.X From a6af4bb278ee68a77e80e3b7e875d3332ff22e6c Mon Sep 17 00:00:00 2001 From: Francesco Pandolfi Date: Fri, 6 Feb 2015 18:59:53 +0100 Subject: [PATCH 11/18] now using compiled IsolationComputer --- .../analyzers/objects/IsoTrackAnalyzer.py | 127 +++++++++++++----- 1 file changed, 95 insertions(+), 32 deletions(-) diff --git a/PhysicsTools/Heppy/python/analyzers/objects/IsoTrackAnalyzer.py b/PhysicsTools/Heppy/python/analyzers/objects/IsoTrackAnalyzer.py index 736c2621b53..32fbf6f9db7 100755 --- a/PhysicsTools/Heppy/python/analyzers/objects/IsoTrackAnalyzer.py +++ b/PhysicsTools/Heppy/python/analyzers/objects/IsoTrackAnalyzer.py @@ -17,6 +17,11 @@ import PhysicsTools.HeppyCore.framework.config as cfg +from ROOT import heppy + + + + def mtw(x1,x2): import math return math.sqrt(2*x1.pt()*x2.pt()*(1-math.cos(x1.phi()-x2.phi()))) @@ -42,6 +47,7 @@ class IsoTrackAnalyzer( Analyzer ): def __init__(self, cfg_ana, cfg_comp, looperName ): super(IsoTrackAnalyzer,self).__init__(cfg_ana,cfg_comp,looperName) + self.IsoTrackIsolationComputer = heppy.IsolationComputer(self.cfg_ana.isoDR) #---------------------------------------- # DECLARATION OF HANDLES OF LEPTONS STUFF @@ -50,6 +56,7 @@ def declareHandles(self): super(IsoTrackAnalyzer, self).declareHandles() self.handles['cmgCand'] = AutoHandle(self.cfg_ana.candidates,self.cfg_ana.candidatesTypes) self.handles['met'] = AutoHandle( 'slimmedMETs', 'std::vector' ) + self.handles['packedCandidates'] = AutoHandle( 'packedPFCandidates', 'std::vector') def beginLoop(self, setup): super(IsoTrackAnalyzer,self).beginLoop(setup) @@ -71,62 +78,40 @@ def makeIsoTrack(self, event): #event.preIsoTrack = [] pfcands = self.handles['cmgCand'].product() + patcands = self.handles['packedCandidates'].product() - charged = [ p for p in pfcands if ( p.charge() != 0 and abs(p.dz())<=self.cfg_ana.dzMax ) ] + charged = [ p for p in patcands if ( p.charge() != 0 and abs(p.dz())<=self.cfg_ana.dzMax ) ] + + self.IsoTrackIsolationComputer.setPackedCandidates(patcands, -1, 0.1, True) alltrack = map( IsoTrack, charged ) for track in alltrack: - foundNonIsoTrack = False - -## ===> require Track Candidate above some pt and charged if ( (abs(track.pdgId())!=11) and (abs(track.pdgId())!=13) and (track.pt() < self.cfg_ana.ptMin) ): continue if ( track.pt() < self.cfg_ana.ptMinEMU ): continue + foundNonIsoTrack = False ## ===> require is not the leading lepton and opposite to the leading lepton if( (self.cfg_ana.doSecondVeto) and len(event.selectedLeptons)>0) : if( deltaR(event.selectedLeptons[0].eta(), event.selectedLeptons[0].phi(), track.eta(), track.phi()) <0.01) : continue if ( (abs(track.pdgId())!=11) and (abs(track.pdgId())!=13) and (track.charge()*event.selectedLeptons[0].charge()) ): continue + ## ===> Redundant:: require the Track Candidate with a minimum dz track.associatedVertex = event.goodVertices[0] ## ===> compute the isolation and find the most isolated track - othertracks = [ p for p in charged if( deltaR(p.eta(), p.phi(), track.eta(), track.phi()) < self.cfg_ana.isoDR and p.pt()>self.cfg_ana.ptPartMin ) ] - #othertracks = alltrack - - isoSum=0 - for part in othertracks: - #### ===> skip pfcands with a pt min (this should be 0) - #if part.pt() skip pfcands outside the cone (this should be 0.3) - #if deltaR(part.eta(), part.phi(), track.eta(), track.phi()) > self.cfg_ana.isoDR : continue - isoSum += part.pt() - ### break the loop to save time - if(isoSum > (self.cfg_ana.maxAbsIso + track.pt())): - foundNonIsoTrack = True - break - - if foundNonIsoTrack: continue - - ## reset - #isoSum=0 - #for part in othertracks : - #### ===> skip pfcands with a pt min (this should be 0) - # if part.pt() skip pfcands outside the cone (this should be 0.3) - # if deltaR(part.eta(), part.phi(), track.eta(), track.phi()) > self.cfg_ana.isoDR : continue - # isoSum += part.pt() + isoSum = self.IsoTrackIsolationComputer.chargedAbsIso(track.physObj, self.cfg_ana.isoDR, 0., self.cfg_ana.ptPartMin) - # ### isoSum = isoSum/track.pt() ## <--- this is for relIso + if(isoSum > (self.cfg_ana.maxAbsIso + track.pt())): continue - ### ===> the sum should not contain the track candidate - track.absIso = isoSum - track.pt() + #if abs(track.pdgId())==211 : + track.absIso = isoSum - track.pt() #### store a preIso track #event.preIsoTrack.append(track) @@ -151,6 +136,84 @@ def makeIsoTrack(self, event): else: event.selectedIsoCleanTrack.append(track) + + +## alltrack = map( IsoTrack, charged ) + +## for track in alltrack: +## +## foundNonIsoTrack = False +## +#### ===> require Track Candidate above some pt and charged +## if ( (abs(track.pdgId())!=11) and (abs(track.pdgId())!=13) and (track.pt() < self.cfg_ana.ptMin) ): continue +## if ( track.pt() < self.cfg_ana.ptMinEMU ): continue +## +## +#### ===> require is not the leading lepton and opposite to the leading lepton +## if( (self.cfg_ana.doSecondVeto) and len(event.selectedLeptons)>0) : +## if( deltaR(event.selectedLeptons[0].eta(), event.selectedLeptons[0].phi(), track.eta(), track.phi()) <0.01) : continue +## if ( (abs(track.pdgId())!=11) and (abs(track.pdgId())!=13) and (track.charge()*event.selectedLeptons[0].charge()) ): continue +## +#### ===> Redundant:: require the Track Candidate with a minimum dz +## track.associatedVertex = event.goodVertices[0] +## +#### ===> compute the isolation and find the most isolated track +## +## othertracks = [ p for p in charged if( deltaR(p.eta(), p.phi(), track.eta(), track.phi()) < self.cfg_ana.isoDR and p.pt()>self.cfg_ana.ptPartMin ) ] +## #othertracks = alltrack +## +## isoSum=0 +## for part in othertracks: +## #### ===> skip pfcands with a pt min (this should be 0) +## #if part.pt() skip pfcands outside the cone (this should be 0.3) +## #if deltaR(part.eta(), part.phi(), track.eta(), track.phi()) > self.cfg_ana.isoDR : continue +## isoSum += part.pt() +## ### break the loop to save time +## if(isoSum > (self.cfg_ana.maxAbsIso + track.pt())): +## foundNonIsoTrack = True +## break +## +## if foundNonIsoTrack: continue +## +## ## reset +## #isoSum=0 +## #for part in othertracks : +## #### ===> skip pfcands with a pt min (this should be 0) +## # if part.pt() skip pfcands outside the cone (this should be 0.3) +## # if deltaR(part.eta(), part.phi(), track.eta(), track.phi()) > self.cfg_ana.isoDR : continue +## # isoSum += part.pt() +## +## # ### isoSum = isoSum/track.pt() ## <--- this is for relIso +## +## ### ===> the sum should not contain the track candidate +## +## track.absIso = isoSum - track.pt() +## +## #### store a preIso track +## #event.preIsoTrack.append(track) +## +### if (isoSum < minIsoSum ) : +## if(track.absIso < min(0.2*track.pt(), self.cfg_ana.maxAbsIso)): +## event.selectedIsoTrack.append(track) +## +## if self.cfg_ana.doPrune: +## myMet = self.handles['met'].product()[0] +## mtwIsoTrack = mtw(track, myMet) +## if mtwIsoTrack < 100: +## if abs(track.pdgId()) == 11 or abs(track.pdgId()) == 13: +## if track.pt()>5 and track.absIso/track.pt()<0.2: +## +## myLeptons = [ l for l in event.selectedLeptons if l.pt() > 10 ] +## nearestSelectedLeptons = makeNearestLeptons(myLeptons,track, event) +## if len(nearestSelectedLeptons) > 0: +## for lep in nearestSelectedLeptons: +## if deltaR(lep.eta(), lep.phi(), track.eta(), track.phi()) > 0.1: +## event.selectedIsoCleanTrack.append(track) +## else: +## event.selectedIsoCleanTrack.append(track) + event.selectedIsoTrack.sort(key = lambda l : l.pt(), reverse = True) event.selectedIsoCleanTrack.sort(key = lambda l : l.pt(), reverse = True) From 219be178ce70d492c370176c0237f0dcae0e8337 Mon Sep 17 00:00:00 2001 From: Francesco Pandolfi Date: Fri, 6 Feb 2015 19:00:03 +0100 Subject: [PATCH 12/18] added configurable fromPV() threshold and dz threshold and option to include leptons to setPackedCandidates --- PhysicsTools/Heppy/interface/IsolationComputer.h | 3 ++- PhysicsTools/Heppy/src/IsolationComputer.cc | 12 +++++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/PhysicsTools/Heppy/interface/IsolationComputer.h b/PhysicsTools/Heppy/interface/IsolationComputer.h index d23b1a01fae..3d96c8cb44e 100644 --- a/PhysicsTools/Heppy/interface/IsolationComputer.h +++ b/PhysicsTools/Heppy/interface/IsolationComputer.h @@ -15,7 +15,8 @@ class IsolationComputer { selfVetoNone=0, selfVetoAll=1, selfVetoFirst=2 }; /// Initialize with the list of packed candidates (note: clears also all vetos) - void setPackedCandidates(const std::vector & all) ; + void setPackedCandidates(const std::vector & all, int fromPV_thresh=1, float dz_thresh=9999., bool also_leptons=false) ; + /// veto footprint from this candidate, for the isolation of all candidates and also for calculation of neutral weights (if used) void addVetos(const reco::Candidate &cand) ; diff --git a/PhysicsTools/Heppy/src/IsolationComputer.cc b/PhysicsTools/Heppy/src/IsolationComputer.cc index 87b77b85a07..f572e8d8e81 100644 --- a/PhysicsTools/Heppy/src/IsolationComputer.cc +++ b/PhysicsTools/Heppy/src/IsolationComputer.cc @@ -15,7 +15,7 @@ namespace { } }; } -void heppy::IsolationComputer::setPackedCandidates(const std::vector & all) +void heppy::IsolationComputer::setPackedCandidates(const std::vector & all, int fromPV_thresh, float dz_thresh, bool also_leptons) { allcands_ = &all; charged_.clear(); neutral_.clear(); pileup_.clear(); @@ -23,12 +23,18 @@ void heppy::IsolationComputer::setPackedCandidates(const std::vector 1) { + } else { + + if ( (abs(p.pdgId()) == 211 ) || ( also_leptons && (abs(p.pdgId()) == 11 ) || (abs(p.pdgId()) == 13 ) ) ) { + + if (p.fromPV() > fromPV_thresh && fabs(p.dz()) < dz_thresh ) { charged_.push_back(&p); } else { pileup_.push_back(&p); } + + } + } } if (weightCone_ > 0) weights_.resize(neutral_.size()); From 0196c690e235daf0ec389ff0974154aa7edad048 Mon Sep 17 00:00:00 2001 From: Francesco Pandolfi Date: Fri, 6 Feb 2015 19:04:23 +0100 Subject: [PATCH 13/18] removed useless cmgCand handle --- PhysicsTools/Heppy/python/analyzers/objects/IsoTrackAnalyzer.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/PhysicsTools/Heppy/python/analyzers/objects/IsoTrackAnalyzer.py b/PhysicsTools/Heppy/python/analyzers/objects/IsoTrackAnalyzer.py index 32fbf6f9db7..5c18269c85e 100755 --- a/PhysicsTools/Heppy/python/analyzers/objects/IsoTrackAnalyzer.py +++ b/PhysicsTools/Heppy/python/analyzers/objects/IsoTrackAnalyzer.py @@ -54,7 +54,6 @@ def __init__(self, cfg_ana, cfg_comp, looperName ): #---------------------------------------- def declareHandles(self): super(IsoTrackAnalyzer, self).declareHandles() - self.handles['cmgCand'] = AutoHandle(self.cfg_ana.candidates,self.cfg_ana.candidatesTypes) self.handles['met'] = AutoHandle( 'slimmedMETs', 'std::vector' ) self.handles['packedCandidates'] = AutoHandle( 'packedPFCandidates', 'std::vector') @@ -77,7 +76,6 @@ def makeIsoTrack(self, event): event.selectedIsoCleanTrack = [] #event.preIsoTrack = [] - pfcands = self.handles['cmgCand'].product() patcands = self.handles['packedCandidates'].product() charged = [ p for p in patcands if ( p.charge() != 0 and abs(p.dz())<=self.cfg_ana.dzMax ) ] From 0fcc5e503703c878633ae14f41efb59d585285b9 Mon Sep 17 00:00:00 2001 From: Francesco Pandolfi Date: Fri, 6 Feb 2015 19:06:18 +0100 Subject: [PATCH 14/18] fixed parentheses --- PhysicsTools/Heppy/src/IsolationComputer.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PhysicsTools/Heppy/src/IsolationComputer.cc b/PhysicsTools/Heppy/src/IsolationComputer.cc index f572e8d8e81..96915bcfa53 100644 --- a/PhysicsTools/Heppy/src/IsolationComputer.cc +++ b/PhysicsTools/Heppy/src/IsolationComputer.cc @@ -25,7 +25,7 @@ void heppy::IsolationComputer::setPackedCandidates(const std::vector fromPV_thresh && fabs(p.dz()) < dz_thresh ) { charged_.push_back(&p); From 929d118c2e578fa9db13c0f705024e086ca07c35 Mon Sep 17 00:00:00 2001 From: Giovanni Date: Wed, 4 Feb 2015 19:15:05 +0100 Subject: [PATCH 15/18] HeppyCore: add a line with the total in the time report --- .../HeppyCore/python/framework/looper.py | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/PhysicsTools/HeppyCore/python/framework/looper.py b/PhysicsTools/HeppyCore/python/framework/looper.py index bfe9da15ada..6ce1ed46765 100644 --- a/PhysicsTools/HeppyCore/python/framework/looper.py +++ b/PhysicsTools/HeppyCore/python/framework/looper.py @@ -89,14 +89,7 @@ def __init__( self, name, if len(self.cfg_comp.files)==0: errmsg = 'please provide at least an input file in the files attribute of this component\n' + str(self.cfg_comp) raise ValueError( errmsg ) - if hasattr(config,"preprocessor") and config.preprocessor is not None : - self.cfg_comp = config.preprocessor.run(self.cfg_comp,self.outDir,firstEvent,nEvents) - if hasattr(self.cfg_comp,"options"): - print self.cfg_comp.files,self.cfg_comp.options - self.events = config.events_class(self.cfg_comp.files, tree_name,options=self.cfg_comp.options) - else : - self.events = config.events_class(self.cfg_comp.files, tree_name) - + self.events = config.events_class(self.cfg_comp.files, tree_name) if hasattr(self.cfg_comp, 'fineSplit'): fineSplitIndex, fineSplitFactor = self.cfg_comp.fineSplit if fineSplitFactor > 1: @@ -192,10 +185,19 @@ def loop(self): allev = max([x['events'] for x in self.timeReport]) warning = self.logger.warning warning("\n ---- TimeReport (all times in ms; first evt is skipped) ---- ") - warning("%9s %9s %9s %9s %s" % ("processed","all evts","time/proc", " time/all", "analyer")) - warning("%9s %9s %9s %9s %s" % ("---------","--------","---------", "---------", "-------------")) + warning("%9s %9s %9s %9s %6s %s" % ("processed","all evts","time/proc", " time/all", " [%] ", "analyer")) + warning("%9s %9s %9s %9s %6s %s" % ("---------","--------","---------", "---------", " -----", "-------------")) + sumtime = sum(rep['time'] for rep in self.timeReport) + passev = self.timeReport[-1]['events'] for ana,rep in zip(self.analyzers,self.timeReport): - warning( "%9d %9d %10.2f %10.2f %s" % ( rep['events'], allev, 1000*rep['time']/(rep['events']-1) if rep['events']>1 else 0, 1000*rep['time']/(allev-1) if allev > 1 else 0, ana.name)) + timePerProcEv = rep['time']/(rep['events']-1) if rep['events'] > 1 else 0 + timePerAllEv = rep['time']/(allev-1) if allev > 1 else 0 + fracAllEv = rep['time']/sumtime + warning( "%9d %9d %10.2f %10.2f %5.1f%% %s" % ( rep['events'], allev, 1000*timePerProcEv, 1000*timePerAllEv, 100.0*fracAllEv, ana.name)) + totPerProcEv = sumtime/(passev-1) if passev > 1 else 0 + totPerAllEv = sumtime/(allev-1) if allev > 1 else 0 + warning("%9s %9s %9s %9s %s" % ("---------","--------","---------", "---------", "-------------")) + warning("%9d %9d %10.2f %10.2f %5.1f%% %s" % ( passev, allev, 1000*totPerProcEv, 1000*totPerAllEv, 100.0, "TOTAL")) warning("") def process(self, iEv ): @@ -232,7 +234,6 @@ def write(self): self.setup.close() - if __name__ == '__main__': import pickle From 16d1cad44d0ca1623a2944fc5932e30c43f624cf Mon Sep 17 00:00:00 2001 From: Giovanni Date: Wed, 4 Feb 2015 23:16:16 +0100 Subject: [PATCH 16/18] Heppy: more decent printout of NTupleVariable and such --- PhysicsTools/Heppy/python/analyzers/core/autovars.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/PhysicsTools/Heppy/python/analyzers/core/autovars.py b/PhysicsTools/Heppy/python/analyzers/core/autovars.py index 5ba729e6aef..e57fc1b3253 100644 --- a/PhysicsTools/Heppy/python/analyzers/core/autovars.py +++ b/PhysicsTools/Heppy/python/analyzers/core/autovars.py @@ -24,6 +24,8 @@ def makeBranch(self,treeNumpy,isMC): def fillBranch(self,treeNumpy,object,isMC): if self.mcOnly and not isMC: return treeNumpy.fill(self.name, self(object)) + def __repr__(self): + return "" % self.name class NTupleObjectType: def __init__(self,name,baseObjectTypes=[],mcOnly=[],variables=[]): @@ -60,6 +62,8 @@ def allBases(self): return ret def removeVariable(self,name): self.variables = [ v for v in self.variables if v.name != name] + def __repr__(self): + return "" % self.name class NTupleObject: def __init__(self, name, objectType, help="", mcOnly=False): @@ -79,6 +83,8 @@ def fillBranches(self,treeNumpy,object,isMC): allvars = self.objectType.allVars(isMC) for v in allvars: treeNumpy.fill("%s_%s" % (self.name, v.name), v(object)) + def __repr__(self): + return "" % self.name class NTupleCollection: @@ -137,5 +143,7 @@ def fillBranchesVector(self,treeNumpy,collection,isMC): for v in allvars: name="%s_%s" % (self.name, v.name) if v.name != "" else self.name treeNumpy.vfill(name, [ v(collection[i]) for i in xrange(num) ]) + def __repr__(self): + return "" % self.name From aafde41b4f1a8e463a60276ad8bf2e9a09bb1a14 Mon Sep 17 00:00:00 2001 From: Giovanni Date: Thu, 5 Feb 2015 18:24:16 +0100 Subject: [PATCH 17/18] Heppy: speed up a bit the GeneratorAnalyer (~10%) --- .../python/analyzers/gen/GeneratorAnalyzer.py | 21 +++++++------------ 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/PhysicsTools/Heppy/python/analyzers/gen/GeneratorAnalyzer.py b/PhysicsTools/Heppy/python/analyzers/gen/GeneratorAnalyzer.py index e38e12ca6d6..dc0cf70dedf 100644 --- a/PhysicsTools/Heppy/python/analyzers/gen/GeneratorAnalyzer.py +++ b/PhysicsTools/Heppy/python/analyzers/gen/GeneratorAnalyzer.py @@ -64,7 +64,9 @@ def makeMCInfo(self, event): verbose = getattr(self.cfg_ana, 'verbose', False) rawGenParticles = self.mchandles['genParticles'].product() good = []; keymap = {}; + allGenParticles = [] for rawIndex,p in enumerate(rawGenParticles): + if self.makeAllGenParticles: allGenParticles.append(p) id = abs(p.pdgId()) status = p.status() # particles must be status > 2, except for prompt leptons, photons, neutralinos @@ -134,7 +136,7 @@ def makeMCInfo(self, event): print "Error keying %d: motherIndex %d, ancestor.pdgId %d, good[gp.motherIndex].pdgId() %d " % (igp, gp.motherIndex, ancestor.pdgId(), good[gp.motherIndex].pdgId()) break ancestor = None if ancestor.numberOfMothers() == 0 else ancestor.motherRef(0) - if abs(gp.pdgId()) not in {1,2,3,4,5,11,12,13,14,15,16,21}: + if abs(gp.pdgId()) not in [1,2,3,4,5,11,12,13,14,15,16,21]: gp.sourceId = gp.pdgId() if gp.motherIndex != -1: ancestor = good[gp.motherIndex] @@ -142,7 +144,7 @@ def makeMCInfo(self, event): gp.sourceId = ancestor.sourceId event.generatorSummary = good # add the ID of the mother to be able to recreate last decay chains - for ip,p in enumerate(event.generatorSummary): + for ip,p in enumerate(good): moms = realGenMothers(p) if len(moms)==0: p.motherId = 0 @@ -164,15 +166,8 @@ def makeMCInfo(self, event): print "\n\n" if self.makeAllGenParticles: - event.genParticles = [] - for rawIndex,p in enumerate(rawGenParticles): - if rawIndex in keymap: - gp = event.generatorSummary[keymap[rawIndex]] - else: - gp = p - gp.rawIndex = rawIndex - gp.genSummaryIndex = -1 - event.genParticles.append(gp) + event.genParticles = allGenParticles + if self.makeSplittedGenLists: event.genHiggsBosons = [] event.genVBosons = [] @@ -225,11 +220,11 @@ def process(self, event): setattr(GeneratorAnalyzer,"defaultConfig", cfg.Analyzer(GeneratorAnalyzer, # BSM particles that can appear with status <= 2 and should be kept - stableBSMParticleIds = { 1000022 }, + stableBSMParticleIds = [ 1000022 ], # Particles of which we want to save the pre-FSR momentum (a la status 3). # Note that for quarks and gluons the post-FSR doesn't make sense, # so those should always be in the list - savePreFSRParticleIds = { 1,2,3,4,5, 11,12,13,14,15,16, 21 }, + savePreFSRParticleIds = [ 1,2,3,4,5, 11,12,13,14,15,16, 21 ], # Make also the list of all genParticles, for other analyzers to handle makeAllGenParticles = True, # Make also the splitted lists From 475bc9e9c94e4f7f1f08e21c794b347bcfdef1c9 Mon Sep 17 00:00:00 2001 From: Giovanni Date: Fri, 13 Feb 2015 16:19:56 +0100 Subject: [PATCH 18/18] HeppyCore: Small speedup of combinatorics in MC matching --- PhysicsTools/HeppyCore/python/utils/deltar.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/PhysicsTools/HeppyCore/python/utils/deltar.py b/PhysicsTools/HeppyCore/python/utils/deltar.py index fe74c547f3b..742505f0e77 100644 --- a/PhysicsTools/HeppyCore/python/utils/deltar.py +++ b/PhysicsTools/HeppyCore/python/utils/deltar.py @@ -49,7 +49,10 @@ def matchObjectCollection3 ( objects, matchCollection, deltaRMax = 0.3, filter = return dict( zip(objects, [None]*len(objects)) ) # build all possible combinations - allPairs = [(deltaR2 (object.eta(), object.phi(), match.eta(), match.phi()), (object, match)) for object in objects for match in matchCollection if filter(object,match) ] + objectCoords = [ (o.eta(),o.phi(),o) for o in objects ] + matchdCoords = [ (o.eta(),o.phi(),o) for o in matchCollection ] + allPairs = [(deltaR2 (oeta, ophi, meta, mphi), (object, match)) for (oeta,ophi,object) in objectCoords for (meta,mphi,match) in matchdCoords if abs(oeta-meta)<=deltaRMax and filter(object,match) ] + #allPairs = [(deltaR2 (object.eta(), object.phi(), match.eta(), match.phi()), (object, match)) for object in objects for match in matchCollection if filter(object,match) ] allPairs.sort () # # to flag already matched objects