class JetAnalyzer(Analyzer): def beginLoop(self, setup): super(JetAnalyzer, self).beginLoop(setup) if self.cfg_ana.do_jec: global_tag = self.cfg_ana.gt_mc if not self.cfg_comp.isMC: global_tag = self.cfg_comp.dataGT do_residual = not self.cfg_comp.isMC from PhysicsTools.Heppy.physicsutils.JetReCalibrator import JetReCalibrator self.jet_calibrator = JetReCalibrator( global_tag, 'AK4PFchs', do_residual, jecPath=os.path.expandvars( "${CMSSW_BASE}/src/CMGTools/RootTools/data/jec"), calculateType1METCorrection=True) self.counters.addCounter('JetAnalyzer') count = self.counters.counter('JetAnalyzer') count.register('all events') count.register('at least 2 good jets') count.register('at least 2 clean jets') def declareHandles(self): super(JetAnalyzer, self).declareHandles() self.handles['jets'] = AutoHandle(self.cfg_ana.jets, 'std::vector<pat::Jet>') def process(self, event): self.readCollections(event.input) jets = self.handles['jets'].product() output_jets = [] if self.cfg_ana.year == '2016': for jet in jets: hjet = Jet(jet) output_jets.append(hjet) else: for jet in jets: hjet = Jet(jet) if not hasattr(self.cfg_ana, 'selection'): continue elif self.cfg_ana.selection(hjet): output_jets.append(hjet) if self.cfg_ana.do_jec: event.metShift = [0., 0.] event.type1METCorr = [0., 0., 0.] self.jet_calibrator.correctAll(output_jets, event.rho, delta=0., addCorr=True, addShifts=True, metShift=event.metShift, type1METCorr=event.type1METCorr) setattr(event, self.cfg_ana.output, output_jets)
class JetAnalyzer(Analyzer): """Taken from RootTools.JetAnalyzer, simplified, modified, added corrections """ def __init__(self, cfg_ana, cfg_comp, looperName): super(JetAnalyzer, self).__init__(cfg_ana, cfg_comp, looperName) mcGT = cfg_ana.mcGT if hasattr(cfg_ana, 'mcGT') else "PHYS14_25_V2" dataGT = cfg_ana.dataGT if hasattr(cfg_ana, 'dataGT') else "GR_70_V2_AN1" self.shiftJEC = self.cfg_ana.shiftJEC if hasattr( self.cfg_ana, 'shiftJEC') else 0 self.recalibrateJets = self.cfg_ana.recalibrateJets self.addJECShifts = self.cfg_ana.addJECShifts if hasattr( self.cfg_ana, 'addJECShifts') else 0 if self.recalibrateJets == "MC": self.recalibrateJets = self.cfg_comp.isMC elif self.recalibrateJets == "Data": self.recalibrateJets = not self.cfg_comp.isMC elif self.recalibrateJets not in [True, False]: raise RuntimeError, "recalibrateJets must be any of { True, False, 'MC', 'Data' }, while it is %r " % self.recalibrateJets calculateSeparateCorrections = getattr(cfg_ana, "calculateSeparateCorrections", False) calculateType1METCorrection = getattr(cfg_ana, "calculateType1METCorrection", False) self.doJEC = self.recalibrateJets or ( self.shiftJEC != 0 ) or self.addJECShifts or calculateSeparateCorrections or calculateType1METCorrection if self.doJEC: doResidual = getattr(cfg_ana, 'applyL2L3Residual', 'Data') if doResidual == "MC": doResidual = self.cfg_comp.isMC elif doResidual == "Data": doResidual = not self.cfg_comp.isMC elif doResidual not in [True, False]: raise RuntimeError, "If specified, applyL2L3Residual must be any of { True, False, 'MC', 'Data'(default)}" GT = getattr(cfg_comp, 'jecGT', mcGT if self.cfg_comp.isMC else dataGT) # Now take care of the optional arguments kwargs = { 'calculateSeparateCorrections': calculateSeparateCorrections, 'calculateType1METCorrection': calculateType1METCorrection, } if kwargs['calculateType1METCorrection']: kwargs['type1METParams'] = cfg_ana.type1METParams # instantiate the jet re-calibrator self.jetReCalibrator = JetReCalibrator(GT, cfg_ana.recalibrationType, doResidual, cfg_ana.jecPath, **kwargs) 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.lepSelCut = getattr(self.cfg_ana, 'lepSelCut', lambda lep: True) self.jetGammaDR = getattr(self.cfg_ana, 'jetGammaDR', 0.4) self.jetGammaLepDR = getattr(self.cfg_ana, 'jetGammaLepDR', 0.4) self.cleanFromLepAndGammaSimultaneously = getattr( self.cfg_ana, 'cleanFromLepAndGammaSimultaneously', False) if self.cleanFromLepAndGammaSimultaneously: if hasattr(self.cfg_ana, 'jetGammaLepDR'): self.jetGammaLepDR = self.jetGammaLepDR elif (self.jetGammaDR == self.jetLepDR): self.jetGammaLepDR = self.jetGammaDR else: raise RuntimeError, "DR for simultaneous cleaning of jets from leptons and photons is not defined, and dR(gamma, jet)!=dR(lep, jet)" if (self.cfg_ana.doQG): qgdefname = "{CMSSW_BASE}/src/PhysicsTools/Heppy/data/pdfQG_AK4chs_13TeV_v2b.root" self.qglcalc = QGLikelihoodCalculator( getattr(self.cfg_ana, "QGpath", qgdefname).format(CMSSW_BASE=os.environ['CMSSW_BASE'])) if not hasattr(self.cfg_ana, "collectionPostFix"): self.cfg_ana.collectionPostFix = "" def declareHandles(self): super(JetAnalyzer, self).declareHandles() self.handles['jets'] = AutoHandle(self.cfg_ana.jetCol, 'std::vector<pat::Jet>') self.handles['genJet'] = AutoHandle(self.cfg_ana.genJetCol, 'vector<reco::GenJet>') self.shiftJER = self.cfg_ana.shiftJER if hasattr( self.cfg_ana, 'shiftJER') else 0 self.addJERShifts = self.cfg_ana.addJERShifts if hasattr( self.cfg_ana, 'addJERShifts') else 0 self.handles['rho'] = AutoHandle(self.cfg_ana.rho, 'double') def beginLoop(self, setup): super(JetAnalyzer, self).beginLoop(setup) def process(self, event): self.readCollections(event.input) rho = float(self.handles['rho'].product()[0]) self.rho = rho ## Read jets, if necessary recalibrate and shift MET if self.cfg_ana.copyJetsByValue: import ROOT #from ROOT.heppy import JetUtils allJets = map( lambda j: Jet(ROOT.heppy.JetUtils.copyJet(j)), self.handles['jets'].product( )) #copy-by-value is safe if JetAnalyzer is ran more than once else: allJets = map(Jet, self.handles['jets'].product()) #set dummy MC flavour for all jets in case we want to ntuplize discarded jets later for jet in allJets: jet.mcFlavour = 0 self.deltaMetFromJEC = [0., 0.] self.type1METCorr = [0., 0., 0.] # print "before. rho",self.rho,self.cfg_ana.collectionPostFix,'allJets len ',len(allJets),'pt', [j.pt() for j in allJets] if self.doJEC: if not self.recalibrateJets: # check point that things won't change jetsBefore = [(j.pt(), j.eta(), j.phi(), j.rawFactor()) for j in allJets] self.jetReCalibrator.correctAll(allJets, rho, delta=self.shiftJEC, addCorr=True, addShifts=self.addJECShifts, metShift=self.deltaMetFromJEC, type1METCorr=self.type1METCorr) if not self.recalibrateJets: jetsAfter = [(j.pt(), j.eta(), j.phi(), j.rawFactor()) for j in allJets] if len(jetsBefore) != len(jetsAfter): print "ERROR: I had to recompute jet corrections, and they rejected some of the jets:\nold = %s\n new = %s\n" % ( jetsBefore, jetsAfter) else: for (told, tnew) in zip(jetsBefore, jetsAfter): if (deltaR2(told[1], told[2], tnew[1], tnew[2])) > 0.0001: print "ERROR: I had to recompute jet corrections, and one jet direction moved: old = %s, new = %s\n" % ( told, tnew) elif abs(told[0] - tnew[0]) / ( told[0] + tnew[0]) > 0.5e-3 or abs( told[3] - tnew[3]) > 0.5e-3: print "ERROR: I had to recompute jet corrections, and one jet pt or corr changed: old = %s, new = %s\n" % ( told, tnew) self.allJetsUsedForMET = allJets # print "after. rho",self.rho,self.cfg_ana.collectionPostFix,'allJets len ',len(allJets),'pt', [j.pt() for j in allJets] if self.cfg_comp.isMC: self.genJets = [x for x in self.handles['genJet'].product()] if self.cfg_ana.do_mc_match: for igj, gj in enumerate(self.genJets): gj.index = igj # self.matchJets(event, allJets) self.matchJets( event, [j for j in allJets if j.pt() > self.cfg_ana.jetPt ]) # To match only jets above chosen threshold if getattr(self.cfg_ana, 'smearJets', False): self.smearJets(event, allJets) ##Sort Jets by pT allJets.sort(key=lambda j: j.pt(), reverse=True) leptons = [] if hasattr(event, 'selectedLeptons'): leptons = [ l for l in event.selectedLeptons if l.pt() > self.lepPtMin and self.lepSelCut(l) ] if self.cfg_ana.cleanJetsFromTaus and hasattr(event, 'selectedTaus'): leptons = leptons[:] + event.selectedTaus if self.cfg_ana.cleanJetsFromIsoTracks and hasattr( event, 'selectedIsoCleanTrack'): leptons = leptons[:] + event.selectedIsoCleanTrack ## Apply jet selection self.jets = [] self.jetsFailId = [] self.jetsAllNoID = [] self.jetsIdOnly = [] for jet in allJets: #Check if lepton and jet have overlapping PF candidates leps_with_overlaps = [] if getattr(self.cfg_ana, 'checkLeptonPFOverlap', True): for i in range(jet.numberOfSourceCandidatePtrs()): p1 = jet.sourceCandidatePtr(i) #Ptr<Candidate> p1 for lep in leptons: for j in range(lep.numberOfSourceCandidatePtrs()): p2 = lep.sourceCandidatePtr(j) has_overlaps = p1.key() == p2.key() and p1.refCore( ).id().productIndex() == p2.refCore().id( ).productIndex() and p1.refCore().id( ).processIndex() == p2.refCore().id().processIndex( ) if has_overlaps: leps_with_overlaps += [lep] if len(leps_with_overlaps) > 0: for lep in leps_with_overlaps: lep.jetOverlap = jet if self.testJetNoID(jet): self.jetsAllNoID.append(jet) if (self.cfg_ana.doQG): jet.qgl_calc = self.qglcalc.computeQGLikelihood jet.qgl_rho = rho if self.testJetID(jet): self.jets.append(jet) self.jetsIdOnly.append(jet) else: self.jetsFailId.append(jet) elif self.testJetID(jet): self.jetsIdOnly.append(jet) jetsEtaCut = [ j for j in self.jets if abs(j.eta()) < self.cfg_ana.jetEta ] self.cleanJetsAll, cleanLeptons = cleanJetsAndLeptons( jetsEtaCut, leptons, self.jetLepDR, self.jetLepArbitration) self.cleanJets = [ j for j in self.cleanJetsAll if abs(j.eta()) < self.cfg_ana.jetEtaCentral ] self.cleanJetsFwd = [ j for j in self.cleanJetsAll if abs(j.eta()) >= self.cfg_ana.jetEtaCentral ] self.discardedJets = [ j for j in self.jets if j not in self.cleanJetsAll ] if hasattr(event, 'selectedLeptons') and self.cfg_ana.cleanSelectedLeptons: 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 ] for lep in leptons: if hasattr(lep, "jetOverlap"): if lep.jetOverlap in self.cleanJetsAll: #print "overlap reco", lep.p4().pt(), lep.p4().eta(), lep.p4().phi(), lep.jetOverlap.p4().pt(), lep.jetOverlap.p4().eta(), lep.jetOverlap.p4().phi() lep.jetOverlapIdx = self.cleanJetsAll.index(lep.jetOverlap) elif lep.jetOverlap in self.discardedJets: #print "overlap discarded", lep.p4().pt(), lep.p4().eta(), lep.p4().phi(), lep.jetOverlap.p4().pt(), lep.jetOverlap.p4().eta(), lep.jetOverlap.p4().phi() lep.jetOverlapIdx = 1000 + self.discardedJets.index( lep.jetOverlap) ## First cleaning, then Jet Id self.noIdCleanJetsAll, cleanLeptons = cleanJetsAndLeptons( self.jetsAllNoID, leptons, self.jetLepDR, self.jetLepArbitration) self.noIdCleanJets = [ j for j in self.noIdCleanJetsAll if abs(j.eta()) < self.cfg_ana.jetEtaCentral ] self.noIdCleanJetsFwd = [ j for j in self.noIdCleanJetsAll if abs(j.eta()) >= self.cfg_ana.jetEtaCentral ] self.noIdDiscardedJets = [ j for j in self.jetsAllNoID if j not in self.noIdCleanJetsAll ] ## Clean Jets from photons (first cleaning, then Jet Id) photons = [] if hasattr(event, 'selectedPhotons'): if self.cfg_ana.cleanJetsFromFirstPhoton: photons = event.selectedPhotons[:1] else: photons = [g for g in event.selectedPhotons] self.gamma_cleanJetaAll = [] self.gamma_noIdCleanJetsAll = [] if self.cleanFromLepAndGammaSimultaneously: self.gamma_cleanJetsAll = cleanNearestJetOnly( jetsEtaCut, photons + leptons, self.jetGammaLepDR) self.gamma_noIdCleanJetsAll = cleanNearestJetOnly( self.jetsAllNoID, photons + leptons, self.jetGammaLepDR) else: self.gamma_cleanJetsAll = cleanNearestJetOnly( self.cleanJetsAll, photons, self.jetGammaDR) self.gamma_noIdCleanJetsAll = cleanNearestJetOnly( self.noIdCleanJetsAll, photons, self.jetGammaDR) self.gamma_cleanJets = [ j for j in self.gamma_cleanJetsAll if abs(j.eta()) < self.cfg_ana.jetEtaCentral ] self.gamma_cleanJetsFwd = [ j for j in self.gamma_cleanJetsAll if abs(j.eta()) >= self.cfg_ana.jetEtaCentral ] self.gamma_noIdCleanJets = [ j for j in self.gamma_noIdCleanJetsAll if abs(j.eta()) < self.cfg_ana.jetEtaCentral ] self.gamma_noIdCleanJetsFwd = [ j for j in self.gamma_noIdCleanJetsAll if abs(j.eta()) >= self.cfg_ana.jetEtaCentral ] ### if self.cfg_ana.alwaysCleanPhotons: self.cleanJets = self.gamma_cleanJets self.cleanJetsAll = self.gamma_cleanJetsAll self.cleanJetsFwd = self.gamma_cleanJetsFwd # self.noIdCleanJets = self.gamma_noIdCleanJets self.noIdCleanJetsAll = self.gamma_noIdCleanJetsAll self.noIdCleanJetsFwd = self.gamma_noIdCleanJetsFwd ## Jet Id, after jet/lepton cleaning self.cleanJetsFailIdAll = [] for jet in self.noIdCleanJetsAll: if not self.testJetID(jet): self.cleanJetsFailIdAll.append(jet) self.cleanJetsFailId = [ j for j in self.cleanJetsFailIdAll if abs(j.eta()) < self.cfg_ana.jetEtaCentral ] ## Jet Id, after jet/photon cleaning self.gamma_cleanJetsFailIdAll = [] for jet in self.gamma_noIdCleanJetsAll: if not self.testJetID(jet): self.gamma_cleanJetsFailIdAll.append(jet) self.gamma_cleanJetsFailId = [ j for j in self.gamma_cleanJetsFailIdAll if abs(j.eta()) < self.cfg_ana.jetEtaCentral ] ## Associate jets to leptons incleptons = event.inclusiveLeptons if hasattr( event, 'inclusiveLeptons') else event.selectedLeptons jlpairs = matchObjectCollection(incleptons, allJets, self.jetLepDR**2) for jet in allJets: jet.leptons = [l for l in jlpairs if jlpairs[l] == jet] for lep in incleptons: jet = jlpairs[lep] if jet is None: setattr(lep, "jet" + self.cfg_ana.collectionPostFix, lep) else: setattr(lep, "jet" + self.cfg_ana.collectionPostFix, jet) ## Associate jets to taus taus = getattr(event, 'selectedTaus', []) jtaupairs = matchObjectCollection(taus, allJets, self.jetLepDR**2) for jet in allJets: jet.taus = [l for l in jtaupairs if jtaupairs[l] == jet] for tau in taus: setattr(tau, "jet" + self.cfg_ana.collectionPostFix, jtaupairs[tau]) #MC stuff if self.cfg_comp.isMC: self.deltaMetFromJetSmearing = [0, 0] for j in self.cleanJetsAll: if hasattr(j, 'deltaMetFromJetSmearing'): self.deltaMetFromJetSmearing[ 0] += j.deltaMetFromJetSmearing[0] self.deltaMetFromJetSmearing[ 1] += j.deltaMetFromJetSmearing[1] self.cleanGenJets = cleanNearestJetOnly(self.genJets, leptons, self.jetLepDR) if self.cfg_ana.cleanGenJetsFromPhoton: self.cleanGenJets = cleanNearestJetOnly( self.cleanGenJets, photons, self.jetLepDR) if getattr(self.cfg_ana, 'attachNeutrinos', True) and hasattr( self.cfg_ana, "genNuSelection"): jetNus = [ x for x in event.genParticles if abs(x.pdgId()) in [12, 14, 16] and self.cfg_ana.genNuSelection(x) ] pairs = matchObjectCollection(jetNus, self.genJets, 0.4**2) for (nu, genJet) in pairs.iteritems(): if genJet is not None: if not hasattr(genJet, "nu"): genJet.nu = nu.p4() else: genJet.nu += nu.p4() if self.cfg_ana.do_mc_match: self.jetFlavour(event) if hasattr(event, "jets" + self.cfg_ana.collectionPostFix): raise RuntimeError( "Event already contains a jet collection with the following postfix: " + self.cfg_ana.collectionPostFix) setattr(event, "rho" + self.cfg_ana.collectionPostFix, self.rho) setattr(event, "deltaMetFromJEC" + self.cfg_ana.collectionPostFix, self.deltaMetFromJEC) setattr(event, "type1METCorr" + self.cfg_ana.collectionPostFix, self.type1METCorr) setattr(event, "allJetsUsedForMET" + self.cfg_ana.collectionPostFix, self.allJetsUsedForMET) setattr(event, "jets" + self.cfg_ana.collectionPostFix, self.jets) setattr(event, "jetsFailId" + self.cfg_ana.collectionPostFix, self.jetsFailId) setattr(event, "jetsAllNoID" + self.cfg_ana.collectionPostFix, self.jetsAllNoID) setattr(event, "jetsIdOnly" + self.cfg_ana.collectionPostFix, self.jetsIdOnly) setattr(event, "cleanJetsAll" + self.cfg_ana.collectionPostFix, self.cleanJetsAll) setattr(event, "cleanJets" + self.cfg_ana.collectionPostFix, self.cleanJets) setattr(event, "cleanJetsFwd" + self.cfg_ana.collectionPostFix, self.cleanJetsFwd) setattr(event, "cleanJetsFailIdAll" + self.cfg_ana.collectionPostFix, self.cleanJetsFailIdAll) setattr(event, "cleanJetsFailId" + self.cfg_ana.collectionPostFix, self.cleanJetsFailId) setattr(event, "discardedJets" + self.cfg_ana.collectionPostFix, self.discardedJets) setattr(event, "gamma_cleanJetsAll" + self.cfg_ana.collectionPostFix, self.gamma_cleanJetsAll) setattr(event, "gamma_cleanJets" + self.cfg_ana.collectionPostFix, self.gamma_cleanJets) setattr(event, "gamma_cleanJetsFwd" + self.cfg_ana.collectionPostFix, self.gamma_cleanJetsFwd) setattr(event, "gamma_cleanJetsFailIdAll" + self.cfg_ana.collectionPostFix, self.gamma_cleanJetsFailIdAll) setattr(event, "gamma_cleanJetsFailId" + self.cfg_ana.collectionPostFix, self.gamma_cleanJetsFailId) if self.cfg_comp.isMC: setattr(event, "deltaMetFromJetSmearing" + self.cfg_ana.collectionPostFix, self.deltaMetFromJetSmearing) setattr(event, "cleanGenJets" + self.cfg_ana.collectionPostFix, self.cleanGenJets) setattr(event, "genJets" + self.cfg_ana.collectionPostFix, self.genJets) if self.cfg_ana.do_mc_match: setattr(event, "bqObjects" + self.cfg_ana.collectionPostFix, self.bqObjects) setattr(event, "cqObjects" + self.cfg_ana.collectionPostFix, self.cqObjects) setattr(event, "partons" + self.cfg_ana.collectionPostFix, self.partons) setattr(event, "heaviestQCDFlavour" + self.cfg_ana.collectionPostFix, self.heaviestQCDFlavour) return True def testJetID(self, jet): jet.puJetIdPassed = jet.puJetId() jet.pfJetIdPassed = jet.jetID('POG_PFID_Loose') if self.cfg_ana.relaxJetId: return True else: return jet.pfJetIdPassed and (jet.puJetIdPassed or not (self.doPuId)) def testJetNoID(self, jet): # 2 is loose pile-up jet id return jet.pt() > self.cfg_ana.jetPt and \ abs( jet.eta() ) < self.cfg_ana.jetEta def jetFlavour(self, event): def isFlavour(x, f): id = abs(x.pdgId()) if id > 999: return (id / 1000) % 10 == f if id > 99: return (id / 100) % 10 == f return id % 100 == f self.bqObjects = [ p for p in event.genParticles if (p.status() == 2 and isFlavour(p, 5)) ] self.cqObjects = [ p for p in event.genParticles if (p.status() == 2 and isFlavour(p, 4)) ] self.partons = [ p for p in event.genParticles if ((p.status() == 23 or p.status() == 3) and abs(p.pdgId()) > 0 and (abs(p.pdgId()) in [1, 2, 3, 4, 5, 21])) ] match = matchObjectCollection2(self.cleanJetsAll, self.partons, deltaRMax=0.3) for jet in self.cleanJetsAll: parton = match[jet] jet.partonId = (parton.pdgId() if parton != None else 0) jet.partonMotherId = (parton.mother(0).pdgId() if parton != None and parton.numberOfMothers() > 0 else 0) for jet in self.jets: (bmatch, dr) = bestMatch(jet, self.bqObjects) if dr < 0.4: jet.mcFlavour = 5 else: (cmatch, dr) = bestMatch(jet, self.cqObjects) if dr < 0.4: jet.mcFlavour = 4 else: jet.mcFlavour = 0 self.heaviestQCDFlavour = 5 if len( self.bqObjects) else (4 if len(self.cqObjects) else 1) def matchJets(self, event, jets): match = matchObjectCollection2(jets, event.genbquarks + event.genwzquarks, deltaRMax=0.3) for jet in jets: gen = match[jet] jet.mcParton = gen jet.mcMatchId = (gen.sourceId if gen != None else 0) jet.mcMatchFlav = (abs(gen.pdgId()) if gen != None else 0) match = matchObjectCollection2(jets, self.genJets, deltaRMax=0.3) for jet in jets: jet.mcJet = match[jet] def smearJets(self, event, jets): # https://twiki.cern.ch/twiki/bin/viewauth/CMS/TWikiTopRefSyst#Jet_energy_resolution for jet in jets: gen = jet.mcJet if gen != None: genpt, jetpt, aeta = gen.pt(), jet.pt(), abs(jet.eta()) # from https://twiki.cern.ch/twiki/bin/view/CMS/JetResolution #8 TeV tables factor = shiftJERfactor(self.shiftJER, aeta) ptscale = max(0.0, (jetpt + (factor - 1) * (jetpt - genpt)) / jetpt) #print "get with pt %.1f (gen pt %.1f, ptscale = %.3f)" % (jetpt,genpt,ptscale) jet.deltaMetFromJetSmearing = [ -(ptscale - 1) * jet.rawFactor() * jet.px(), -(ptscale - 1) * jet.rawFactor() * jet.py() ] if ptscale != 0: jet.setP4(jet.p4() * ptscale) # leave the uncorrected unchanged for sync jet.setRawFactor(jet.rawFactor() / ptscale) #else: print "jet with pt %.1d, eta %.2f is unmatched" % (jet.pt(), jet.eta()) if (self.shiftJER == 0) and (self.addJERShifts): setattr(jet, "corrJER", ptscale) factorJERUp = shiftJERfactor(1, aeta) ptscaleJERUp = max(0.0, (jetpt + (factorJERUp - 1) * (jetpt - genpt)) / jetpt) setattr(jet, "corrJERUp", ptscaleJERUp) factorJERDown = shiftJERfactor(-1, aeta) ptscaleJERDown = max(0.0, (jetpt + (factorJERDown - 1) * (jetpt - genpt)) / jetpt) setattr(jet, "corrJERDown", ptscaleJERDown)
class JetAnalyzer( Analyzer ): """Taken from RootTools.JetAnalyzer, simplified, modified, added corrections """ def __init__(self, cfg_ana, cfg_comp, looperName): super(JetAnalyzer,self).__init__(cfg_ana, cfg_comp, looperName) mcGT = cfg_ana.mcGT if hasattr(cfg_ana,'mcGT') else "PHYS14_25_V2" dataGT = cfg_ana.dataGT if hasattr(cfg_ana,'dataGT') else "GR_70_V2_AN1" self.shiftJEC = self.cfg_ana.shiftJEC if hasattr(self.cfg_ana, 'shiftJEC') else 0 self.recalibrateJets = self.cfg_ana.recalibrateJets self.addJECShifts = self.cfg_ana.addJECShifts if hasattr(self.cfg_ana, 'addJECShifts') else 0 if self.recalibrateJets == "MC" : self.recalibrateJets = self.cfg_comp.isMC elif self.recalibrateJets == "Data": self.recalibrateJets = not self.cfg_comp.isMC elif self.recalibrateJets not in [True,False]: raise RuntimeError("recalibrateJets must be any of { True, False, 'MC', 'Data' }, while it is %r " % self.recalibrateJets) calculateSeparateCorrections = getattr(cfg_ana,"calculateSeparateCorrections", False); calculateType1METCorrection = getattr(cfg_ana,"calculateType1METCorrection", False); self.doJEC = self.recalibrateJets or (self.shiftJEC != 0) or self.addJECShifts or calculateSeparateCorrections or calculateType1METCorrection if self.doJEC: doResidual = getattr(cfg_ana, 'applyL2L3Residual', 'Data') if doResidual == "MC": doResidual = self.cfg_comp.isMC elif doResidual == "Data": doResidual = not self.cfg_comp.isMC elif doResidual not in [True,False]: raise RuntimeError("If specified, applyL2L3Residual must be any of { True, False, 'MC', 'Data'(default)}") GT = getattr(cfg_comp, 'jecGT', mcGT if self.cfg_comp.isMC else dataGT) # Now take care of the optional arguments kwargs = { 'calculateSeparateCorrections':calculateSeparateCorrections, 'calculateType1METCorrection' :calculateType1METCorrection, } if kwargs['calculateType1METCorrection']: kwargs['type1METParams'] = cfg_ana.type1METParams # instantiate the jet re-calibrator self.jetReCalibrator = JetReCalibrator(GT, cfg_ana.recalibrationType, doResidual, cfg_ana.jecPath, **kwargs) 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.lepSelCut = getattr(self.cfg_ana, 'lepSelCut', lambda lep : True) self.jetGammaDR = getattr(self.cfg_ana, 'jetGammaDR', 0.4) self.jetGammaLepDR = getattr(self.cfg_ana, 'jetGammaLepDR', 0.4) self.cleanFromLepAndGammaSimultaneously = getattr(self.cfg_ana, 'cleanFromLepAndGammaSimultaneously', False) if self.cleanFromLepAndGammaSimultaneously: if hasattr(self.cfg_ana, 'jetGammaLepDR'): self.jetGammaLepDR = self.jetGammaLepDR elif (self.jetGammaDR == self.jetLepDR): self.jetGammaLepDR = self.jetGammaDR else: raise RuntimeError("DR for simultaneous cleaning of jets from leptons and photons is not defined, and dR(gamma, jet)!=dR(lep, jet)") if(self.cfg_ana.doQG): qgdefname="{CMSSW_BASE}/src/PhysicsTools/Heppy/data/pdfQG_AK4chs_13TeV_v2b.root" self.qglcalc = QGLikelihoodCalculator(getattr(self.cfg_ana,"QGpath",qgdefname).format(CMSSW_BASE= os.environ['CMSSW_BASE'])) if not hasattr(self.cfg_ana ,"collectionPostFix"):self.cfg_ana.collectionPostFix="" def declareHandles(self): super(JetAnalyzer, self).declareHandles() self.handles['jets'] = AutoHandle( self.cfg_ana.jetCol, 'std::vector<pat::Jet>' ) self.handles['genJet'] = AutoHandle( self.cfg_ana.genJetCol, 'vector<reco::GenJet>' ) self.shiftJER = self.cfg_ana.shiftJER if hasattr(self.cfg_ana, 'shiftJER') else 0 self.addJERShifts = self.cfg_ana.addJERShifts if hasattr(self.cfg_ana, 'addJERShifts') else 0 self.handles['rho'] = AutoHandle( self.cfg_ana.rho, 'double' ) def beginLoop(self, setup): super(JetAnalyzer,self).beginLoop(setup) def process(self, event): self.readCollections( event.input ) rho = float(self.handles['rho'].product()[0]) self.rho = rho ## Read jets, if necessary recalibrate and shift MET if self.cfg_ana.copyJetsByValue: import ROOT #from ROOT.heppy import JetUtils allJets = map(lambda j:Jet(ROOT.heppy.JetUtils.copyJet(j)), self.handles['jets'].product()) #copy-by-value is safe if JetAnalyzer is ran more than once else: allJets = map(Jet, self.handles['jets'].product()) #set dummy MC flavour for all jets in case we want to ntuplize discarded jets later for jet in allJets: jet.mcFlavour = 0 self.deltaMetFromJEC = [0.,0.] self.type1METCorr = [0.,0.,0.] # print "before. rho",self.rho,self.cfg_ana.collectionPostFix,'allJets len ',len(allJets),'pt', [j.pt() for j in allJets] if self.doJEC: if not self.recalibrateJets: # check point that things won't change jetsBefore = [ (j.pt(),j.eta(),j.phi(),j.rawFactor()) for j in allJets ] self.jetReCalibrator.correctAll(allJets, rho, delta=self.shiftJEC, addCorr=True, addShifts=self.addJECShifts, metShift=self.deltaMetFromJEC, type1METCorr=self.type1METCorr ) if not self.recalibrateJets: jetsAfter = [ (j.pt(),j.eta(),j.phi(),j.rawFactor()) for j in allJets ] if len(jetsBefore) != len(jetsAfter): print("ERROR: I had to recompute jet corrections, and they rejected some of the jets:\nold = %s\n new = %s\n" % (jetsBefore,jetsAfter)) else: for (told, tnew) in zip(jetsBefore,jetsAfter): if (deltaR2(told[1],told[2],tnew[1],tnew[2])) > 0.0001: print("ERROR: I had to recompute jet corrections, and one jet direction moved: old = %s, new = %s\n" % (told, tnew)) elif abs(told[0]-tnew[0])/(told[0]+tnew[0]) > 0.5e-3 or abs(told[3]-tnew[3]) > 0.5e-3: print("ERROR: I had to recompute jet corrections, and one jet pt or corr changed: old = %s, new = %s\n" % (told, tnew)) self.allJetsUsedForMET = allJets # print "after. rho",self.rho,self.cfg_ana.collectionPostFix,'allJets len ',len(allJets),'pt', [j.pt() for j in allJets] if self.cfg_comp.isMC: self.genJets = [ x for x in self.handles['genJet'].product() ] if self.cfg_ana.do_mc_match: for igj, gj in enumerate(self.genJets): gj.index = igj # self.matchJets(event, allJets) self.matchJets(event, [ j for j in allJets if j.pt()>self.cfg_ana.jetPt ]) # To match only jets above chosen threshold if getattr(self.cfg_ana, 'smearJets', False): self.smearJets(event, allJets) ##Sort Jets by pT allJets.sort(key = lambda j : j.pt(), reverse = True) leptons = [] if hasattr(event, 'selectedLeptons'): leptons = [ l for l in event.selectedLeptons if l.pt() > self.lepPtMin and self.lepSelCut(l) ] if self.cfg_ana.cleanJetsFromTaus and hasattr(event, 'selectedTaus'): leptons = leptons[:] + event.selectedTaus if self.cfg_ana.cleanJetsFromIsoTracks and hasattr(event, 'selectedIsoCleanTrack'): leptons = leptons[:] + event.selectedIsoCleanTrack ## Apply jet selection self.jets = [] self.jetsFailId = [] self.jetsAllNoID = [] self.jetsIdOnly = [] for jet in allJets: #Check if lepton and jet have overlapping PF candidates leps_with_overlaps = [] if getattr(self.cfg_ana, 'checkLeptonPFOverlap', True): for i in range(jet.numberOfSourceCandidatePtrs()): p1 = jet.sourceCandidatePtr(i) #Ptr<Candidate> p1 for lep in leptons: for j in range(lep.numberOfSourceCandidatePtrs()): p2 = lep.sourceCandidatePtr(j) has_overlaps = p1.key() == p2.key() and p1.refCore().id().productIndex() == p2.refCore().id().productIndex() and p1.refCore().id().processIndex() == p2.refCore().id().processIndex() if has_overlaps: leps_with_overlaps += [lep] if len(leps_with_overlaps)>0: for lep in leps_with_overlaps: lep.jetOverlap = jet if self.testJetNoID( jet ): self.jetsAllNoID.append(jet) if(self.cfg_ana.doQG): jet.qgl_calc = self.qglcalc.computeQGLikelihood jet.qgl_rho = rho if self.testJetID( jet ): self.jets.append(jet) self.jetsIdOnly.append(jet) else: self.jetsFailId.append(jet) elif self.testJetID (jet ): self.jetsIdOnly.append(jet) jetsEtaCut = [j for j in self.jets if abs(j.eta()) < self.cfg_ana.jetEta ] self.cleanJetsAll, cleanLeptons = cleanJetsAndLeptons(jetsEtaCut, leptons, self.jetLepDR, self.jetLepArbitration) self.cleanJets = [j for j in self.cleanJetsAll if abs(j.eta()) < self.cfg_ana.jetEtaCentral ] self.cleanJetsFwd = [j for j in self.cleanJetsAll if abs(j.eta()) >= self.cfg_ana.jetEtaCentral ] self.discardedJets = [j for j in self.jets if j not in self.cleanJetsAll] if hasattr(event, 'selectedLeptons') and self.cfg_ana.cleanSelectedLeptons: 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 ] for lep in leptons: if hasattr(lep, "jetOverlap"): if lep.jetOverlap in self.cleanJetsAll: #print "overlap reco", lep.p4().pt(), lep.p4().eta(), lep.p4().phi(), lep.jetOverlap.p4().pt(), lep.jetOverlap.p4().eta(), lep.jetOverlap.p4().phi() lep.jetOverlapIdx = self.cleanJetsAll.index(lep.jetOverlap) elif lep.jetOverlap in self.discardedJets: #print "overlap discarded", lep.p4().pt(), lep.p4().eta(), lep.p4().phi(), lep.jetOverlap.p4().pt(), lep.jetOverlap.p4().eta(), lep.jetOverlap.p4().phi() lep.jetOverlapIdx = 1000 + self.discardedJets.index(lep.jetOverlap) ## First cleaning, then Jet Id self.noIdCleanJetsAll, cleanLeptons = cleanJetsAndLeptons(self.jetsAllNoID, leptons, self.jetLepDR, self.jetLepArbitration) self.noIdCleanJets = [j for j in self.noIdCleanJetsAll if abs(j.eta()) < self.cfg_ana.jetEtaCentral ] self.noIdCleanJetsFwd = [j for j in self.noIdCleanJetsAll if abs(j.eta()) >= self.cfg_ana.jetEtaCentral ] self.noIdDiscardedJets = [j for j in self.jetsAllNoID if j not in self.noIdCleanJetsAll] ## Clean Jets from photons (first cleaning, then Jet Id) photons = [] if hasattr(event, 'selectedPhotons'): if self.cfg_ana.cleanJetsFromFirstPhoton: photons = event.selectedPhotons[:1] else: photons = [ g for g in event.selectedPhotons ] self.gamma_cleanJetaAll = [] self.gamma_noIdCleanJetsAll = [] if self.cleanFromLepAndGammaSimultaneously: self.gamma_cleanJetsAll = cleanNearestJetOnly(jetsEtaCut, photons+leptons, self.jetGammaLepDR) self.gamma_noIdCleanJetsAll = cleanNearestJetOnly(self.jetsAllNoID, photons+leptons, self.jetGammaLepDR) else: self.gamma_cleanJetsAll = cleanNearestJetOnly(self.cleanJetsAll, photons, self.jetGammaDR) self.gamma_noIdCleanJetsAll = cleanNearestJetOnly(self.noIdCleanJetsAll, photons, self.jetGammaDR) self.gamma_cleanJets = [j for j in self.gamma_cleanJetsAll if abs(j.eta()) < self.cfg_ana.jetEtaCentral ] self.gamma_cleanJetsFwd = [j for j in self.gamma_cleanJetsAll if abs(j.eta()) >= self.cfg_ana.jetEtaCentral ] self.gamma_noIdCleanJets = [j for j in self.gamma_noIdCleanJetsAll if abs(j.eta()) < self.cfg_ana.jetEtaCentral ] self.gamma_noIdCleanJetsFwd = [j for j in self.gamma_noIdCleanJetsAll if abs(j.eta()) >= self.cfg_ana.jetEtaCentral ] ### if self.cfg_ana.alwaysCleanPhotons: self.cleanJets = self.gamma_cleanJets self.cleanJetsAll = self.gamma_cleanJetsAll self.cleanJetsFwd = self.gamma_cleanJetsFwd # self.noIdCleanJets = self.gamma_noIdCleanJets self.noIdCleanJetsAll = self.gamma_noIdCleanJetsAll self.noIdCleanJetsFwd = self.gamma_noIdCleanJetsFwd ## Jet Id, after jet/lepton cleaning self.cleanJetsFailIdAll = [] for jet in self.noIdCleanJetsAll: if not self.testJetID( jet ): self.cleanJetsFailIdAll.append(jet) self.cleanJetsFailId = [j for j in self.cleanJetsFailIdAll if abs(j.eta()) < self.cfg_ana.jetEtaCentral ] ## Jet Id, after jet/photon cleaning self.gamma_cleanJetsFailIdAll = [] for jet in self.gamma_noIdCleanJetsAll: if not self.testJetID( jet ): self.gamma_cleanJetsFailIdAll.append(jet) self.gamma_cleanJetsFailId = [j for j in self.gamma_cleanJetsFailIdAll if abs(j.eta()) < self.cfg_ana.jetEtaCentral ] ## Associate jets to leptons incleptons = event.inclusiveLeptons if hasattr(event, 'inclusiveLeptons') else event.selectedLeptons jlpairs = matchObjectCollection(incleptons, allJets, self.jetLepDR**2) for jet in allJets: jet.leptons = [l for l in jlpairs if jlpairs[l] == jet ] for lep in incleptons: jet = jlpairs[lep] if jet is None: setattr(lep,"jet"+self.cfg_ana.collectionPostFix,lep) else: setattr(lep,"jet"+self.cfg_ana.collectionPostFix,jet) ## Associate jets to taus taus = getattr(event,'selectedTaus',[]) jtaupairs = matchObjectCollection( taus, allJets, self.jetLepDR**2) for jet in allJets: jet.taus = [l for l in jtaupairs if jtaupairs[l] == jet ] for tau in taus: setattr(tau,"jet"+self.cfg_ana.collectionPostFix,jtaupairs[tau]) #MC stuff if self.cfg_comp.isMC: self.deltaMetFromJetSmearing = [0, 0] for j in self.cleanJetsAll: if hasattr(j, 'deltaMetFromJetSmearing'): self.deltaMetFromJetSmearing[0] += j.deltaMetFromJetSmearing[0] self.deltaMetFromJetSmearing[1] += j.deltaMetFromJetSmearing[1] self.cleanGenJets = cleanNearestJetOnly(self.genJets, leptons, self.jetLepDR) if self.cfg_ana.cleanGenJetsFromPhoton: self.cleanGenJets = cleanNearestJetOnly(self.cleanGenJets, photons, self.jetLepDR) if getattr(self.cfg_ana, 'attachNeutrinos', True) and hasattr(self.cfg_ana,"genNuSelection") : jetNus=[x for x in event.genParticles if abs(x.pdgId()) in [12,14,16] and self.cfg_ana.genNuSelection(x) ] pairs= matchObjectCollection (jetNus, self.genJets, 0.4**2) for (nu,genJet) in six.iteritems(pairs) : if genJet is not None : if not hasattr(genJet,"nu") : genJet.nu=nu.p4() else : genJet.nu+=nu.p4() if self.cfg_ana.do_mc_match: self.jetFlavour(event) if hasattr(event,"jets"+self.cfg_ana.collectionPostFix): raise RuntimeError("Event already contains a jet collection with the following postfix: "+self.cfg_ana.collectionPostFix) setattr(event,"rho" +self.cfg_ana.collectionPostFix, self.rho ) setattr(event,"deltaMetFromJEC" +self.cfg_ana.collectionPostFix, self.deltaMetFromJEC ) setattr(event,"type1METCorr" +self.cfg_ana.collectionPostFix, self.type1METCorr ) setattr(event,"allJetsUsedForMET" +self.cfg_ana.collectionPostFix, self.allJetsUsedForMET ) setattr(event,"jets" +self.cfg_ana.collectionPostFix, self.jets ) setattr(event,"jetsFailId" +self.cfg_ana.collectionPostFix, self.jetsFailId ) setattr(event,"jetsAllNoID" +self.cfg_ana.collectionPostFix, self.jetsAllNoID ) setattr(event,"jetsIdOnly" +self.cfg_ana.collectionPostFix, self.jetsIdOnly ) setattr(event,"cleanJetsAll" +self.cfg_ana.collectionPostFix, self.cleanJetsAll ) setattr(event,"cleanJets" +self.cfg_ana.collectionPostFix, self.cleanJets ) setattr(event,"cleanJetsFwd" +self.cfg_ana.collectionPostFix, self.cleanJetsFwd ) setattr(event,"cleanJetsFailIdAll" +self.cfg_ana.collectionPostFix, self.cleanJetsFailIdAll ) setattr(event,"cleanJetsFailId" +self.cfg_ana.collectionPostFix, self.cleanJetsFailId ) setattr(event,"discardedJets" +self.cfg_ana.collectionPostFix, self.discardedJets ) setattr(event,"gamma_cleanJetsAll" +self.cfg_ana.collectionPostFix, self.gamma_cleanJetsAll ) setattr(event,"gamma_cleanJets" +self.cfg_ana.collectionPostFix, self.gamma_cleanJets ) setattr(event,"gamma_cleanJetsFwd" +self.cfg_ana.collectionPostFix, self.gamma_cleanJetsFwd ) setattr(event,"gamma_cleanJetsFailIdAll" +self.cfg_ana.collectionPostFix, self.gamma_cleanJetsFailIdAll ) setattr(event,"gamma_cleanJetsFailId" +self.cfg_ana.collectionPostFix, self.gamma_cleanJetsFailId ) if self.cfg_comp.isMC: setattr(event,"deltaMetFromJetSmearing"+self.cfg_ana.collectionPostFix, self.deltaMetFromJetSmearing) setattr(event,"cleanGenJets" +self.cfg_ana.collectionPostFix, self.cleanGenJets ) setattr(event,"genJets" +self.cfg_ana.collectionPostFix, self.genJets ) if self.cfg_ana.do_mc_match: setattr(event,"bqObjects" +self.cfg_ana.collectionPostFix, self.bqObjects ) setattr(event,"cqObjects" +self.cfg_ana.collectionPostFix, self.cqObjects ) setattr(event,"partons" +self.cfg_ana.collectionPostFix, self.partons ) setattr(event,"heaviestQCDFlavour" +self.cfg_ana.collectionPostFix, self.heaviestQCDFlavour ) return True def testJetID(self, jet): jet.puJetIdPassed = jet.puJetId() jet.pfJetIdPassed = jet.jetID('POG_PFID_Loose') if self.cfg_ana.relaxJetId: return True else: return jet.pfJetIdPassed and (jet.puJetIdPassed or not(self.doPuId)) def testJetNoID( self, jet ): # 2 is loose pile-up jet id return jet.pt() > self.cfg_ana.jetPt and \ abs( jet.eta() ) < self.cfg_ana.jetEta; def jetFlavour(self,event): def isFlavour(x,f): id = abs(x.pdgId()) if id > 999: return (id/1000)%10 == f if id > 99: return (id/100)%10 == f return id % 100 == f self.bqObjects = [ p for p in event.genParticles if (p.status() == 2 and isFlavour(p,5)) ] self.cqObjects = [ p for p in event.genParticles if (p.status() == 2 and isFlavour(p,4)) ] self.partons = [ p for p in event.genParticles if ((p.status() == 23 or p.status() == 3) and abs(p.pdgId())>0 and (abs(p.pdgId()) in [1,2,3,4,5,21]) ) ] match = matchObjectCollection2(self.cleanJetsAll, self.partons, deltaRMax = 0.3) for jet in self.cleanJetsAll: parton = match[jet] jet.partonId = (parton.pdgId() if parton != None else 0) jet.partonMotherId = (parton.mother(0).pdgId() if parton != None and parton.numberOfMothers()>0 else 0) for jet in self.jets: (bmatch, dr) = bestMatch(jet, self.bqObjects) if dr < 0.4: jet.mcFlavour = 5 else: (cmatch, dr) = bestMatch(jet, self.cqObjects) if dr < 0.4: jet.mcFlavour = 4 else: jet.mcFlavour = 0 self.heaviestQCDFlavour = 5 if len(self.bqObjects) else (4 if len(self.cqObjects) else 1); def matchJets(self, event, jets): match = matchObjectCollection2(jets, event.genbquarks + event.genwzquarks, deltaRMax = 0.3) for jet in jets: gen = match[jet] jet.mcParton = gen jet.mcMatchId = (gen.sourceId if gen != None else 0) jet.mcMatchFlav = (abs(gen.pdgId()) if gen != None else 0) match = matchObjectCollection2(jets, self.genJets, deltaRMax = 0.3) for jet in jets: jet.mcJet = match[jet] def smearJets(self, event, jets): # https://twiki.cern.ch/twiki/bin/viewauth/CMS/TWikiTopRefSyst#Jet_energy_resolution for jet in jets: gen = jet.mcJet if gen != None: genpt, jetpt, aeta = gen.pt(), jet.pt(), abs(jet.eta()) # from https://twiki.cern.ch/twiki/bin/view/CMS/JetResolution #8 TeV tables factor = shiftJERfactor(self.shiftJER, aeta) ptscale = max(0.0, (jetpt + (factor-1)*(jetpt-genpt))/jetpt) #print "get with pt %.1f (gen pt %.1f, ptscale = %.3f)" % (jetpt,genpt,ptscale) jet.deltaMetFromJetSmearing = [ -(ptscale-1)*jet.rawFactor()*jet.px(), -(ptscale-1)*jet.rawFactor()*jet.py() ] if ptscale != 0: jet.setP4(jet.p4()*ptscale) # leave the uncorrected unchanged for sync jet.setRawFactor(jet.rawFactor()/ptscale) #else: print "jet with pt %.1d, eta %.2f is unmatched" % (jet.pt(), jet.eta()) if (self.shiftJER==0) and (self.addJERShifts): setattr(jet, "corrJER", ptscale ) factorJERUp= shiftJERfactor(1, aeta) ptscaleJERUp = max(0.0, (jetpt + (factorJERUp-1)*(jetpt-genpt))/jetpt) setattr(jet, "corrJERUp", ptscaleJERUp) factorJERDown= shiftJERfactor(-1, aeta) ptscaleJERDown = max(0.0, (jetpt + (factorJERDown-1)*(jetpt-genpt))/jetpt) setattr(jet, "corrJERDown", ptscaleJERDown)
class EventInterpretationBase(Analyzer): def __init__(self, cfg_ana, cfg_comp, looperName): super(EventInterpretationBase, self).__init__(cfg_ana, cfg_comp, looperName) self.selectFat = self.cfg_ana.selectFat self.selectPairLNu = self.cfg_ana.selectPairLNu self.selectPairLL = self.cfg_ana.selectPairLL self.selectPairJJ = self.cfg_ana.selectPairJJ self.selectPairJJNuNu = self.cfg_ana.selectPairJJNuNu self.isMC = cfg_comp.isMC if hasattr(cfg_ana, 'matchDR'): self.matchDR = cfg_ana.matchDR else: self.matchDR = 0.2 mcGT = cfg_ana.mcGT if hasattr(cfg_ana, 'mcGT') else "PHYS14_25_V2" dataGT = cfg_ana.dataGT if hasattr(cfg_ana, 'dataGT') else "GR_70_V2_AN1" self.shiftJEC = self.cfg_ana.shiftJEC if hasattr( self.cfg_ana, 'shiftJEC') else 0 self.recalibrateJets = self.cfg_ana.recalibrateJets if self.recalibrateJets == "MC": self.recalibrateJets = self.cfg_comp.isMC elif self.recalibrateJets == "Data": self.recalibrateJets = not self.cfg_comp.isMC elif self.recalibrateJets not in [True, False]: raise RuntimeError, "recalibrateJets must be any of { True, False, 'MC', 'Data' }, while it is %r " % self.recalibrateJets self.doJEC = self.recalibrateJets or (self.shiftJEC != 0) if self.doJEC: if self.cfg_comp.isMC: if hasattr(self.cfg_comp, 'globalTag'): self.jetReCalibrator = JetReCalibrator( self.cfg_comp.globalTag, self.cfg_ana.recalibrationType, False, cfg_ana.jecPath) self.jetReCalibratorFAT = JetReCalibrator( self.cfg_comp.globalTag, self.cfg_ana.recalibrationTypeFAT, False, cfg_ana.jecPath) else: self.jetReCalibrator = JetReCalibrator( mcGT, self.cfg_ana.recalibrationType, False, cfg_ana.jecPath) self.jetReCalibratorFAT = JetReCalibrator( mcGT, self.cfg_ana.recalibrationTypeFAT, False, cfg_ana.jecPath, 3, True) else: if hasattr(self.cfg_comp, 'globalTag'): self.jetReCalibrator = JetReCalibrator( self.cfg_comp.globalTag, self.cfg_ana.recalibrationType, True, cfg_ana.jecPath) self.jetReCalibratorFAT = JetReCalibrator( self.cfg_comp.globalTag, self.cfg_ana.recalibrationTypeFAT, True, cfg_ana.jecPath) else: self.jetReCalibrator = JetReCalibrator( dataGT, self.cfg_ana.recalibrationType, True, cfg_ana.jecPath) self.jetReCalibratorFAT = JetReCalibrator( dataGT, self.cfg_ana.recalibrationTypeFAT, True, cfg_ana.jecPath) self.attachBTag = cfg_ana.attachBTag if self.attachBTag: self.btagDiscriminator = cfg_ana.btagDiscriminator if hasattr(cfg_ana, 'doSkim'): self.doSkim = cfg_ana.doSkim else: self.doSkim = False def declareHandles(self): super(EventInterpretationBase, self).declareHandles() self.handles['packed'] = AutoHandle( 'packedPFCandidates', 'std::vector<pat::PackedCandidate>') self.handles['rho'] = AutoHandle(self.cfg_ana.rho, 'double') if self.attachBTag or self.doSkim: self.handles['jets'] = AutoHandle(self.cfg_ana.standardJets, 'std::vector<pat::Jet>') self.handles['fatjets'] = AutoHandle(self.cfg_ana.fatJets, 'std::vector<pat::Jet>') self.handles['subjets'] = AutoHandle( (self.cfg_ana.subJets, 'SubJets'), 'std::vector<pat::Jet>') def removeLeptonFootPrint(self, leptons, cands): toRemove = [] cList = list(cands) for lepton in leptons: for p in range(0, lepton.numberOfSourceCandidatePtrs()): index = lepton.sourceCandidatePtr(p).key() if not cands[index] in toRemove: toRemove.append(cands[index]) for r in toRemove: cList.remove(r) return cList def matchSubJets(self, jets, genquarks): for j in jets: for s in j.subjets_SD + j.subjets: s.mcquark = None s.matched = 0 for g in genquarks: if deltaR(s.eta(), s.phi(), g.eta(), g.phi()) < self.matchDR: s.matched = 1 s.mcquark = g break def skim(self, leptons, met): cleanedJets = [] for jet in self.handles['fatjets'].product(): overlap = False for lepton in leptons: if deltaR(jet.eta(), jet.phi(), lepton.eta(), lepton.phi()) < 0.8: overlap = True break if not overlap: cleanedJets.append(jet) nJets = len(cleanedJets) nLeptons = len(leptons) if (nLeptons > 0 and nJets > 0) or nJets > 1 or (nJets > 0 and met.pt() > 300): return True return False def puppiWeight(self, cands): skimmedCollection = [] for p in cands: p.setP4(p.p4() * p.puppiWeight()) if p.pt() > 0: skimmedCollection.append(p) return skimmedCollection def makeFatJets(self, cands): toolboxFat = PyJetToolbox(cands) toolboxFat.setInterface(True, self.cfg_ana.ktPowerFat, self.cfg_ana.rFat) toolboxFat.setMassDrop(self.cfg_ana.massdrop) toolboxFat.setSubjets(True, 'inc', self.cfg_ana.subjets) toolboxFat.setPruning(self.cfg_ana.prunning) toolboxFat.setNtau(True) if hasattr(self.cfg_ana, 'softdrop_beta'): toolboxFat.setSoftDrop(self.cfg_ana.softdrop, self.cfg_ana.softdrop_beta, self.cfg_ana.softdrop_zeta) else: toolboxFat.setSoftDrop(self.cfg_ana.softdrop) # Lets cluster !! Fat jets first fatJets = toolboxFat.inclusiveJets(200.0, True) filtered = filter(self.selectFat, fatJets) ##Apply JECS in original,SoftDrop and pruned: if self.jetReCalibratorFAT is not None: prunedJets = [] for j in fatJets: prunedJets.append(j) prunedJets.append(j.softDropJet) prunedJets.append(j.prunedJet) #do not apply L1 corrections:rho=0.0 self.jetReCalibratorFAT.correctAll(prunedJets, 0.0, self.shiftJEC, True, False, [0., 0.], [0., 0., 0.]) # self.jetReCalibratorFAT.correctAll(originalJets, self.rho, self.shiftJEC,True,False,[0.,0.],[0.,0.,0.]) for p in prunedJets: p.setRawFactor(1.0 / p.corr) standardFatJets = self.handles['fatjets'].product() if self.attachBTag: for fat in filtered: for standardFat in standardFatJets: fat.btag = standardFat.bDiscriminator( self.btagDiscriminator) for j in fat.subjets_SD + fat.subjets: for standard in self.handles['subjets'].product(): if deltaR(j.eta(), j.phi(), standard.eta(), standard.phi()) < 0.1: j.btag = standard.bDiscriminator( self.btagDiscriminator) break return filtered def makeSatelliteJets(self, cands): toolbox = PyJetToolbox(cands) toolbox.setInterface(True, self.cfg_ana.ktPower, self.cfg_ana.r) toolbox.setMassDrop(False) toolbox.setSubjets(False, 'inc', 2) toolbox.setPruning(False) toolbox.setNtau(False) toolbox.setSoftDrop(False) unfiltered = toolbox.inclusiveJets(30.0, False) if self.attachBTag: for j in unfiltered: for standard in self.handles['jets'].product(): if deltaR(j.eta(), j.phi(), standard.eta(), standard.phi()) < 0.1: j.btag = standard.bDiscriminator( self.btagDiscriminator) break if self.jetReCalibrator is not None: self.jetReCalibrator.correctAll(unfiltered, self.rho, self.shiftJEC, True, False, [0., 0.], [0., 0., 0.]) for p in unfiltered: p.setRawFactor(1.0 / p.corr) filtered = filter(lambda x: x.pt() > 30, unfiltered) return filtered else: return unfiltered def removeJetFootPrint(self, jets, cands): toRemove = [] for j in jets: toRemove.extend(j.constituents) out = list(set(cands) - set(toRemove)) return out def topology(self, obj): #first clean nicely the jets from leptons and subjets objToClean = [] if abs(obj['pair'].leg1.pdgId()) == 23: objToClean.extend([obj['pair'].leg1.leg1, obj['pair'].leg1.leg2]) # print 'Z->ll', obj['pair'].leg1.leg1.pt(),obj['pair'].leg1.leg1.eta(),obj['pair'].leg1.leg1.phi(),obj['pair'].leg1.leg2.pt(),obj['pair'].leg1.leg2.eta(),obj['pair'].leg1.leg2.phi() if abs(obj['pair'].leg1.pdgId()) == 24: objToClean.extend([obj['pair'].leg1.leg1]) # print 'W->lnu', obj['pair'].leg1.leg1.pt(),obj['pair'].leg1.leg1.eta(),obj['pair'].leg1.leg1.phi() if abs(obj['pair'].leg1.pdgId()) == 1: objToClean.extend(obj['pair'].leg1.subjets) if abs(obj['pair'].leg2.pdgId()) == 23: objToClean.extend([obj['pair'].leg2.leg1, obj['pair'].leg2.leg2]) if abs(obj['pair'].leg2.pdgId()) == 24: objToClean.extend([obj['pair'].leg2.leg1]) if abs(obj['pair'].leg2.pdgId()) == 1: objToClean.extend(obj['pair'].leg2.subjets) # print 'jet', obj['pair'].leg2.pt(),obj['pair'].leg2.eta(),obj['pair'].leg2.phi() newJets = [] for j in obj['satelliteJets']: keep = True for c in objToClean: dr = deltaR(j.eta(), j.phi(), c.eta(), c.phi()) # print 'dr=',dr if dr < 0.4: keep = False break if keep: # print 'filtered satellite jet',j.pt(),j.eta(),j.phi() newJets.append(j) obj['satelliteJets'] = newJets if len(obj['satelliteJets']) < 2: obj['vbfDEta'] = -1.0 obj['vbfMJJ'] = -1.0 else: j1 = obj['satelliteJets'][0] j2 = obj['satelliteJets'][1] obj['vbfDEta'] = abs(j1.eta() - j2.eta()) obj['vbfMJJ'] = (j1.p4() + j2.p4()).M() NL = 0 NM = 0 NT = 0 bestBTag = None minDR = 1000.0 for s in obj['satelliteJets']: btag = s.bTag() if btag > 0.423: NL = NL + 1 DR = deltaR(obj['pair'].eta(), obj['pair'].phi(), s.eta(), s.phi()) if DR < minDR: bestBTag = s minDR = DR if btag > 0.814: NM = NM + 1 if btag > 0.941: NT = NT + 1 obj['nLooseBTags'] = NL obj['nMediumBTags'] = NM obj['nTightBTags'] = NT if bestBTag == None: obj['topMass'] = -1 else: obj['topMass'] = (bestBTag.p4() + s.p4()).mass() def beginLoop(self, setup): super(EventInterpretationBase, self).beginLoop(setup) def process(self, event): self.readCollections(event.input) rho = float(self.handles['rho'].product()[0]) self.rho = rho
class JetAnalyzer( Analyzer ): """Taken from RootTools.JetAnalyzer, simplified, modified, added corrections """ def __init__(self, cfg_ana, cfg_comp, looperName): super(JetAnalyzer,self).__init__(cfg_ana, cfg_comp, looperName) mcGT = cfg_ana.mcGT if hasattr(cfg_ana,'mcGT') else "PHYS14_25_V2" dataGT = cfg_ana.dataGT if hasattr(cfg_ana,'dataGT') else "GR_70_V2_AN1" self.shiftJEC = self.cfg_ana.shiftJEC if hasattr(self.cfg_ana, 'shiftJEC') else 0 self.recalibrateJets = self.cfg_ana.recalibrateJets if self.recalibrateJets == "MC" : self.recalibrateJets = self.cfg_comp.isMC elif self.recalibrateJets == "Data": self.recalibrateJets = not self.cfg_comp.isMC elif self.recalibrateJets not in [True,False]: raise RuntimeError, "recalibrateJets must be any of { True, False, 'MC', 'Data' }, while it is %r " % self.recalibrateJets self.doJEC = self.recalibrateJets or (self.shiftJEC != 0) if self.doJEC: if self.cfg_comp.isMC: self.jetReCalibrator = JetReCalibrator(mcGT,"AK4PFchs", False,cfg_ana.jecPath) else: self.jetReCalibrator = JetReCalibrator(dataGT,"AK4PFchs", True,cfg_ana.jecPath) 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/qgTagger/QGLikelihoodDBFiles/QGL_v1a/pdfQG_AK4chs_antib_13TeV_v1.root") def declareHandles(self): super(JetAnalyzer, self).declareHandles() self.handles['jets'] = AutoHandle( self.cfg_ana.jetCol, 'std::vector<pat::Jet>' ) self.handles['genJet'] = AutoHandle( 'slimmedGenJets', 'vector<reco::GenJet>' ) self.shiftJER = self.cfg_ana.shiftJER if hasattr(self.cfg_ana, 'shiftJER') else 0 self.handles['rho'] = AutoHandle( ('fixedGridRhoFastjetAll','',''), 'double' ) def beginLoop(self, setup): super(JetAnalyzer,self).beginLoop(setup) def process(self, event): self.readCollections( event.input ) rho = float(self.handles['rho'].product()[0]) event.rho = rho ## Read jets, if necessary recalibrate and shift MET allJets = map(Jet, self.handles['jets'].product()) event.deltaMetFromJEC = [0.,0.] if self.doJEC: #print "\nCalibrating jets %s for lumi %d, event %d" % (self.cfg_ana.jetCol, event.lumi, event.eventId) self.jetReCalibrator.correctAll(allJets, rho, delta=self.shiftJEC, metShift=event.deltaMetFromJEC) event.allJetsUsedForMET = allJets if self.cfg_comp.isMC: event.genJets = [ x for x in self.handles['genJet'].product() ] self.matchJets(event, allJets) if getattr(self.cfg_ana, 'smearJets', False): self.smearJets(event, allJets) ##Sort Jets by pT allJets.sort(key = lambda j : j.pt(), reverse = True) ## Apply jet selection event.jets = [] event.jetsFailId = [] event.jetsAllNoID = [] event.jetsIdOnly = [] for jet in allJets: if self.testJetNoID( jet ): event.jetsAllNoID.append(jet) if self.testJetID (jet ): if(self.cfg_ana.doQG): self.computeQGvars(jet) jet.qgl = self.qglcalc.computeQGLikelihood(jet, rho) event.jets.append(jet) event.jetsIdOnly.append(jet) else: event.jetsFailId.append(jet) elif self.testJetID (jet ): event.jetsIdOnly.append(jet) ## Clean Jets from leptons leptons = [] if hasattr(event, 'selectedLeptons'): leptons = [ l for l in event.selectedLeptons if l.pt() > self.lepPtMin ] if self.cfg_ana.cleanJetsFromTaus and hasattr(event, 'selectedTaus'): leptons = leptons[:] + event.selectedTaus if self.cfg_ana.cleanJetsFromIsoTracks and hasattr(event, 'selectedIsoCleanTrack'): leptons = leptons[:] + event.selectedIsoCleanTrack 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 = [] if hasattr(event, 'selectedPhotons'): if self.cfg_ana.cleanJetsFromFirstPhoton: photons = event.selectedPhotons[:1] else: photons = [ g for g in event.selectedPhotons ] event.gamma_cleanJetsAll = cleanNearestJetOnly(event.cleanJetsAll, photons, self.jetGammaDR) event.gamma_cleanJets = [j for j in event.gamma_cleanJetsAll if abs(j.eta()) < self.cfg_ana.jetEtaCentral ] event.gamma_cleanJetsFwd = [j for j in event.gamma_cleanJetsAll if abs(j.eta()) >= self.cfg_ana.jetEtaCentral ] ### ## Associate jets to leptons leptons = event.inclusiveLeptons if hasattr(event, 'inclusiveLeptons') else event.selectedLeptons jlpairs = matchObjectCollection( leptons, allJets, self.jetLepDR**2) for jet in allJets: jet.leptons = [l for l in jlpairs if jlpairs[l] == jet ] for lep in leptons: jet = jlpairs[lep] if jet is None: lep.jet = lep else: lep.jet = jet ## Associate jets to taus taus = getattr(event,'selectedTaus',[]) jtaupairs = matchObjectCollection( taus, allJets, self.jetLepDR**2) for jet in allJets: jet.taus = [l for l in jtaupairs if jtaupairs[l] == jet ] for tau in taus: tau.jet = jtaupairs[tau] #MC stuff if self.cfg_comp.isMC: event.deltaMetFromJetSmearing = [0, 0] for j in event.cleanJetsAll: if hasattr(j, 'deltaMetFromJetSmearing'): event.deltaMetFromJetSmearing[0] += j.deltaMetFromJetSmearing[0] event.deltaMetFromJetSmearing[1] += j.deltaMetFromJetSmearing[1] event.cleanGenJets = cleanNearestJetOnly(event.genJets, leptons, self.jetLepDR) #event.nGenJets25 = 0 #event.nGenJets25Cen = 0 #event.nGenJets25Fwd = 0 #for j in event.cleanGenJets: # event.nGenJets25 += 1 # if abs(j.eta()) <= 2.4: event.nGenJets25Cen += 1 # else: event.nGenJets25Fwd += 1 self.jetFlavour(event) return True def testJetID(self, jet): jet.puJetIdPassed = jet.puJetId() jet.pfJetIdPassed = jet.jetID('POG_PFID_Loose') if self.cfg_ana.relaxJetId: return True else: return jet.pfJetIdPassed and (jet.puJetIdPassed or not(self.doPuId)) def testJetNoID( self, jet ): # 2 is loose pile-up jet id return jet.pt() > self.cfg_ana.jetPt and \ abs( jet.eta() ) < self.cfg_ana.jetEta; def computeQGvars(self, jet): jet.mult = 0 sum_weight = 0. sum_pt = 0. sum_deta = 0. sum_dphi = 0. sum_deta2 = 0. sum_detadphi = 0. sum_dphi2 = 0. for ii in range(0, jet.numberOfDaughters()) : part = jet.daughter(ii) if part.charge() == 0 : # neutral particles if part.pt() < 1.: continue else : # charged particles if part.trackHighPurity()==False: continue if part.fromPV()<=1: continue jet.mult += 1 deta = part.eta() - jet.eta() dphi = deltaPhi(part.phi(), jet.phi()) partPt = part.pt() weight = partPt*partPt sum_weight += weight sum_pt += partPt sum_deta += deta*weight sum_dphi += dphi*weight sum_deta2 += deta*deta*weight sum_detadphi += deta*dphi*weight sum_dphi2 += dphi*dphi*weight a = 0. b = 0. c = 0. if sum_weight > 0 : jet.ptd = math.sqrt(sum_weight)/sum_pt ave_deta = sum_deta/sum_weight ave_dphi = sum_dphi/sum_weight ave_deta2 = sum_deta2/sum_weight ave_dphi2 = sum_dphi2/sum_weight a = ave_deta2 - ave_deta*ave_deta b = ave_dphi2 - ave_dphi*ave_dphi c = -(sum_detadphi/sum_weight - ave_deta*ave_dphi) else: jet.ptd = 0. delta = math.sqrt(math.fabs((a-b)*(a-b)+4.*c*c)) if a+b-delta > 0: jet.axis2 = -math.log(math.sqrt(0.5*(a+b-delta))) else: jet.axis2 = -1. def jetFlavour(self,event): def isFlavour(x,f): id = abs(x.pdgId()) if id > 999: return (id/1000)%10 == f if id > 99: return (id/100)%10 == f return id % 100 == f event.bqObjects = [ p for p in event.genParticles if (p.status() == 2 and isFlavour(p,5)) ] event.cqObjects = [ p for p in event.genParticles if (p.status() == 2 and isFlavour(p,4)) ] event.partons = [ p for p in event.genParticles if ((p.status() == 23 or p.status() == 3) and abs(p.pdgId())>0 and (abs(p.pdgId()) in [1,2,3,4,5,21]) ) ] match = matchObjectCollection2(event.cleanJetsAll, event.partons, deltaRMax = 0.3) for jet in event.cleanJetsAll: parton = match[jet] jet.partonId = (parton.pdgId() if parton != None else 0) jet.partonMotherId = (parton.mother(0).pdgId() if parton != None and parton.numberOfMothers()>0 else 0) for jet in event.jets: (bmatch, dr) = bestMatch(jet, event.bqObjects) if dr < 0.4: jet.mcFlavour = 5 else: (cmatch, dr) = bestMatch(jet, event.cqObjects) if dr < 0.4: jet.mcFlavour = 4 else: jet.mcFlavour = 0 event.heaviestQCDFlavour = 5 if len(event.bqObjects) else (4 if len(event.cqObjects) else 1); def matchJets(self, event, jets): match = matchObjectCollection2(jets, event.genbquarks + event.genwzquarks, deltaRMax = 0.3) for jet in jets: gen = match[jet] jet.mcParton = gen jet.mcMatchId = (gen.sourceId if gen != None else 0) jet.mcMatchFlav = (abs(gen.pdgId()) if gen != None else 0) match = matchObjectCollection2(jets, event.genJets, deltaRMax = 0.3) for jet in jets: jet.mcJet = match[jet] def smearJets(self, event, jets): # https://twiki.cern.ch/twiki/bin/viewauth/CMS/TWikiTopRefSyst#Jet_energy_resolution for jet in jets: gen = jet.mcJet if gen != None: genpt, jetpt, aeta = gen.pt(), jet.pt(), abs(jet.eta()) # from https://twiki.cern.ch/twiki/bin/view/CMS/JetResolution factor = 1.052 + self.shiftJER*math.hypot(0.012,0.062); if aeta > 2.3: factor = 1.288 + self.shiftJER*math.hypot(0.127,0.154) elif aeta > 1.7: factor = 1.134 + self.shiftJER*math.hypot(0.035,0.066) elif aeta > 1.1: factor = 1.096 + self.shiftJER*math.hypot(0.017,0.063) elif aeta > 0.5: factor = 1.057 + self.shiftJER*math.hypot(0.012,0.056) ptscale = max(0.0, (jetpt + (factor-1)*(jetpt-genpt))/jetpt) #print "get with pt %.1f (gen pt %.1f, ptscale = %.3f)" % (jetpt,genpt,ptscale) jet.deltaMetFromJetSmearing = [ -(ptscale-1)*jet.rawFactor()*jet.px(), -(ptscale-1)*jet.rawFactor()*jet.py() ] if ptscale != 0: jet.setP4(jet.p4()*ptscale) # leave the uncorrected unchanged for sync jet._rawFactorMultiplier *= (1.0/ptscale) if ptscale != 0 else 1
class JetAnalyzer(Analyzer): """Taken from RootTools.JetAnalyzer, simplified, modified, added corrections """ def __init__(self, cfg_ana, cfg_comp, looperName): super(JetAnalyzer, self).__init__(cfg_ana, cfg_comp, looperName) mcGT = cfg_ana.mcGT if hasattr(cfg_ana, 'mcGT') else "PHYS14_25_V2" dataGT = cfg_ana.dataGT if hasattr(cfg_ana, 'dataGT') else "GR_70_V2_AN1" self.shiftJEC = self.cfg_ana.shiftJEC if hasattr( self.cfg_ana, 'shiftJEC') else 0 self.recalibrateJets = self.cfg_ana.recalibrateJets if self.recalibrateJets == "MC": self.recalibrateJets = self.cfg_comp.isMC elif self.recalibrateJets == "Data": self.recalibrateJets = not self.cfg_comp.isMC elif self.recalibrateJets not in [True, False]: raise RuntimeError, "recalibrateJets must be any of { True, False, 'MC', 'Data' }, while it is %r " % self.recalibrateJets self.doJEC = self.recalibrateJets or (self.shiftJEC != 0) if self.doJEC: if self.cfg_comp.isMC: self.jetReCalibrator = JetReCalibrator( mcGT, self.cfg_ana.recalibrationType, False, cfg_ana.jecPath) else: self.jetReCalibrator = JetReCalibrator( dataGT, self.cfg_ana.recalibrationType, True, cfg_ana.jecPath) 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.lepSelCut = getattr(self.cfg_ana, 'lepSelCut', lambda lep: True) self.jetGammaDR = getattr(self.cfg_ana, 'jetGammaDR', 0.4) if (self.cfg_ana.doQG): self.qglcalc = QGLikelihoodCalculator( "%s/src/PhysicsTools/Heppy/data/pdfQG_AK4chs_antib_13TeV_v1.root" % os.environ['CMSSW_BASE']) if not hasattr(self.cfg_ana, "collectionPostFix"): self.cfg_ana.collectionPostFix = "" def declareHandles(self): super(JetAnalyzer, self).declareHandles() self.handles['jets'] = AutoHandle(self.cfg_ana.jetCol, 'std::vector<pat::Jet>') self.handles['genJet'] = AutoHandle(self.cfg_ana.genJetCol, 'vector<reco::GenJet>') self.shiftJER = self.cfg_ana.shiftJER if hasattr( self.cfg_ana, 'shiftJER') else 0 self.handles['rho'] = AutoHandle(self.cfg_ana.rho, 'double') def beginLoop(self, setup): super(JetAnalyzer, self).beginLoop(setup) def process(self, event): self.readCollections(event.input) rho = float(self.handles['rho'].product()[0]) self.rho = rho ## Read jets, if necessary recalibrate and shift MET if self.cfg_ana.copyJetsByValue: import ROOT allJets = map( lambda j: Jet(ROOT.pat.Jet(j)), self.handles['jets'].product( )) #copy-by-value is safe if JetAnalyzer is ran more than once else: allJets = map(Jet, self.handles['jets'].product()) self.deltaMetFromJEC = [0., 0.] # print "before. rho",self.rho,self.cfg_ana.collectionPostFix,'allJets len ',len(allJets),'pt', [j.pt() for j in allJets] if self.doJEC: # print "\nCalibrating jets %s for lumi %d, event %d" % (self.cfg_ana.jetCol, event.lumi, event.eventId) self.jetReCalibrator.correctAll(allJets, rho, delta=self.shiftJEC, metShift=self.deltaMetFromJEC) self.allJetsUsedForMET = allJets # print "after. rho",self.rho,self.cfg_ana.collectionPostFix,'allJets len ',len(allJets),'pt', [j.pt() for j in allJets] if self.cfg_comp.isMC: self.genJets = [x for x in self.handles['genJet'].product()] self.matchJets(event, allJets) if getattr(self.cfg_ana, 'smearJets', False): self.smearJets(event, allJets) ##Sort Jets by pT allJets.sort(key=lambda j: j.pt(), reverse=True) ## Apply jet selection self.jets = [] self.jetsFailId = [] self.jetsAllNoID = [] self.jetsIdOnly = [] for jet in allJets: if self.testJetNoID(jet): self.jetsAllNoID.append(jet) if self.testJetID(jet): if (self.cfg_ana.doQG): self.computeQGvars(jet) jet.qgl = self.qglcalc.computeQGLikelihood(jet, rho) self.jets.append(jet) self.jetsIdOnly.append(jet) else: self.jetsFailId.append(jet) elif self.testJetID(jet): self.jetsIdOnly.append(jet) ## Clean Jets from leptons leptons = [] if hasattr(event, 'selectedLeptons'): leptons = [ l for l in event.selectedLeptons if l.pt() > self.lepPtMin and self.lepSelCut(l) ] if self.cfg_ana.cleanJetsFromTaus and hasattr(event, 'selectedTaus'): leptons = leptons[:] + event.selectedTaus if self.cfg_ana.cleanJetsFromIsoTracks and hasattr( event, 'selectedIsoCleanTrack'): leptons = leptons[:] + event.selectedIsoCleanTrack self.cleanJetsAll, cleanLeptons = cleanJetsAndLeptons( self.jets, leptons, self.jetLepDR, self.jetLepArbitration) self.cleanJets = [ j for j in self.cleanJetsAll if abs(j.eta()) < self.cfg_ana.jetEtaCentral ] self.cleanJetsFwd = [ j for j in self.cleanJetsAll if abs(j.eta()) >= self.cfg_ana.jetEtaCentral ] self.discardedJets = [ j for j in self.jets if j not in self.cleanJetsAll ] if hasattr(event, 'selectedLeptons') and self.cfg_ana.cleanSelectedLeptons: 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 = [] if hasattr(event, 'selectedPhotons'): if self.cfg_ana.cleanJetsFromFirstPhoton: photons = event.selectedPhotons[:1] else: photons = [g for g in event.selectedPhotons] self.gamma_cleanJetsAll = cleanNearestJetOnly(self.cleanJetsAll, photons, self.jetGammaDR) self.gamma_cleanJets = [ j for j in self.gamma_cleanJetsAll if abs(j.eta()) < self.cfg_ana.jetEtaCentral ] self.gamma_cleanJetsFwd = [ j for j in self.gamma_cleanJetsAll if abs(j.eta()) >= self.cfg_ana.jetEtaCentral ] ### ## Associate jets to leptons leptons = event.inclusiveLeptons if hasattr( event, 'inclusiveLeptons') else event.selectedLeptons jlpairs = matchObjectCollection(leptons, allJets, self.jetLepDR**2) for jet in allJets: jet.leptons = [l for l in jlpairs if jlpairs[l] == jet] for lep in leptons: jet = jlpairs[lep] if jet is None: lep.jet = lep else: lep.jet = jet ## Associate jets to taus taus = getattr(event, 'selectedTaus', []) jtaupairs = matchObjectCollection(taus, allJets, self.jetLepDR**2) for jet in allJets: jet.taus = [l for l in jtaupairs if jtaupairs[l] == jet] for tau in taus: tau.jet = jtaupairs[tau] #MC stuff if self.cfg_comp.isMC: self.deltaMetFromJetSmearing = [0, 0] for j in self.cleanJetsAll: if hasattr(j, 'deltaMetFromJetSmearing'): self.deltaMetFromJetSmearing[ 0] += j.deltaMetFromJetSmearing[0] self.deltaMetFromJetSmearing[ 1] += j.deltaMetFromJetSmearing[1] self.cleanGenJets = cleanNearestJetOnly(self.genJets, leptons, self.jetLepDR) if self.cfg_ana.cleanGenJetsFromPhoton: self.cleanGenJets = cleanNearestJetOnly( self.cleanGenJets, photons, self.jetLepDR) #event.nGenJets25 = 0 #event.nGenJets25Cen = 0 #event.nGenJets25Fwd = 0 #for j in event.cleanGenJets: # event.nGenJets25 += 1 # if abs(j.eta()) <= 2.4: event.nGenJets25Cen += 1 # else: event.nGenJets25Fwd += 1 self.jetFlavour(event) setattr(event, "rho" + self.cfg_ana.collectionPostFix, self.rho) setattr(event, "deltaMetFromJEC" + self.cfg_ana.collectionPostFix, self.deltaMetFromJEC) setattr(event, "deltaMetFromJetSmearing" + self.cfg_ana.collectionPostFix, self.deltaMetFromJetSmearing) setattr(event, "allJetsUsedForMET" + self.cfg_ana.collectionPostFix, self.allJetsUsedForMET) setattr(event, "genJets" + self.cfg_ana.collectionPostFix, self.genJets) setattr(event, "cleanGenJets" + self.cfg_ana.collectionPostFix, self.cleanGenJets) setattr(event, "jets" + self.cfg_ana.collectionPostFix, self.jets) setattr(event, "jetsFailId" + self.cfg_ana.collectionPostFix, self.jetsFailId) setattr(event, "jetsAllNoID" + self.cfg_ana.collectionPostFix, self.jetsAllNoID) setattr(event, "jetsIdOnly" + self.cfg_ana.collectionPostFix, self.jetsIdOnly) setattr(event, "cleanJetsAll" + self.cfg_ana.collectionPostFix, self.cleanJetsAll) setattr(event, "cleanJets" + self.cfg_ana.collectionPostFix, self.cleanJets) setattr(event, "cleanJetsFwd" + self.cfg_ana.collectionPostFix, self.cleanJetsFwd) setattr(event, "discardedJets" + self.cfg_ana.collectionPostFix, self.discardedJets) setattr(event, "gamma_cleanJetsAll" + self.cfg_ana.collectionPostFix, self.gamma_cleanJetsAll) setattr(event, "gamma_cleanJets" + self.cfg_ana.collectionPostFix, self.gamma_cleanJets) setattr(event, "gamma_cleanJetsFwd" + self.cfg_ana.collectionPostFix, self.gamma_cleanJetsFwd) setattr(event, "bqObjects" + self.cfg_ana.collectionPostFix, self.bqObjects) setattr(event, "cqObjects" + self.cfg_ana.collectionPostFix, self.cqObjects) setattr(event, "partons" + self.cfg_ana.collectionPostFix, self.partons) setattr(event, "heaviestQCDFlavour" + self.cfg_ana.collectionPostFix, self.heaviestQCDFlavour) return True def testJetID(self, jet): jet.puJetIdPassed = jet.puJetId() jet.pfJetIdPassed = jet.jetID('POG_PFID_Loose') if self.cfg_ana.relaxJetId: return True else: return jet.pfJetIdPassed and (jet.puJetIdPassed or not (self.doPuId)) def testJetNoID(self, jet): # 2 is loose pile-up jet id return jet.pt() > self.cfg_ana.jetPt and \ abs( jet.eta() ) < self.cfg_ana.jetEta def computeQGvars(self, jet): jet.mult = 0 sum_weight = 0. sum_pt = 0. sum_deta = 0. sum_dphi = 0. sum_deta2 = 0. sum_detadphi = 0. sum_dphi2 = 0. for ii in range(0, jet.numberOfDaughters()): part = jet.daughter(ii) if part.charge() == 0: # neutral particles if part.pt() < 1.: continue else: # charged particles if part.trackHighPurity() == False: continue if part.fromPV() <= 1: continue jet.mult += 1 deta = part.eta() - jet.eta() dphi = deltaPhi(part.phi(), jet.phi()) partPt = part.pt() weight = partPt * partPt sum_weight += weight sum_pt += partPt sum_deta += deta * weight sum_dphi += dphi * weight sum_deta2 += deta * deta * weight sum_detadphi += deta * dphi * weight sum_dphi2 += dphi * dphi * weight a = 0. b = 0. c = 0. if sum_weight > 0: jet.ptd = math.sqrt(sum_weight) / sum_pt ave_deta = sum_deta / sum_weight ave_dphi = sum_dphi / sum_weight ave_deta2 = sum_deta2 / sum_weight ave_dphi2 = sum_dphi2 / sum_weight a = ave_deta2 - ave_deta * ave_deta b = ave_dphi2 - ave_dphi * ave_dphi c = -(sum_detadphi / sum_weight - ave_deta * ave_dphi) else: jet.ptd = 0. delta = math.sqrt(math.fabs((a - b) * (a - b) + 4. * c * c)) if a + b - delta > 0: jet.axis2 = -math.log(math.sqrt(0.5 * (a + b - delta))) else: jet.axis2 = -1. def jetFlavour(self, event): def isFlavour(x, f): id = abs(x.pdgId()) if id > 999: return (id / 1000) % 10 == f if id > 99: return (id / 100) % 10 == f return id % 100 == f self.bqObjects = [ p for p in event.genParticles if (p.status() == 2 and isFlavour(p, 5)) ] self.cqObjects = [ p for p in event.genParticles if (p.status() == 2 and isFlavour(p, 4)) ] self.partons = [ p for p in event.genParticles if ((p.status() == 23 or p.status() == 3) and abs(p.pdgId()) > 0 and (abs(p.pdgId()) in [1, 2, 3, 4, 5, 21])) ] match = matchObjectCollection2(self.cleanJetsAll, self.partons, deltaRMax=0.3) for jet in self.cleanJetsAll: parton = match[jet] jet.partonId = (parton.pdgId() if parton != None else 0) jet.partonMotherId = (parton.mother(0).pdgId() if parton != None and parton.numberOfMothers() > 0 else 0) for jet in self.jets: (bmatch, dr) = bestMatch(jet, self.bqObjects) if dr < 0.4: jet.mcFlavour = 5 else: (cmatch, dr) = bestMatch(jet, self.cqObjects) if dr < 0.4: jet.mcFlavour = 4 else: jet.mcFlavour = 0 self.heaviestQCDFlavour = 5 if len( self.bqObjects) else (4 if len(self.cqObjects) else 1) def matchJets(self, event, jets): match = matchObjectCollection2(jets, event.genbquarks + event.genwzquarks, deltaRMax=0.3) for jet in jets: gen = match[jet] jet.mcParton = gen jet.mcMatchId = (gen.sourceId if gen != None else 0) jet.mcMatchFlav = (abs(gen.pdgId()) if gen != None else 0) match = matchObjectCollection2(jets, self.genJets, deltaRMax=0.3) for jet in jets: jet.mcJet = match[jet] def smearJets(self, event, jets): # https://twiki.cern.ch/twiki/bin/viewauth/CMS/TWikiTopRefSyst#Jet_energy_resolution for jet in jets: gen = jet.mcJet if gen != None: genpt, jetpt, aeta = gen.pt(), jet.pt(), abs(jet.eta()) # from https://twiki.cern.ch/twiki/bin/view/CMS/JetResolution factor = 1.052 + self.shiftJER * math.hypot(0.012, 0.062) if aeta > 2.3: factor = 1.288 + self.shiftJER * math.hypot(0.127, 0.154) elif aeta > 1.7: factor = 1.134 + self.shiftJER * math.hypot(0.035, 0.066) elif aeta > 1.1: factor = 1.096 + self.shiftJER * math.hypot(0.017, 0.063) elif aeta > 0.5: factor = 1.057 + self.shiftJER * math.hypot(0.012, 0.056) ptscale = max(0.0, (jetpt + (factor - 1) * (jetpt - genpt)) / jetpt) #print "get with pt %.1f (gen pt %.1f, ptscale = %.3f)" % (jetpt,genpt,ptscale) jet.deltaMetFromJetSmearing = [ -(ptscale - 1) * jet.rawFactor() * jet.px(), -(ptscale - 1) * jet.rawFactor() * jet.py() ] if ptscale != 0: jet.setP4(jet.p4() * ptscale) # leave the uncorrected unchanged for sync jet._rawFactorMultiplier *= (1.0 / ptscale) if ptscale != 0 else 1
class JetAnalyzer( Analyzer ): """Taken from RootTools.JetAnalyzer, simplified, modified, added corrections """ def __init__(self, cfg_ana, cfg_comp, looperName): super(JetAnalyzer,self).__init__(cfg_ana, cfg_comp, looperName) mcGT = cfg_ana.mcGT if hasattr(cfg_ana,'mcGT') else "PHYS14_25_V2" dataGT = cfg_ana.dataGT if hasattr(cfg_ana,'dataGT') else "GR_70_V2_AN1" self.shiftJEC = self.cfg_ana.shiftJEC if hasattr(self.cfg_ana, 'shiftJEC') else 0 self.recalibrateJets = self.cfg_ana.recalibrateJets self.addJECShifts = self.cfg_ana.addJECShifts if self.recalibrateJets == "MC" : self.recalibrateJets = self.cfg_comp.isMC elif self.recalibrateJets == "Data": self.recalibrateJets = not self.cfg_comp.isMC elif self.recalibrateJets not in [True,False]: raise RuntimeError, "recalibrateJets must be any of { True, False, 'MC', 'Data' }, while it is %r " % self.recalibrateJets self.doJEC = self.recalibrateJets or (self.shiftJEC != 0) or self.addJECShifts if self.doJEC: doResidual = getattr(cfg_ana, 'applyL2L3Residual', 'Data') if doResidual == "MC": doResidual = self.cfg_comp.isMC elif doResidual == "Data": doResidual = not self.cfg_comp.isMC elif doResidual not in [True,False]: raise RuntimeError, "If specified, applyL2L3Residual must be any of { True, False, 'MC', 'Data'(default)}" if self.cfg_comp.isMC: self.jetReCalibrator = JetReCalibrator(mcGT,self.cfg_ana.recalibrationType, doResidual, cfg_ana.jecPath, calculateSeparateCorrections=getattr(cfg_ana,"calculateSeparateCorrections",False)) else: self.jetReCalibrator = JetReCalibrator(dataGT,self.cfg_ana.recalibrationType, doResidual, cfg_ana.jecPath, calculateSeparateCorrections=getattr(cfg_ana,"calculateSeparateCorrections",False)) 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.lepSelCut = getattr(self.cfg_ana, 'lepSelCut', lambda lep : True) self.jetGammaDR = getattr(self.cfg_ana, 'jetGammaDR', 0.4) if(self.cfg_ana.doQG): qgdefname="{CMSSW_BASE}/src/PhysicsTools/Heppy/data/pdfQG_AK4chs_antib_13TeV_v1.root" self.qglcalc = QGLikelihoodCalculator(getattr(self.cfg_ana,"QGpath",qgdefname).format(CMSSW_BASE= os.environ['CMSSW_BASE'])) if not hasattr(self.cfg_ana ,"collectionPostFix"):self.cfg_ana.collectionPostFix="" def declareHandles(self): super(JetAnalyzer, self).declareHandles() self.handles['jets'] = AutoHandle( self.cfg_ana.jetCol, 'std::vector<pat::Jet>' ) self.handles['genJet'] = AutoHandle( self.cfg_ana.genJetCol, 'vector<reco::GenJet>' ) self.shiftJER = self.cfg_ana.shiftJER if hasattr(self.cfg_ana, 'shiftJER') else 0 self.handles['rho'] = AutoHandle( self.cfg_ana.rho, 'double' ) def beginLoop(self, setup): super(JetAnalyzer,self).beginLoop(setup) def process(self, event): self.readCollections( event.input ) rho = float(self.handles['rho'].product()[0]) self.rho = rho ## Read jets, if necessary recalibrate and shift MET if self.cfg_ana.copyJetsByValue: import ROOT allJets = map(lambda j:Jet(ROOT.pat.Jet(ROOT.edm.Ptr(ROOT.pat.Jet)(ROOT.edm.ProductID(),j,0))), self.handles['jets'].product()) #copy-by-value is safe if JetAnalyzer is ran more than once else: allJets = map(Jet, self.handles['jets'].product()) self.deltaMetFromJEC = [0.,0.] # print "before. rho",self.rho,self.cfg_ana.collectionPostFix,'allJets len ',len(allJets),'pt', [j.pt() for j in allJets] if self.doJEC: # print "\nCalibrating jets %s for lumi %d, event %d" % (self.cfg_ana.jetCol, event.lumi, event.eventId) self.jetReCalibrator.correctAll(allJets, rho, delta=self.shiftJEC, metShift=self.deltaMetFromJEC) if self.addJECShifts: for delta, shift in [(1.0, "JECUp"), (0.0, ""), (-1.0, "JECDown")]: for j1 in allJets: corr = self.jetReCalibrator.getCorrection(j1, rho, delta, self.deltaMetFromJEC) setattr(j1, "corr"+shift, corr) self.allJetsUsedForMET = allJets # print "after. rho",self.rho,self.cfg_ana.collectionPostFix,'allJets len ',len(allJets),'pt', [j.pt() for j in allJets] if self.cfg_comp.isMC: self.genJets = [ x for x in self.handles['genJet'].product() ] if self.cfg_ana.do_mc_match: self.matchJets(event, allJets) if getattr(self.cfg_ana, 'smearJets', False): self.smearJets(event, allJets) ##Sort Jets by pT allJets.sort(key = lambda j : j.pt(), reverse = True) ## Apply jet selection self.jets = [] self.jetsFailId = [] self.jetsAllNoID = [] self.jetsIdOnly = [] for jet in allJets: if self.testJetNoID( jet ): self.jetsAllNoID.append(jet) # temporary fix since the jetID it's not good for eta>3 if abs(jet.eta()) <3: if self.testJetID (jet ): if(self.cfg_ana.doQG): jet.qgl_calc = self.qglcalc.computeQGLikelihood jet.qgl_rho = rho self.jets.append(jet) self.jetsIdOnly.append(jet) else: self.jetsFailId.append(jet) else: self.jets.append(jet) elif self.testJetID (jet ): self.jetsIdOnly.append(jet) ## Clean Jets from leptons leptons = [] if hasattr(event, 'selectedLeptons'): leptons = [ l for l in event.selectedLeptons if l.pt() > self.lepPtMin and self.lepSelCut(l) ] if self.cfg_ana.cleanJetsFromTaus and hasattr(event, 'selectedTaus'): leptons = leptons[:] + event.selectedTaus if self.cfg_ana.cleanJetsFromIsoTracks and hasattr(event, 'selectedIsoCleanTrack'): leptons = leptons[:] + event.selectedIsoCleanTrack jetsEtaCut = [j for j in self.jets if abs(j.eta()) < self.cfg_ana.jetEta ] self.cleanJetsAll, cleanLeptons = cleanJetsAndLeptons(jetsEtaCut, leptons, self.jetLepDR, self.jetLepArbitration) #self.cleanJetsAll, cleanLeptons = cleanJetsAndLeptons(self.jets, leptons, self.jetLepDR, self.jetLepArbitration) ##from central self.cleanJets = [j for j in self.cleanJetsAll if abs(j.eta()) < self.cfg_ana.jetEtaCentral ] self.cleanJetsFwd = [j for j in self.cleanJetsAll if abs(j.eta()) >= self.cfg_ana.jetEtaCentral ] self.discardedJets = [j for j in self.jets if j not in self.cleanJetsAll] if hasattr(event, 'selectedLeptons') and self.cfg_ana.cleanSelectedLeptons: 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 = [] if hasattr(event, 'selectedPhotons'): if self.cfg_ana.cleanJetsFromFirstPhoton: photons = event.selectedPhotons[:1] else: photons = [ g for g in event.selectedPhotons ] self.gamma_cleanJetsAll = cleanNearestJetOnly(self.cleanJetsAll, photons, self.jetGammaDR) self.gamma_cleanJets = [j for j in self.gamma_cleanJetsAll if abs(j.eta()) < self.cfg_ana.jetEtaCentral ] self.gamma_cleanJetsFwd = [j for j in self.gamma_cleanJetsAll if abs(j.eta()) >= self.cfg_ana.jetEtaCentral ] ### if self.cfg_ana.alwaysCleanPhotons: self.cleanJets = self.gamma_cleanJets self.cleanJetsAll = self.gamma_cleanJetsAll self.cleanJetsFwd = self.gamma_cleanJetsFwd ## Associate jets to leptons leptons = event.inclusiveLeptons if hasattr(event, 'inclusiveLeptons') else event.selectedLeptons jlpairs = matchObjectCollection( leptons, allJets, self.jetLepDR**2) for jet in allJets: jet.leptons = [l for l in jlpairs if jlpairs[l] == jet ] for lep in leptons: jet = jlpairs[lep] if jet is None: setattr(lep,"jet"+self.cfg_ana.collectionPostFix,lep) else: setattr(lep,"jet"+self.cfg_ana.collectionPostFix,jet) ## Associate jets to taus taus = getattr(event,'selectedTaus',[]) jtaupairs = matchObjectCollection( taus, allJets, self.jetLepDR**2) for jet in allJets: jet.taus = [l for l in jtaupairs if jtaupairs[l] == jet ] for tau in taus: setattr(tau,"jet"+self.cfg_ana.collectionPostFix,jtaupairs[tau]) #MC stuff if self.cfg_comp.isMC: self.deltaMetFromJetSmearing = [0, 0] for j in self.cleanJetsAll: if hasattr(j, 'deltaMetFromJetSmearing'): self.deltaMetFromJetSmearing[0] += j.deltaMetFromJetSmearing[0] self.deltaMetFromJetSmearing[1] += j.deltaMetFromJetSmearing[1] self.cleanGenJets = cleanNearestJetOnly(self.genJets, leptons, self.jetLepDR) if self.cfg_ana.cleanGenJetsFromPhoton: self.cleanGenJets = cleanNearestJetOnly(self.cleanGenJets, photons, self.jetLepDR) #event.nGenJets25 = 0 #event.nGenJets25Cen = 0 #event.nGenJets25Fwd = 0 #for j in event.cleanGenJets: # event.nGenJets25 += 1 # if abs(j.eta()) <= 2.4: event.nGenJets25Cen += 1 # else: event.nGenJets25Fwd += 1 if self.cfg_ana.do_mc_match: self.jetFlavour(event) if hasattr(event,"jets"+self.cfg_ana.collectionPostFix): raise RuntimeError, "Event already contains a jet collection with the following postfix: "+self.cfg_ana.collectionPostFix setattr(event,"rho" +self.cfg_ana.collectionPostFix, self.rho ) setattr(event,"deltaMetFromJEC" +self.cfg_ana.collectionPostFix, self.deltaMetFromJEC ) setattr(event,"allJetsUsedForMET" +self.cfg_ana.collectionPostFix, self.allJetsUsedForMET ) setattr(event,"jets" +self.cfg_ana.collectionPostFix, self.jets ) setattr(event,"jetsFailId" +self.cfg_ana.collectionPostFix, self.jetsFailId ) setattr(event,"jetsAllNoID" +self.cfg_ana.collectionPostFix, self.jetsAllNoID ) setattr(event,"jetsIdOnly" +self.cfg_ana.collectionPostFix, self.jetsIdOnly ) setattr(event,"cleanJetsAll" +self.cfg_ana.collectionPostFix, self.cleanJetsAll ) setattr(event,"cleanJets" +self.cfg_ana.collectionPostFix, self.cleanJets ) setattr(event,"cleanJetsFwd" +self.cfg_ana.collectionPostFix, self.cleanJetsFwd ) setattr(event,"discardedJets" +self.cfg_ana.collectionPostFix, self.discardedJets ) setattr(event,"gamma_cleanJetsAll" +self.cfg_ana.collectionPostFix, self.gamma_cleanJetsAll ) setattr(event,"gamma_cleanJets" +self.cfg_ana.collectionPostFix, self.gamma_cleanJets ) setattr(event,"gamma_cleanJetsFwd" +self.cfg_ana.collectionPostFix, self.gamma_cleanJetsFwd ) if self.cfg_comp.isMC: setattr(event,"deltaMetFromJetSmearing"+self.cfg_ana.collectionPostFix, self.deltaMetFromJetSmearing) setattr(event,"cleanGenJets" +self.cfg_ana.collectionPostFix, self.cleanGenJets ) setattr(event,"genJets" +self.cfg_ana.collectionPostFix, self.genJets ) if self.cfg_ana.do_mc_match: setattr(event,"bqObjects" +self.cfg_ana.collectionPostFix, self.bqObjects ) setattr(event,"cqObjects" +self.cfg_ana.collectionPostFix, self.cqObjects ) setattr(event,"partons" +self.cfg_ana.collectionPostFix, self.partons ) setattr(event,"heaviestQCDFlavour" +self.cfg_ana.collectionPostFix, self.heaviestQCDFlavour ) return True def testJetID(self, jet): jet.puJetIdPassed = jet.puJetId() jet.pfJetIdPassed = jet.jetID('POG_PFID_Loose') if self.cfg_ana.relaxJetId: return True else: return jet.pfJetIdPassed and (jet.puJetIdPassed or not(self.doPuId)) def testJetNoID( self, jet ): # 2 is loose pile-up jet id return jet.pt() > self.cfg_ana.jetPt and \ abs( jet.eta() ) < self.cfg_ana.jetEta; def jetFlavour(self,event): def isFlavour(x,f): id = abs(x.pdgId()) if id > 999: return (id/1000)%10 == f if id > 99: return (id/100)%10 == f return id % 100 == f self.bqObjects = [ p for p in event.genParticles if (p.status() == 2 and isFlavour(p,5)) ] self.cqObjects = [ p for p in event.genParticles if (p.status() == 2 and isFlavour(p,4)) ] self.partons = [ p for p in event.genParticles if ((p.status() == 23 or p.status() == 3) and abs(p.pdgId())>0 and (abs(p.pdgId()) in [1,2,3,4,5,21]) ) ] match = matchObjectCollection2(self.cleanJetsAll, self.partons, deltaRMax = 0.3) for jet in self.cleanJetsAll: parton = match[jet] jet.partonId = (parton.pdgId() if parton != None else 0) jet.partonMotherId = (parton.mother(0).pdgId() if parton != None and parton.numberOfMothers()>0 else 0) for jet in self.jets: (bmatch, dr) = bestMatch(jet, self.bqObjects) if dr < 0.4: jet.mcFlavour = 5 else: (cmatch, dr) = bestMatch(jet, self.cqObjects) if dr < 0.4: jet.mcFlavour = 4 else: jet.mcFlavour = 0 self.heaviestQCDFlavour = 5 if len(self.bqObjects) else (4 if len(self.cqObjects) else 1); def matchJets(self, event, jets): match = matchObjectCollection2(jets, event.genbquarks + event.genwzquarks, deltaRMax = 0.3) for jet in jets: gen = match[jet] jet.mcParton = gen jet.mcMatchId = (gen.sourceId if gen != None else 0) jet.mcMatchFlav = (abs(gen.pdgId()) if gen != None else 0) match = matchObjectCollection2(jets, self.genJets, deltaRMax = 0.3) for jet in jets: jet.mcJet = match[jet] def smearJets(self, event, jets): # https://twiki.cern.ch/twiki/bin/viewauth/CMS/TWikiTopRefSyst#Jet_energy_resolution for jet in jets: gen = jet.mcJet if gen != None: genpt, jetpt, aeta = gen.pt(), jet.pt(), abs(jet.eta()) # from https://twiki.cern.ch/twiki/bin/view/CMS/JetResolution factor = 1.052 + self.shiftJER*math.hypot(0.012,0.062); if aeta > 2.3: factor = 1.288 + self.shiftJER*math.hypot(0.127,0.154) elif aeta > 1.7: factor = 1.134 + self.shiftJER*math.hypot(0.035,0.066) elif aeta > 1.1: factor = 1.096 + self.shiftJER*math.hypot(0.017,0.063) elif aeta > 0.5: factor = 1.057 + self.shiftJER*math.hypot(0.012,0.056) ptscale = max(0.0, (jetpt + (factor-1)*(jetpt-genpt))/jetpt) #print "get with pt %.1f (gen pt %.1f, ptscale = %.3f)" % (jetpt,genpt,ptscale) jet.deltaMetFromJetSmearing = [ -(ptscale-1)*jet.rawFactor()*jet.px(), -(ptscale-1)*jet.rawFactor()*jet.py() ] if ptscale != 0: jet.setP4(jet.p4()*ptscale) # leave the uncorrected unchanged for sync jet._rawFactorMultiplier *= (1.0/ptscale) if ptscale != 0 else 1
class JetAnalyzer(Analyzer): """Analyze jets. Copied from heppy examples and edit to not rely on heppy examples. This analyzer filters the jets that do not correspond to the leptons stored in event.selectedLeptons, and puts in the event: - jets: all jets passing the pt and eta cuts - cleanJets: the collection of jets away from the leptons - cleanBJets: the jets passing testBJet, and away from the leptons Example configuration: jetAna = cfg.Analyzer( 'JetAnalyzer', jetCol = 'slimmedJets' # cmg jet input collection # pt threshold jetPt = 30, # eta range definition jetEta = 5.0, # seed for the btag scale factor btagSFseed = 0xdeadbeef, # if True, the PF and PU jet ID are not applied, and the jets get flagged relaxJetId = False, relaxPuJetId = False, ) """ def __init__(self, cfg_ana, cfg_comp, looperName): super(JetAnalyzer, self).__init__(cfg_ana, cfg_comp, looperName) self.btagSF = BTagSF(0, wp='medium') self.recalibrateJets = getattr(cfg_ana, 'recalibrateJets', False) mcGT = getattr(cfg_ana, 'mcGT', 'Spring16_25nsV6_MC') dataGT = getattr(cfg_ana, 'dataGT', 'Spring16_25nsV6_DATA') if self.recalibrateJets: doResidual = getattr(cfg_ana, 'applyL2L3Residual', 'Data') if doResidual == "MC": doResidual = self.cfg_comp.isMC elif doResidual == "Data": doResidual = not self.cfg_comp.isMC elif doResidual not in [True, False]: raise RuntimeError, "If specified, applyL2L3Residual must be any of { True, False, 'MC', 'Data'(default)}" GT = getattr(cfg_comp, 'jecGT', mcGT if self.cfg_comp.isMC else dataGT) # instantiate the jet re-calibrator self.jetReCalibrator = JetReCalibrator( GT, 'AK4PFchs', doResidual, jecPath="%s/src/CMGTools/RootTools/data/jec" % os.environ['CMSSW_BASE']) def declareHandles(self): super(JetAnalyzer, self).declareHandles() self.handles['jets'] = AutoHandle(self.cfg_ana.jetCol, 'std::vector<pat::Jet>') if hasattr(self.cfg_ana, 'leptonCollections'): for coll, cms_type in self.cfg_ana.leptonCollections.items(): self.handles[coll] = AutoHandle(coll, cms_type) if self.cfg_comp.isMC: self.mchandles['genParticles'] = AutoHandle( 'packedGenParticles', 'std::vector<pat::PackedGenParticle>') self.mchandles['genJets'] = AutoHandle( 'slimmedGenJets', 'std::vector<reco::GenJet>') def beginLoop(self, setup): super(JetAnalyzer, self).beginLoop(setup) self.counters.addCounter('jets') count = self.counters.counter('jets') count.register('all events') count.register('at least 2 good jets') count.register('at least 2 clean jets') count.register('at least 1 b jet') count.register('at least 2 b jets') def process(self, event): self.readCollections(event.input) miniaodjets = self.handles['jets'].product() allJets = [] event.jets = [] event.bJets = [] event.cleanJets = [] event.cleanBJets = [] leptons = [] if hasattr(event, 'selectedLeptons'): leptons = event.selectedLeptons if hasattr(self.cfg_ana, 'toClean'): leptons = getattr(event, self.cfg_ana.toClean) if hasattr(self.cfg_ana, 'leptonCollections'): for coll in self.cfg_ana.leptonCollections: leptons += self.handles[coll].product() genJets = None if self.cfg_comp.isMC: genJets = map(GenJet, self.mchandles['genJets'].product()) allJets = [Jet(jet) for jet in miniaodjets] if self.recalibrateJets: self.jetReCalibrator.correctAll(allJets, event.rho, delta=0., addCorr=True, addShifts=True) for jet in allJets: if genJets: # Use DeltaR = 0.25 matching like JetMET pairs = matchObjectCollection([jet], genJets, 0.25 * 0.25) if pairs[jet] is None: pass else: jet.matchedGenJet = pairs[jet] # Add JER correction for MC jets. Requires gen-jet matching. if self.cfg_comp.isMC and hasattr( self.cfg_ana, 'jerCorr') and self.cfg_ana.jerCorr: self.jerCorrection(jet) # Add JES correction for MC jets. if self.cfg_comp.isMC and hasattr(self.cfg_ana, 'jesCorr'): self.jesCorrection(jet, self.cfg_ana.jesCorr) if self.testJet(jet): event.jets.append(jet) if self.testBJet(jet): event.bJets.append(jet) self.counters.counter('jets').inc('all events') event.cleanJets, dummy = cleanObjectCollection(event.jets, masks=leptons, deltaRMin=0.5) event.cleanBJets, dummy = cleanObjectCollection(event.bJets, masks=leptons, deltaRMin=0.5) # Attach matched jets to selected + other leptons if hasattr(event, 'otherLeptons'): leptons += event.otherLeptons pairs = matchObjectCollection(leptons, allJets, 0.5 * 0.5) # associating a jet to each lepton for lepton in leptons: jet = pairs[lepton] if jet is None: lepton.jet = lepton else: lepton.jet = jet # associating a leg to each clean jet invpairs = matchObjectCollection(event.cleanJets, leptons, 99999.) for jet in event.cleanJets: leg = invpairs[jet] jet.leg = leg for jet in event.cleanJets: jet.matchGenParton = 999.0 event.jets30 = [jet for jet in event.jets if jet.pt() > 30] event.cleanJets30 = [jet for jet in event.cleanJets if jet.pt() > 30] if len(event.jets30) >= 2: self.counters.counter('jets').inc('at least 2 good jets') if len(event.cleanJets30) >= 2: self.counters.counter('jets').inc('at least 2 clean jets') if len(event.cleanBJets) > 0: self.counters.counter('jets').inc('at least 1 b jet') if len(event.cleanBJets) > 1: self.counters.counter('jets').inc('at least 2 b jets') # save HTs event.HT_allJets = sum([jet.pt() for jet in allJets]) event.HT_jets = sum([jet.pt() for jet in event.jets]) event.HT_bJets = sum([jet.pt() for jet in event.bJets]) event.HT_cleanJets = sum([jet.pt() for jet in event.cleanJets]) event.HT_jets30 = sum([jet.pt() for jet in event.jets30]) event.HT_cleanJets30 = sum([jet.pt() for jet in event.cleanJets30]) return True def jerCorrection(self, jet): ''' Adds JER correction according to first method at https://twiki.cern.ch/twiki/bin/view/CMS/JetResolution Requires some attention when genJet matching fails. ''' if not hasattr(jet, 'matchedGenJet'): return #import pdb; pdb.set_trace() corrections = [0.052, 0.057, 0.096, 0.134, 0.288] maxEtas = [0.5, 1.1, 1.7, 2.3, 5.0] eta = abs(jet.eta()) for i, maxEta in enumerate(maxEtas): if eta < maxEta: pt = jet.pt() deltaPt = (pt - jet.matchedGenJet.pt()) * corrections[i] totalScale = (pt + deltaPt) / pt if totalScale < 0.: totalScale = 0. jet.scaleEnergy(totalScale) break def jesCorrection(self, jet, scale=0.): ''' Adds JES correction in number of sigmas (scale) ''' # Do nothing if nothing to change if scale == 0.: return unc = jet.uncOnFourVectorScale() totalScale = 1. + scale * unc if totalScale < 0.: totalScale = 0. jet.scaleEnergy(totalScale) def testJetID(self, jet): jet.puJetIdPassed = jet.puJetId() jet.pfJetIdPassed = jet.jetID("POG_PFID_Loose") puJetId = self.cfg_ana.relaxPuJetId or jet.puJetIdPassed pfJetId = self.cfg_ana.relaxJetId or jet.pfJetIdPassed return puJetId and pfJetId def testJet(self, jet): pt = jet.pt() if hasattr(self.cfg_ana, 'ptUncTolerance') and self.cfg_ana.ptUncTolerance: pt = max(pt, pt * jet.corrJECUp / jet.corr, pt * jet.corrJECDown / jet.corr) return pt > self.cfg_ana.jetPt and \ abs( jet.eta() ) < self.cfg_ana.jetEta and \ self.testJetID(jet) def testBJet(self, jet, csv_cut=0.8): # medium csv working point # https://twiki.cern.ch/twiki/bin/viewauth/CMS/BtagRecommendation74X jet.btagMVA = jet.btag('pfCombinedInclusiveSecondaryVertexV2BJetTags') # jet.btagFlag = jet.btagMVA > csv_cut # Use the following once we start applying data-MC scale factors: jet.btagFlag = self.btagSF.isBTagged( pt=jet.pt(), eta=jet.eta(), csv=jet.btag("pfCombinedInclusiveSecondaryVertexV2BJetTags"), jetflavor=abs(jet.partonFlavour()), is_data=not self.cfg_comp.isMC, csv_cut=csv_cut) return self.testJet(jet) and \ abs(jet.eta()) < 2.4 and \ jet.btagFlag and \ self.testJetID(jet)
class JetSelector(Analyzer): """Analyze jets. Copied from heppy examples and edit to not rely on heppy examples. This analyzer filters the jets that do not correspond to the leptons stored in event.selectedLeptons, and puts in the event: - jets: all jets passing the pt and eta cuts - cleanJets: the collection of jets away from the leptons - cleanBJets: the jets passing testBJet, and away from the leptons Example configuration: jetAna = cfg.Analyzer( 'JetSelector', jetCol = 'slimmedJets' # cmg jet input collection # pt threshold jetPt = 30, # eta range definition jetEta = 5.0, # seed for the btag scale factor btagSFseed = 0xdeadbeef, # if True, the PF and PU jet ID are not applied, and the jets get flagged relaxJetId = False, relaxPuJetId = False, ) """ def __init__(self, cfg_ana, cfg_comp, looperName): super(JetSelector, self).__init__(cfg_ana, cfg_comp, looperName) self.btagSF = BTagSF(0, wp='medium') self.recalibrateJets = getattr(cfg_ana, 'recalibrateJets', False) mcGT = getattr(cfg_ana, 'mcGT', 'Spring16_25nsV6_MC') dataGT = getattr(cfg_ana, 'dataGT', 'Spring16_25nsV6_DATA') if self.recalibrateJets: doResidual = getattr(cfg_ana, 'applyL2L3Residual', 'Data') if doResidual == "MC": doResidual = self.cfg_comp.isMC elif doResidual == "Data": doResidual = not self.cfg_comp.isMC elif doResidual not in [True, False]: raise RuntimeError, "If specified, applyL2L3Residual must be any of { True, False, 'MC', 'Data'(default)}" GT = getattr(cfg_comp, 'jecGT', mcGT if self.cfg_comp.isMC else dataGT) # instantiate the jet re-calibrator self.jetReCalibrator = JetReCalibrator( GT, 'AK4PFchs', doResidual, jecPath="%s/src/CMGTools/RootTools/data/jec" % os.environ['CMSSW_BASE']) def declareHandles(self): super(JetSelector, self).declareHandles() self.handles['jets'] = AutoHandle(self.cfg_ana.jetCol, 'std::vector<pat::Jet>') if self.cfg_comp.isMC: self.mchandles['genParticles'] = AutoHandle( 'packedGenParticles', 'std::vector<pat::PackedGenParticle>') self.mchandles['genJets'] = AutoHandle( 'slimmedGenJets', 'std::vector<reco::GenJet>') def beginLoop(self, setup): super(JetSelector, self).beginLoop(setup) self.counters.addCounter('jets') count = self.counters.counter('jets') count.register('all events') count.register('at least 2 good jets') count.register('at least 2 clean jets') count.register('exactly 2 b jets') def process(self, event): self.counters.counter('jets').inc('all events') self.readCollections(event.input) miniaodjets = self.handles['jets'].product() allJets = [] to_clean_against = [] if hasattr(self.cfg_ana, 'toClean'): for collection in self.cfg_ana.toClean: to_clean_against += getattr(event, collection) genJets = None if self.cfg_comp.isMC: genJets = map(GenJet, self.mchandles['genJets'].product()) allJets = [Jet(jet) for jet in miniaodjets] if self.recalibrateJets: self.jetReCalibrator.correctAll(allJets, event.rho, delta=0., addCorr=True, addShifts=True) for jet in allJets: if genJets: # Use DeltaR = 0.25 matching like JetMET pairs = matchObjectCollection([jet], genJets, 0.25 * 0.25) if pairs[jet] is None: pass else: jet.matchedGenJet = pairs[jet] # Add JER correction for MC jets. Requires gen-jet matching. if self.cfg_comp.isMC and hasattr( self.cfg_ana, 'jerCorr') and self.cfg_ana.jerCorr: self.jerCorrection(jet) # Add JES correction for MC jets. if self.cfg_comp.isMC and hasattr(self.cfg_ana, 'jesCorr'): self.jesCorrection(jet, self.cfg_ana.jesCorr) jet.btagMVA = jet.btag( 'pfCombinedInclusiveSecondaryVertexV2BJetTags' ) #TODO switch to deepCSV jet.btagged = self.btagSF.isBTagged( pt=jet.pt(), eta=jet.eta(), csv=jet.btag("pfCombinedInclusiveSecondaryVertexV2BJetTags"), jetflavor=abs(jet.hadronFlavour()), is_data=not self.cfg_comp.isMC, csv_cut= 0.800 #CSVM from https://twiki.cern.ch/twiki/bin/viewauth/CMS/BtagRecommendation80X ) ## if self.testJet(jet): ## event.jets.append(jet) ## if self.testBJet(jet): ## event.bJets.append(jet) allJets = [ jet for jet in allJets if bool(jet.jetID("POG_PFID_Loose")) if jet.pt() > 20. if abs(jet.eta()) < 2.4 ] if len(allJets) < 2: return False self.counters.counter('jets').inc('at least 2 good jets') event.jets, dummy = cleanObjectCollection(allJets, masks=to_clean_against, deltaRMin=0.5) if len(event.jets) < 2: return False self.counters.counter('jets').inc('at least 2 clean jets') event.bJets = [jet for jet in event.jets if jet.btagged] if len(event.bJets) != 2: return False self.counters.counter('jets').inc('exactly 2 b jets') # save HTs event.HT_jets = sum([jet.pt() for jet in event.jets]) event.HT_bJets = sum([jet.pt() for jet in event.bJets]) return True def jerCorrection(self, jet): ''' Adds JER correction according to first method at https://twiki.cern.ch/twiki/bin/view/CMS/JetResolution Requires some attention when genJet matching fails. ''' if not hasattr(jet, 'matchedGenJet'): return #import pdb; pdb.set_trace() corrections = [0.052, 0.057, 0.096, 0.134, 0.288] maxEtas = [0.5, 1.1, 1.7, 2.3, 5.0] eta = abs(jet.eta()) for i, maxEta in enumerate(maxEtas): if eta < maxEta: pt = jet.pt() deltaPt = (pt - jet.matchedGenJet.pt()) * corrections[i] totalScale = (pt + deltaPt) / pt if totalScale < 0.: totalScale = 0. jet.scaleEnergy(totalScale) break def jesCorrection(self, jet, scale=0.): ''' Adds JES correction in number of sigmas (scale) ''' # Do nothing if nothing to change if scale == 0.: return unc = jet.uncOnFourVectorScale() totalScale = 1. + scale * unc if totalScale < 0.: totalScale = 0. jet.scaleEnergy(totalScale)
class monoXPuppiJetAnalyzer(Analyzer): """Taken from RootTools.JetAnalyzer, simplified, modified, added corrections """ @staticmethod def puppiCorrector(pJet): #self, pJet): correctionFilePath = "%s/src/CMGTools//MonoXAnalysis/cfg/puppiCorr.root" % os.environ[ 'CMSSW_BASE'] #print "---- Correction file for PUPPI: ",correctionFilePath correctionFile = TFile.Open(correctionFilePath) puppisd_corrGEN = correctionFile.Get("puppiJECcorr_gen") puppisd_corrRECO_cen = correctionFile.Get("puppiJECcorr_reco_0eta1v3") puppisd_corrRECO_for = correctionFile.Get( "puppiJECcorr_reco_1v3eta2v5") genCorr = 1. recoCorr = 1. totalWeight = 1. genCorr = puppisd_corrGEN.Eval(pJet.pt()) if (math.fabs(pJet.eta()) <= 1.3): recoCorr = puppisd_corrRECO_cen.Eval(pJet.pt()) else: if (math.fabs(pJet.eta()) > 1.3): recoCorr = puppisd_corrRECO_for.Eval(pJet.pt()) totalWeight = genCorr * recoCorr pJet_massCorr = totalWeight * pJet.mass() return pJet_massCorr def __init__(self, cfg_ana, cfg_comp, looperName): super(monoXPuppiJetAnalyzer, self).__init__(cfg_ana, cfg_comp, looperName) mcGT = cfg_ana.mcGT if hasattr(cfg_ana, 'mcGT') else "PHYS14_25_V2" dataGT = cfg_ana.dataGT if hasattr(cfg_ana, 'dataGT') else "GR_70_V2_AN1" self.shiftJEC = self.cfg_ana.shiftJEC if hasattr( self.cfg_ana, 'shiftJEC') else 0 self.recalibrateJets = self.cfg_ana.recalibrateJets self.addJECShifts = self.cfg_ana.addJECShifts if hasattr( self.cfg_ana, 'addJECShifts') else 0 if self.recalibrateJets == "MC": self.recalibrateJets = self.cfg_comp.isMC elif self.recalibrateJets == "Data": self.recalibrateJets = not self.cfg_comp.isMC elif self.recalibrateJets not in [True, False]: raise RuntimeError, "recalibrateJets must be any of { True, False, 'MC', 'Data' }, while it is %r " % self.recalibrateJets self.doJEC = self.recalibrateJets or (self.shiftJEC != 0) or self.addJECShifts if self.doJEC: doResidual = getattr(cfg_ana, 'applyL2L3Residual', 'Data') if doResidual == "MC": doResidual = self.cfg_comp.isMC elif doResidual == "Data": doResidual = not self.cfg_comp.isMC elif doResidual not in [True, False]: raise RuntimeError, "If specified, applyL2L3Residual must be any of { True, False, 'MC', 'Data'(default)}" GT = getattr(cfg_comp, 'jecGT', mcGT if self.cfg_comp.isMC else dataGT) # instantiate the jet re-calibrator self.jetReCalibrator = JetReCalibrator(GT, cfg_ana.recalibrationType, doResidual, cfg_ana.jecPath) 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 def declareHandles(self): super(monoXPuppiJetAnalyzer, self).declareHandles() self.handles['jets'] = AutoHandle(self.cfg_ana.jetCol, 'std::vector<pat::Jet>') self.handles['rho'] = AutoHandle(self.cfg_ana.rho, 'double') def beginLoop(self, setup): super(monoXPuppiJetAnalyzer, self).beginLoop(setup) def process(self, event): self.readCollections(event.input) rho = float(self.handles['rho'].product()[0]) self.rho = rho ## Read jets, if necessary recalibrate and shift MET allJets = map(Jet, self.handles['jets'].product()) self.deltaMetFromJEC = [0., 0.] self.type1METCorr = [0., 0., 0.] if self.doJEC: if not self.recalibrateJets: # check point that things won't change jetsBefore = [(j.pt(), j.eta(), j.phi(), j.rawFactor()) for j in allJets] self.jetReCalibrator.correctAll(allJets, rho, delta=self.shiftJEC, addCorr=True, addShifts=self.addJECShifts, metShift=self.deltaMetFromJEC, type1METCorr=self.type1METCorr) if not self.recalibrateJets: jetsAfter = [(j.pt(), j.eta(), j.phi(), j.rawFactor()) for j in allJets] if len(jetsBefore) != len(jetsAfter): print "ERROR: I had to recompute jet corrections, and they rejected some of the jets:\nold = %s\n new = %s\n" % ( jetsBefore, jetsAfter) else: for (told, tnew) in zip(jetsBefore, jetsAfter): if (deltaR2(told[1], told[2], tnew[1], tnew[2])) > 0.0001: print "ERROR: I had to recompute jet corrections, and one jet direction moved: old = %s, new = %s\n" % ( told, tnew) elif abs(told[0] - tnew[0]) / ( told[0] + tnew[0]) > 0.5e-3 or abs( told[3] - tnew[3]) > 0.5e-3: print "ERROR: I had to recompute jet corrections, and one jet pt or corr changed: old = %s, new = %s\n" % ( told, tnew) ## Apply jet selection event.puppiJets = [] event.puppiJetsNoID = [] event.puppiAK08Jets = [] firstJet = True #global jetPuppiAk08 for jet in allJets: if self.testJetNoID(jet): event.puppiJetsNoID.append(jet) if self.testJetID(jet): # if firstJet: # jetPuppiAk08 = jet # print "FIRST JET!!!" # firstJet = False # else: # print "SECOND JET" # jetPuppiAk08+=jet jet.puppiMassCorrected = self.puppiCorrector(jet) event.puppiJets.append(jet) #jetPuppiAk08.puppiMassCorrected = self.puppiCorrector(jetPuppiAk08) #event.puppiAK08Jets.append(jetPuppiAk08) ## Associate jets to leptons leptons = event.inclusiveLeptons if hasattr( event, 'inclusiveLeptons') else event.selectedLeptons jlpairs = matchObjectCollection(leptons, allJets, self.jetLepDR**2) for jet in allJets: jet.leptons = [l for l in jlpairs if jlpairs[l] == jet] for lep in leptons: jet = jlpairs[lep] if jet is None: lep.puppijet = lep.jet else: lep.puppijet = jet def testJetID(self, jet): #jet.puJetIdPassed = jet.puJetId() jet.pfJetIdPassed = jet.jetID('POG_PFID_Loose') if self.cfg_ana.relaxJetId: return True else: return jet.pfJetIdPassed #return jet.pfJetIdPassed and (jet.puJetIdPassed or not(self.doPuId)) def testJetNoID(self, jet): return jet.pt() > self.cfg_ana.jetPt and \ abs( jet.eta() ) < self.cfg_ana.jetEta
class EventInterpretationBase( Analyzer ): def __init__(self, cfg_ana, cfg_comp, looperName): super(EventInterpretationBase,self).__init__(cfg_ana, cfg_comp, looperName) self.selectFat = self.cfg_ana.selectFat self.selectPairLNu = self.cfg_ana.selectPairLNu self.selectPairLL = self.cfg_ana.selectPairLL self.selectPairJJ = self.cfg_ana.selectPairJJ self.selectPairJJNuNu = self.cfg_ana.selectPairJJNuNu self.isMC =cfg_comp.isMC if hasattr(cfg_ana,'matchDR'): self.matchDR = cfg_ana.matchDR else: self.matchDR = 0.2 mcGT = cfg_ana.mcGT if hasattr(cfg_ana,'mcGT') else "PHYS14_25_V2" dataGT = cfg_ana.dataGT if hasattr(cfg_ana,'dataGT') else "GR_70_V2_AN1" self.shiftJEC = self.cfg_ana.shiftJEC if hasattr(self.cfg_ana, 'shiftJEC') else 0 self.recalibrateJets = self.cfg_ana.recalibrateJets if self.recalibrateJets == "MC" : self.recalibrateJets = self.cfg_comp.isMC elif self.recalibrateJets == "Data": self.recalibrateJets = not self.cfg_comp.isMC elif self.recalibrateJets not in [True,False]: raise RuntimeError, "recalibrateJets must be any of { True, False, 'MC', 'Data' }, while it is %r " % self.recalibrateJets self.doJEC = self.recalibrateJets or (self.shiftJEC != 0) if self.doJEC: if self.cfg_comp.isMC: if hasattr(self.cfg_comp,'globalTag'): self.jetReCalibrator = JetReCalibrator(self.cfg_comp.globalTag,self.cfg_ana.recalibrationType, False,cfg_ana.jecPath) self.jetReCalibratorFAT = JetReCalibrator(self.cfg_comp.globalTag,self.cfg_ana.recalibrationTypeFAT, False,cfg_ana.jecPath) else: self.jetReCalibrator = JetReCalibrator(mcGT,self.cfg_ana.recalibrationType, False,cfg_ana.jecPath) self.jetReCalibratorFAT = JetReCalibrator(mcGT,self.cfg_ana.recalibrationTypeFAT, False,cfg_ana.jecPath) else: if hasattr(self.cfg_comp,'globalTag'): self.jetReCalibrator = JetReCalibrator(self.cfg_comp.globalTag,self.cfg_ana.recalibrationType, True,cfg_ana.jecPath) self.jetReCalibratorFAT = JetReCalibrator(self.cfg_comp.globalTag,self.cfg_ana.recalibrationTypeFAT, True,cfg_ana.jecPath) else: self.jetReCalibrator = JetReCalibrator(dataGT,self.cfg_ana.recalibrationType, True,cfg_ana.jecPath) self.jetReCalibratorFAT = JetReCalibrator(dataGT,self.cfg_ana.recalibrationTypeFAT, True,cfg_ana.jecPath) self.attachBTag = cfg_ana.attachBTag if self.attachBTag: self.btagDiscriminator = cfg_ana.btagDiscriminator if hasattr(cfg_ana,'doSkim'): self.doSkim = cfg_ana.doSkim else: self.doSkim=False def declareHandles(self): super(EventInterpretationBase, self).declareHandles() self.handles['packed'] = AutoHandle( 'packedPFCandidates', 'std::vector<pat::PackedCandidate>' ) self.handles['rho'] = AutoHandle( self.cfg_ana.rho, 'double' ) if self.attachBTag or self.doSkim: self.handles['jets'] = AutoHandle( self.cfg_ana.standardJets, 'std::vector<pat::Jet>' ) self.handles['fatjets'] = AutoHandle( self.cfg_ana.fatJets, 'std::vector<pat::Jet>' ) self.handles['subjets'] = AutoHandle( (self.cfg_ana.subJets,'SubJets'), 'std::vector<pat::Jet>' ) def removeLeptonFootPrint(self,leptons,cands): toRemove=[] cList=list(cands) for lepton in leptons: for p in range(0,lepton.numberOfSourceCandidatePtrs()): index = lepton.sourceCandidatePtr(p).key() if not cands[index] in toRemove: toRemove.append(cands[index]) for r in toRemove: cList.remove(r) return cList def matchSubJets(self,jets,genquarks): for j in jets: for s in j.subjets_SD+j.subjets: s.mcquark = None s.matched=0 for g in genquarks: if deltaR(s.eta(),s.phi(),g.eta(),g.phi())<self.matchDR: s.matched=1 s.mcquark = g break; def skim(self,leptons,met): cleanedJets = [] for jet in self.handles['fatjets'].product(): overlap=False for lepton in leptons: if deltaR(jet.eta(),jet.phi(),lepton.eta(),lepton.phi())<0.8: overlap=True break; if not overlap: cleanedJets.append(jet) nJets = len(cleanedJets) nLeptons = len(leptons) if (nLeptons>0 and nJets>0) or nJets>1 or (nJets>0 and met.pt()>300): return True return False def makeFatJets(self,cands): toolboxFat = PyJetToolbox(cands) toolboxFat.setInterface(True,self.cfg_ana.ktPowerFat,self.cfg_ana.rFat) toolboxFat.setMassDrop(self.cfg_ana.massdrop) toolboxFat.setSubjets(True,'inc',self.cfg_ana.subjets) toolboxFat.setPruning(self.cfg_ana.prunning) toolboxFat.setNtau(True) if hasattr(self.cfg_ana,'softdrop_beta'): toolboxFat.setSoftDrop(self.cfg_ana.softdrop,self.cfg_ana.softdrop_beta,self.cfg_ana.softdrop_zeta) else: toolboxFat.setSoftDrop(self.cfg_ana.softdrop) # Lets cluster !! Fat jets first fatJets=toolboxFat.inclusiveJets(200.0,True) filtered = filter(self.selectFat,fatJets) ##Apply JECS in SoftDrop and Pruned: if self.jetReCalibratorFAT is not None: prunedJets=[] for j in fatJets: prunedJets.append(j.softDropJet) prunedJets.append(j.prunedJet) self.jetReCalibratorFAT.correctAll(prunedJets, self.rho, self.shiftJEC,True,False,[0.,0.],[0.,0.,0.]) for p in prunedJets: p.setRawFactor(1.0/p.corr) standardFatJets = self.handles['fatjets'].product() if self.attachBTag: for fat in filtered: for standardFat in standardFatJets: fat.btag = standardFat.bDiscriminator(self.btagDiscriminator) for j in fat.subjets_SD+fat.subjets: for standard in self.handles['subjets'].product(): if deltaR(j.eta(),j.phi(),standard.eta(),standard.phi())<0.1: j.btag = standard.bDiscriminator(self.btagDiscriminator) break return filtered def makeSatelliteJets(self,cands): toolbox = PyJetToolbox(cands) toolbox.setInterface(True,self.cfg_ana.ktPower,self.cfg_ana.r) toolbox.setMassDrop(False) toolbox.setSubjets(False,'inc',2) toolbox.setPruning(False) toolbox.setNtau(False) toolbox.setSoftDrop(False) unfiltered = toolbox.inclusiveJets(30.0,False) if self.attachBTag: for j in unfiltered: for standard in self.handles['jets'].product(): if deltaR(j.eta(),j.phi(),standard.eta(),standard.phi())<0.1: j.btag = standard.bDiscriminator(self.btagDiscriminator) break if self.jetReCalibrator is not None: self.jetReCalibrator.correctAll(unfiltered, self.rho, self.shiftJEC,True,False,[0.,0.],[0.,0.,0.]) for p in unfiltered: p.setRawFactor(1.0/p.corr) filtered=filter(lambda x: x.pt()>30, unfiltered) return filtered else: return unfiltered def removeJetFootPrint(self,jets,cands): toRemove=[] for j in jets: toRemove.extend(j.constituents) out=list(set(cands)-set(toRemove)) return out def topology(self,obj): #first clean nicely the jets from leptons and subjets objToClean=[] if abs(obj['pair'].leg1.pdgId())==23: objToClean.extend([obj['pair'].leg1.leg1,obj['pair'].leg1.leg2]) # print 'Z->ll', obj['pair'].leg1.leg1.pt(),obj['pair'].leg1.leg1.eta(),obj['pair'].leg1.leg1.phi(),obj['pair'].leg1.leg2.pt(),obj['pair'].leg1.leg2.eta(),obj['pair'].leg1.leg2.phi() if abs(obj['pair'].leg1.pdgId())==24: objToClean.extend([obj['pair'].leg1.leg1]) # print 'W->lnu', obj['pair'].leg1.leg1.pt(),obj['pair'].leg1.leg1.eta(),obj['pair'].leg1.leg1.phi() if abs(obj['pair'].leg1.pdgId())==1: objToClean.extend(obj['pair'].leg1.subjets) if abs(obj['pair'].leg2.pdgId())==23: objToClean.extend([obj['pair'].leg2.leg1,obj['pair'].leg2.leg2]) if abs(obj['pair'].leg2.pdgId())==24: objToClean.extend([obj['pair'].leg2.leg1]) if abs(obj['pair'].leg2.pdgId())==1: objToClean.extend(obj['pair'].leg2.subjets) # print 'jet', obj['pair'].leg2.pt(),obj['pair'].leg2.eta(),obj['pair'].leg2.phi() newJets=[] for j in obj['satelliteJets']: keep=True for c in objToClean: dr=deltaR(j.eta(),j.phi(),c.eta(),c.phi()) # print 'dr=',dr if dr<0.4: keep=False break if keep: # print 'filtered satellite jet',j.pt(),j.eta(),j.phi() newJets.append(j) obj['satelliteJets']=newJets if len(obj['satelliteJets'])<2: obj['vbfDEta'] = -1.0 obj['vbfMJJ'] = -1.0 else: j1 = obj['satelliteJets'][0] j2 = obj['satelliteJets'][1] obj['vbfDEta'] = abs(j1.eta()-j2.eta()) obj['vbfMJJ'] = (j1.p4()+j2.p4()).M() NL = 0 NM = 0 NT = 0 bestBTag=None minDR=1000.0 for s in obj['satelliteJets']: btag = s.bTag() if btag>0.423: NL=NL+1 DR=deltaR(obj['pair'].eta(),obj['pair'].phi(),s.eta(),s.phi()) if DR<minDR: bestBTag=s minDR=DR if btag>0.814: NM=NM+1 if btag>0.941: NT=NT+1 obj['nLooseBTags'] = NL obj['nMediumBTags'] = NM obj['nTightBTags'] = NT if bestBTag==None: obj['topMass'] = -1 else: obj['topMass'] = (bestBTag.p4()+s.p4()).mass() def beginLoop(self, setup): super(EventInterpretationBase,self).beginLoop(setup) def process(self, event): self.readCollections( event.input ) rho = float(self.handles['rho'].product()[0]) self.rho = rho
class JetAnalyzer(Analyzer): """Analyze jets. Copied from heppy examples and edit to not rely on heppy examples. This analyzer filters the jets that do not correspond to the leptons stored in event.selectedLeptons, and puts in the event: - jets: all jets passing the pt and eta cuts - cleanJets: the collection of jets away from the leptons - cleanBJets: the jets passing testBJet, and away from the leptons Example configuration: jetAna = cfg.Analyzer( 'JetAnalyzer', jetCol = 'slimmedJets' # cmg jet input collection # pt threshold jetPt = 30, # eta range definition jetEta = 5.0, # seed for the btag scale factor btagSFseed = 0xdeadbeef, # if True, the PF and PU jet ID are not applied, and the jets get flagged relaxJetId = False, relaxPuJetId = False, ) """ def __init__(self, cfg_ana, cfg_comp, looperName): super(JetAnalyzer, self).__init__(cfg_ana, cfg_comp, looperName) self.btagSF = BTagSF(seed=getattr(self.cfg_ana, 'btagSFseed', 0), mc_eff_file=getattr(self.cfg_ana, 'mc_eff_file'), sf_file=getattr(self.cfg_ana, 'sf_file'), wp=getattr(self.cfg_ana, 'btag_wp', 'medium'), ) self.recalibrateJets = getattr(cfg_ana, 'recalibrateJets', False) mcGT = getattr(cfg_ana, 'mcGT', 'Spring16_25nsV6_MC') dataGT = getattr(cfg_ana, 'dataGT', 'Spring16_25nsV6_DATA') if self.recalibrateJets: doResidual = getattr(cfg_ana, 'applyL2L3Residual', 'Data') if doResidual == "MC": doResidual = self.cfg_comp.isMC elif doResidual == "Data": doResidual = not self.cfg_comp.isMC elif doResidual not in [True, False]: raise RuntimeError, "If specified, applyL2L3Residual must be any of { True, False, 'MC', 'Data'(default)}" GT = getattr(cfg_comp, 'jecGT', mcGT if self.cfg_comp.isMC else dataGT) # instantiate the jet re-calibrator self.jetReCalibrator = JetReCalibrator(GT, 'AK4PFchs', doResidual, jecPath="%s/src/CMGTools/RootTools/data/jec" % os.environ['CMSSW_BASE']) def declareHandles(self): super(JetAnalyzer, self).declareHandles() # self.handles['jets'] = AutoHandle(self.cfg_ana.jetCol, 'std::vector<pat::Jet>') # try to use recomputed jets, but if it fails, resort to normal slimmedJets in miniAODs self.handles['jets'] = AutoHandle(self.cfg_ana.jetCol, 'std::vector<pat::Jet>', mayFail=True, fallbackLabel='slimmedJets', lazy=False) if self.cfg_comp.isMC: self.mchandles['genParticles'] = AutoHandle('packedGenParticles', 'std::vector<pat::PackedGenParticle>') self.mchandles['genJets' ] = AutoHandle('slimmedGenJets' , 'std::vector<reco::GenJet>' ) def beginLoop(self, setup): super(JetAnalyzer, self).beginLoop(setup) self.counters.addCounter('jets') count = self.counters.counter('jets') count.register('all events') def process(self, event): self.readCollections(event.input) # create Heppy Jet objects allJets = map(Jet, self.handles['jets'].product()) # create intially empty jet collections event.jets = [] event.bJets = [] event.cleanJets = OrderedDict() event.cleanJets30 = OrderedDict() event.cleanBJets = OrderedDict() # selected leptons as defined in the analyzer prior to this leptons = getattr(event, 'selectedLeptons', []) genJets = None if self.cfg_comp.isMC: genJets = map(GenJet, self.mchandles['genJets'].product()) # recalibrate jets if self.recalibrateJets: self.jetReCalibrator.correctAll(allJets, event.rho, delta=0., metShift=[0.,0.], addCorr=True, addShifts=True) # fill the various jet collections and # possibly correct jets (if configured to do so) for jet in allJets: if genJets: # Use DeltaR = 0.25 matching like JetMET pairs = matchObjectCollection([jet], genJets, 0.25 * 0.25) if pairs[jet] is None: pass else: jet.matchedGenJet = pairs[jet] # Add JER/JES correction for MC jets. Requires gen-jet matching. # Add JES correction for MC jets. if self.cfg_comp.isMC and hasattr(self.cfg_ana, 'jerCorr') and self.cfg_ana.jerCorr: self.jerCorrection(jet) if self.cfg_comp.isMC and hasattr(self.cfg_ana, 'jesCorr') : self.jesCorrection(jet, self.cfg_ana.jesCorr) # preselect jets if self.testJet(jet) : event.jets.append(jet) # compute deepjet scores only once self._prepareDeepJet(jet, year=self.cfg_ana.year, wp=getattr(self.cfg_ana, 'btag_wp', 'medium')) # create collection of bjets if self.testBJet(jet, year=self.cfg_ana.year, wp=getattr(self.cfg_ana, 'btag_wp', 'medium'), final_state='tot'): event.bJets.append(jet) self.counters.counter('jets').inc('all events') for final_state in ['mmm', 'mem', 'eee', 'eem']: if final_state not in leptons.keys(): continue # RM: found out that there's not a lot of final state dependency, # so we'll use the inclusive measurement that has better stats # preselect jets, with the appropriate btag SF correction **final state dependent**! # event.bJets = [] # for jet in event.jets: # if self.testBJet(jet, # year=self.cfg_ana.year, # wp=getattr(self.cfg_ana, 'btag_wp', 'medium'), # final_state=final_state): # event.bJets.append(jet) # clean jets from selected leptons (per final state!) event.cleanJets [final_state], dummy = cleanObjectCollection(event.jets , masks=leptons[final_state], deltaRMin=0.5) event.cleanBJets[final_state], dummy = cleanObjectCollection(event.bJets, masks=leptons[final_state], deltaRMin=0.5) pairs = matchObjectCollection(leptons[final_state], allJets, 0.5 * 0.5) # associating a jet to each lepton for lepton in leptons[final_state]: jet = pairs[lepton] if jet is None: lepton.jet = lepton else: lepton.jet = jet # associating to each (clean) jet the lepton that's closest to it invpairs = matchObjectCollection(event.cleanJets[final_state], leptons[final_state], 99999.) for jet in event.cleanJets[final_state]: leg = invpairs[jet] jet.leg = leg for jet in event.cleanJets[final_state]: jet.matchGenParton = 999.0 event.jets30 = [jet for jet in event.jets if jet.pt() > 30] event.cleanJets30[final_state] = [jet for jet in event.cleanJets[final_state] if jet.pt() > 30] return True def jerCorrection(self, jet): ''' Adds JER correction according to first method at https://twiki.cern.ch/twiki/bin/view/CMS/JetResolution Requires some attention when genJet matching fails. ''' if not hasattr(jet, 'matchedGenJet'): return #import pdb; pdb.set_trace() corrections = [0.052, 0.057, 0.096, 0.134, 0.288] maxEtas = [0.5, 1.1, 1.7, 2.3, 5.0] eta = abs(jet.eta()) for i, maxEta in enumerate(maxEtas): if eta < maxEta: pt = jet.pt() deltaPt = (pt - jet.matchedGenJet.pt()) * corrections[i] totalScale = (pt + deltaPt) / pt if totalScale < 0.: totalScale = 0. jet.scaleEnergy(totalScale) break def jesCorrection(self, jet, scale=0.): ''' Adds JES correction in number of sigmas (scale) ''' # Do nothing if nothing to change if scale == 0.: return unc = jet.uncOnFourVectorScale() totalScale = 1. + scale * unc if totalScale < 0.: totalScale = 0. jet.scaleEnergy(totalScale) def testJetID(self, jet): jet.puJetIdPassed = jet.puJetId() jet.pfJetIdPassed = jet.jetID("POG_PFID_Tight") puJetId = self.cfg_ana.relaxPuJetId or jet.puJetIdPassed pfJetId = self.cfg_ana.relaxJetId or jet.pfJetIdPassed return puJetId and pfJetId def testJet(self, jet): pt = jet.pt() if hasattr(self.cfg_ana, 'ptUncTolerance') and self.cfg_ana.ptUncTolerance: pt = max(pt, pt * jet.corrJECUp/jet.corr, pt * jet.corrJECDown/jet.corr) return pt > self.cfg_ana.jetPt and \ abs( jet.eta() ) < self.cfg_ana.jetEta and \ self.testJetID(jet) def _prepareDeepJet(self, jet, year, wp): jet.deepflavour_prob_b = jet.btag('pfDeepFlavourJetTags:probb') jet.deepflavour_prob_bb = jet.btag('pfDeepFlavourJetTags:probbb') jet.deepflavour_prob_lepb = jet.btag('pfDeepFlavourJetTags:problepb') jet.deepflavour_score = jet.deepflavour_prob_b + \ jet.deepflavour_prob_bb + \ jet.deepflavour_prob_lepb jet.pass_deepflavour = jet.deepflavour_score >= deepflavour_wp[year][wp] def testBJet(self, jet, year, wp, final_state): ''' Test DeepFlavour including scale factors ''' # Use the following once we start applying data-MC scale factors: jet.btagFlag = self.btagSF.isBTagged( pt = jet.pt(), eta = jet.eta(), deepjet = jet.deepflavour_score, jetflavor = abs(jet.partonFlavour()), is_data = not self.cfg_comp.isMC, deepjet_cut = deepflavour_wp[year][wp], final_state = final_state, ) return self.testJet(jet) and \ abs(jet.eta()) < 2.4 and \ jet.btagFlag and \ self.testJetID(jet)
class monoXFatJetAnalyzer(Analyzer): """Taken from RootTools.JetAnalyzer, simplified, modified, added corrections """ def __init__(self, cfg_ana, cfg_comp, looperName): super(monoXFatJetAnalyzer, self).__init__(cfg_ana, cfg_comp, looperName) mcGT = cfg_ana.mcGT if hasattr(cfg_ana, 'mcGT') else "PHYS14_25_V2" dataGT = cfg_ana.dataGT if hasattr(cfg_ana, 'dataGT') else "GR_70_V2_AN1" self.shiftJEC = self.cfg_ana.shiftJEC if hasattr( self.cfg_ana, 'shiftJEC') else 0 self.recalibrateJets = self.cfg_ana.recalibrateJets self.addJECShifts = self.cfg_ana.addJECShifts if hasattr( self.cfg_ana, 'addJECShifts') else 0 if self.recalibrateJets == "MC": self.recalibrateJets = self.cfg_comp.isMC elif self.recalibrateJets == "Data": self.recalibrateJets = not self.cfg_comp.isMC elif self.recalibrateJets not in [True, False]: raise RuntimeError, "recalibrateJets must be any of { True, False, 'MC', 'Data' }, while it is %r " % self.recalibrateJets self.doJEC = self.recalibrateJets or (self.shiftJEC != 0) or self.addJECShifts if self.doJEC: doResidual = getattr(cfg_ana, 'applyL2L3Residual', 'Data') if doResidual == "MC": doResidual = self.cfg_comp.isMC elif doResidual == "Data": doResidual = not self.cfg_comp.isMC elif doResidual not in [True, False]: raise RuntimeError, "If specified, applyL2L3Residual must be any of { True, False, 'MC', 'Data'(default)}" GT = getattr(cfg_comp, 'jecGT', mcGT if self.cfg_comp.isMC else dataGT) # instantiate the jet re-calibrator self.jetReCalibrator = JetReCalibrator(GT, cfg_ana.recalibrationType, doResidual, cfg_ana.jecPath) 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 def declareHandles(self): super(monoXFatJetAnalyzer, self).declareHandles() self.handles['jets'] = AutoHandle(self.cfg_ana.jetCol, 'std::vector<pat::Jet>') self.handles['rho'] = AutoHandle(self.cfg_ana.rho, 'double') def beginLoop(self, setup): super(monoXFatJetAnalyzer, self).beginLoop(setup) def process(self, event): self.readCollections(event.input) rho = float(self.handles['rho'].product()[0]) self.rho = rho ## Read jets, if necessary recalibrate and shift MET allJets = map(Jet, self.handles['jets'].product()) self.deltaMetFromJEC = [0., 0.] self.type1METCorr = [0., 0., 0.] if self.doJEC: if not self.recalibrateJets: # check point that things won't change jetsBefore = [(j.pt(), j.eta(), j.phi(), j.rawFactor()) for j in allJets] self.jetReCalibrator.correctAll(allJets, rho, delta=self.shiftJEC, addCorr=True, addShifts=self.addJECShifts, metShift=self.deltaMetFromJEC, type1METCorr=self.type1METCorr) if not self.recalibrateJets: jetsAfter = [(j.pt(), j.eta(), j.phi(), j.rawFactor()) for j in allJets] if len(jetsBefore) != len(jetsAfter): print "ERROR: I had to recompute jet corrections, and they rejected some of the jets:\nold = %s\n new = %s\n" % ( jetsBefore, jetsAfter) else: for (told, tnew) in zip(jetsBefore, jetsAfter): if (deltaR2(told[1], told[2], tnew[1], tnew[2])) > 0.0001: print "ERROR: I had to recompute jet corrections, and one jet direction moved: old = %s, new = %s\n" % ( told, tnew) elif abs(told[0] - tnew[0]) / ( told[0] + tnew[0]) > 0.5e-3 or abs( told[3] - tnew[3]) > 0.5e-3: print "ERROR: I had to recompute jet corrections, and one jet pt or corr changed: old = %s, new = %s\n" % ( told, tnew) ## Apply jet selection event.fatJets = [] event.fatJetsNoID = [] for jet in allJets: if self.testJetNoID(jet): event.fatJetsNoID.append(jet) if self.testJetID(jet): event.fatJets.append(jet) ## Associate jets to leptons leptons = event.inclusiveLeptons if hasattr( event, 'inclusiveLeptons') else event.selectedLeptons jlpairs = matchObjectCollection(leptons, allJets, self.jetLepDR**2) for jet in allJets: jet.leptons = [l for l in jlpairs if jlpairs[l] == jet] for lep in leptons: jet = jlpairs[lep] if jet is None: lep.fatjet = lep.jet else: lep.fatjet = jet def testJetID(self, jet): #jet.puJetIdPassed = jet.puJetId() jet.pfJetIdPassed = jet.jetID('POG_PFID_Loose') if self.cfg_ana.relaxJetId: return True else: return jet.pfJetIdPassed #return jet.pfJetIdPassed and (jet.puJetIdPassed or not(self.doPuId)) def testJetNoID(self, jet): return jet.pt() > self.cfg_ana.jetPt and \ abs( jet.eta() ) < self.cfg_ana.jetEta
class JetAnalyzer(Analyzer): """Taken from RootTools.JetAnalyzer, simplified, modified, added corrections """ def __init__(self, cfg_ana, cfg_comp, looperName): super(JetAnalyzer, self).__init__(cfg_ana, cfg_comp, looperName) mcGT = cfg_ana.mcGT if hasattr(cfg_ana, 'mcGT') else "PHYS14_25_V2" dataGT = cfg_ana.dataGT if hasattr(cfg_ana, 'dataGT') else "GR_70_V2_AN1" self.shiftJEC = self.cfg_ana.shiftJEC if hasattr( self.cfg_ana, 'shiftJEC') else 0 self.recalibrateJets = self.cfg_ana.recalibrateJets if self.recalibrateJets == "MC": self.recalibrateJets = self.cfg_comp.isMC elif self.recalibrateJets == "Data": self.recalibrateJets = not self.cfg_comp.isMC elif self.recalibrateJets not in [True, False]: raise RuntimeError, "recalibrateJets must be any of { True, False, 'MC', 'Data' }, while it is %r " % self.recalibrateJets self.doJEC = self.recalibrateJets or (self.shiftJEC != 0) if self.doJEC: if self.cfg_comp.isMC: 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 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" ) def declareHandles(self): super(JetAnalyzer, self).declareHandles() self.handles['jets'] = AutoHandle(self.cfg_ana.jetCol, 'std::vector<pat::Jet>') self.handles['genJet'] = AutoHandle('slimmedGenJets', 'vector<reco::GenJet>') self.shiftJER = self.cfg_ana.shiftJER if hasattr( self.cfg_ana, 'shiftJER') else 0 self.handles['rho'] = AutoHandle(('fixedGridRhoFastjetAll', '', ''), 'double') def beginLoop(self, setup): super(JetAnalyzer, self).beginLoop(setup) def process(self, event): self.readCollections(event.input) rho = float(self.handles['rho'].product()[0]) event.rho = rho ## Read jets, if necessary recalibrate and shift MET allJets = map(Jet, self.handles['jets'].product()) event.deltaMetFromJEC = [0., 0.] if self.doJEC: #print "\nCalibrating jets %s for lumi %d, event %d" % (self.cfg_ana.jetCol, event.lumi, event.eventId) self.jetReCalibrator.correctAll(allJets, rho, delta=self.shiftJEC, metShift=event.deltaMetFromJEC) event.allJetsUsedForMET = allJets if self.cfg_comp.isMC: event.genJets = [x for x in self.handles['genJet'].product()] self.matchJets(event, allJets) if getattr(self.cfg_ana, 'smearJets', False): self.smearJets(event, allJets) ## Apply jet selection event.jets = [] event.jetsFailId = [] event.jetsAllNoID = [] event.jetsIdOnly = [] for jet in allJets: if self.testJetNoID(jet): event.jetsAllNoID.append(jet) if self.testJetID(jet): if (self.cfg_ana.doQG): self.computeQGvars(jet) jet.qgl = self.qglcalc.computeQGLikelihood(jet, rho) event.jets.append(jet) event.jetsIdOnly.append(jet) else: event.jetsFailId.append(jet) elif self.testJetID(jet): event.jetsIdOnly.append(jet) ## Clean Jets from leptons leptons = [] if hasattr(event, 'selectedLeptons'): leptons = [ l for l in event.selectedLeptons if l.pt() > self.lepPtMin ] if self.cfg_ana.cleanJetsFromTaus and hasattr(event, 'selectedTaus'): 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.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 ] ## Clean Jets from photons photons = [] if hasattr(event, 'selectedPhotons'): photons = [g for g in event.selectedPhotons] event.gamma_cleanJetsAll = cleanNearestJetOnly(event.cleanJetsAll, photons, self.jetGammaDR) event.gamma_cleanJets = [ j for j in event.gamma_cleanJetsAll if abs(j.eta()) < self.cfg_ana.jetEtaCentral ] event.gamma_cleanJetsFwd = [ j for j in event.gamma_cleanJetsAll if abs(j.eta()) >= self.cfg_ana.jetEtaCentral ] ### ## Associate jets to leptons leptons = event.inclusiveLeptons if hasattr( event, 'inclusiveLeptons') else event.selectedLeptons jlpairs = matchObjectCollection(leptons, allJets, self.jetLepDR**2) for jet in allJets: jet.leptons = [l for l in jlpairs if jlpairs[l] == jet] for lep in leptons: jet = jlpairs[lep] if jet is None: lep.jet = lep else: lep.jet = jet if self.cfg_comp.isMC: event.deltaMetFromJetSmearing = [0, 0] for j in event.cleanJetsAll: 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.nGenJets25 = 0 #event.nGenJets25Cen = 0 #event.nGenJets25Fwd = 0 #for j in event.cleanGenJets: # event.nGenJets25 += 1 # if abs(j.eta()) <= 2.4: event.nGenJets25Cen += 1 # else: event.nGenJets25Fwd += 1 self.jetFlavour(event) return True def testJetID(self, jet): jet.puJetIdPassed = jet.puJetId() jet.pfJetIdPassed = jet.jetID('POG_PFID_Loose') if self.cfg_ana.relaxJetId: return True else: return jet.pfJetIdPassed and (jet.puJetIdPassed or not (self.doPuId)) def testJetNoID(self, jet): # 2 is loose pile-up jet id return jet.pt() > self.cfg_ana.jetPt and \ abs( jet.eta() ) < self.cfg_ana.jetEta def computeQGvars(self, jet): jet.mult = 0 sum_weight = 0. sum_pt = 0. sum_deta = 0. sum_dphi = 0. sum_deta2 = 0. sum_detadphi = 0. sum_dphi2 = 0. for ii in range(0, jet.numberOfDaughters()): part = jet.daughter(ii) usePart = True if part.charge() == 0: # neutral particles if part.pt() > 1.: jet.mult += 1 else: # charged particles jet.mult += 1 if part.trackHighPurity() == False: usePart = False if part.fromPV() <= 1: usePart = False if usePart: deta = part.eta() - jet.eta() dphi = deltaPhi(part.phi(), jet.phi()) partPt = part.pt() weight = partPt * partPt sum_weight += weight sum_pt += partPt sum_deta += deta * weight sum_dphi += dphi * weight sum_deta2 += deta * deta * weight sum_detadphi += deta * dphi * weight sum_dphi2 += dphi * dphi * weight a = 0. b = 0. c = 0. if sum_weight > 0: jet.ptd = math.sqrt(sum_weight) / sum_pt ave_deta = sum_deta / sum_weight ave_dphi = sum_dphi / sum_weight ave_deta2 = sum_deta2 / sum_weight ave_dphi2 = sum_dphi2 / sum_weight a = ave_deta2 - ave_deta * ave_deta b = ave_dphi2 - ave_dphi * ave_dphi c = -(sum_detadphi / sum_weight - ave_deta * ave_dphi) else: jet.ptd = 0. delta = math.sqrt(math.fabs((a - b) * (a - b) + 4. * c * c)) if a + b - delta > 0: jet.axis2 = -math.log(math.sqrt(0.5 * (a + b - delta))) else: jet.axis2 = -1. def jetFlavour(self, event): def isFlavour(x, f): id = abs(x.pdgId()) if id > 999: return (id / 1000) % 10 == f if id > 99: return (id / 100) % 10 == f return id % 100 == f event.bqObjects = [ p for p in event.genParticles if (p.status() == 2 and isFlavour(p, 5)) ] event.cqObjects = [ p for p in event.genParticles if (p.status() == 2 and isFlavour(p, 4)) ] event.partons = [ p for p in event.genParticles if ((p.status() == 23 or p.status() == 3) and abs(p.pdgId()) > 0 and (abs(p.pdgId()) in [1, 2, 3, 4, 5, 21])) ] match = matchObjectCollection2(event.cleanJetsAll, event.partons, deltaRMax=0.3) for jet in event.cleanJetsAll: parton = match[jet] jet.partonId = (parton.pdgId() if parton != None else 0) jet.partonMotherId = (parton.mother(0).pdgId() if parton != None and parton.numberOfMothers() > 0 else 0) for jet in event.jets: (bmatch, dr) = bestMatch(jet, event.bqObjects) if dr < 0.4: jet.mcFlavour = 5 else: (cmatch, dr) = bestMatch(jet, event.cqObjects) if dr < 0.4: jet.mcFlavour = 4 else: jet.mcFlavour = 0 event.heaviestQCDFlavour = 5 if len( event.bqObjects) else (4 if len(event.cqObjects) else 1) def matchJets(self, event, jets): match = matchObjectCollection2(jets, event.genbquarks + event.genwzquarks, deltaRMax=0.3) for jet in jets: gen = match[jet] jet.mcParton = gen jet.mcMatchId = (gen.sourceId if gen != None else 0) jet.mcMatchFlav = (abs(gen.pdgId()) if gen != None else 0) match = matchObjectCollection2(jets, event.genJets, deltaRMax=0.3) for jet in jets: jet.mcJet = match[jet] def smearJets(self, event, jets): # https://twiki.cern.ch/twiki/bin/viewauth/CMS/TWikiTopRefSyst#Jet_energy_resolution for jet in jets: gen = jet.mcJet if gen != None: genpt, jetpt, aeta = gen.pt(), jet.pt(), abs(jet.eta()) # from https://twiki.cern.ch/twiki/bin/view/CMS/JetResolution factor = 1.052 + self.shiftJER * math.hypot(0.012, 0.062) if aeta > 2.3: factor = 1.288 + self.shiftJER * math.hypot(0.127, 0.154) elif aeta > 1.7: factor = 1.134 + self.shiftJER * math.hypot(0.035, 0.066) elif aeta > 1.1: factor = 1.096 + self.shiftJER * math.hypot(0.017, 0.063) elif aeta > 0.5: factor = 1.057 + self.shiftJER * math.hypot(0.012, 0.056) ptscale = max(0.0, (jetpt + (factor - 1) * (jetpt - genpt)) / jetpt) #print "get with pt %.1f (gen pt %.1f, ptscale = %.3f)" % (jetpt,genpt,ptscale) jet.deltaMetFromJetSmearing = [ -(ptscale - 1) * jet.rawFactor() * jet.px(), -(ptscale - 1) * jet.rawFactor() * jet.py() ] if ptscale != 0: jet.setP4(jet.p4() * ptscale) # leave the uncorrected unchanged for sync jet._rawFactorMultiplier *= (1.0 / ptscale) if ptscale != 0 else 1