def arbitrate(self): pi1 = ROOT.Math.LorentzVector('<ROOT::Math::PxPyPzM4D<double> >')( self.tk1_.px(), self.tk1_.py(), self.tk1_.pz(), m_pi_ch) pi2 = ROOT.Math.LorentzVector('<ROOT::Math::PxPyPzM4D<double> >')( self.tk2_.px(), self.tk2_.py(), self.tk2_.pz(), m_pi_ch) k1 = ROOT.Math.LorentzVector('<ROOT::Math::PxPyPzM4D<double> >')( self.tk1_.px(), self.tk1_.py(), self.tk1_.pz(), m_k_ch) k2 = ROOT.Math.LorentzVector('<ROOT::Math::PxPyPzM4D<double> >')( self.tk2_.px(), self.tk2_.py(), self.tk2_.pz(), m_k_ch) # assign the mass hypotheses if abs((pi1 + k2).mass() - m_k_st_zero) < abs((pi2 + k1).mass() - m_k_st_zero): self.pi_ = PhysicsObject( ROOT.pat.PackedCandidate(self.tk1_.physObj)) self.k_ = PhysicsObject(ROOT.pat.PackedCandidate( self.tk2_.physObj)) else: self.pi_ = PhysicsObject( ROOT.pat.PackedCandidate(self.tk2_.physObj)) self.k_ = PhysicsObject(ROOT.pat.PackedCandidate( self.tk1_.physObj)) self.pi_.setMass(m_pi_ch) self.k_.setMass(m_k_ch) self.pi_.setPdgId(self.pi_.charge() * 211) self.k_.setPdgId(self.k_.charge() * 321)
def __init__(self, leg1, leg2, pdgid, status=3, sort_by_pt=False, mass1=-1, mass2=-1): ''' Parameters (stored as attributes): leg1,2 : first and second leg. pdgid : pdg code of the resonance status : status code of the resonance ''' if isinstance(leg1.physObj, ROOT.pat.PackedCandidate): leg1 = PhysicsObject(ROOT.pat.PackedCandidate(leg1.physObj)) if isinstance(leg2.physObj, ROOT.pat.PackedCandidate): leg2 = PhysicsObject(ROOT.pat.PackedCandidate(leg2.physObj)) if sort_by_pt: self.leg1 = leg1 if leg1.pt() >= leg2.pt() else leg2 self.leg2 = leg2 if leg1.pt() >= leg2.pt() else leg1 else: self.leg1 = leg1 self.leg2 = leg2 if mass1>0: self.leg1.setMass(mass1) if mass2>0: self.leg2.setMass(mass2) self._p4 = leg1.p4() + leg2.p4() self._charge = leg1.charge() + leg2.charge() self._pdgid = pdgid self._status = status
def process(self, event): run = event.input.eventAuxiliary().id().run() lumi = event.input.eventAuxiliary().id().luminosityBlock() eventId = event.input.eventAuxiliary().id().event() self.readCollections( event.input ) # Will need who for jet calibration later rho = self.handles["rho"].product()[0] ######## # AK8 Jets from MiniAOD + Subjet btags ######## setattr(event, "ak08", map(PhysicsObject, self.handles["ak08"].product())) setattr(event, "ak0softdropsubjets", map(PhysicsObject, self.handles["ak08softdropsubjets"].product())) # bb-tag Output newtags = self.handles['ak08bbtag'].product() # Loop over jets for ij, jet in enumerate(getattr(event, "ak08")): # Fill bb-tag for i in xrange(len(newtags)) : if jet.physObj == newtags.key(i).get(): jet.bbtag = newtags.value(i) # bb-tag Inputs muonTagInfos = self.handles['ak08muonTagInfos'].product()[ij] elecTagInfos = self.handles['ak08elecTagInfos'].product()[ij] ipTagInfo = self.handles['ak08ipTagInfos'].product()[ij] svTagInfo = self.handles['ak08svTagInfos'].product()[ij] calcBBTagVariables(jet, muonTagInfos, elecTagInfos, ipTagInfo, svTagInfo, njettiness_08, maxSVDeltaRToJet = 0.7,) # end of loop over jets ######## # Ungroomed Fatjets + NSubjettiness + Hbb Tagging ######## for prefix in ["ca15"]: if self.skip_ca15 and ("ca15" in prefix): continue # N-Subjettiness tau1 = self.handles[prefix+'tau1'].product() tau2 = self.handles[prefix+'tau2'].product() tau3 = self.handles[prefix+'tau3'].product() # bb-tag Output newtags = self.handles[prefix+'bbtag'].product() # Four Vector setattr(event, prefix+"ungroomed", map(PhysicsObject, self.handles[prefix+'ungroomed'].product())) # Loop over jets for ij, jet in enumerate(getattr(event, prefix+"ungroomed")): # Fill N-Subjettiness jet.tau1 = tau1.get(ij) jet.tau2 = tau2.get(ij) jet.tau3 = tau3.get(ij) # Fill bb-tag for i in xrange(len(newtags)) : if jet.physObj == newtags.key(i).get(): jet.bbtag = newtags.value(i) # bb-tag Inputs muonTagInfos = self.handles['ca15muonTagInfos'].product()[ij] elecTagInfos = self.handles['ca15elecTagInfos'].product()[ij] ipTagInfo = self.handles['ca15ipTagInfos'].product()[ij] svTagInfo = self.handles['ca15svTagInfos'].product()[ij] calcBBTagVariables(jet, muonTagInfos, elecTagInfos, ipTagInfo, svTagInfo, njettiness_15, maxSVDeltaRToJet = 1.3) # end of loop over jets ######## # Softdrop Fatjets + NSubjettiness ######## for fj_name in ["ca15softdropz2b1"]: if self.skip_ca15 and ("ca15" in fj_name): continue # Set the four-vector setattr(event, fj_name, map(PhysicsObject, self.handles[fj_name].product())) # N-Subjettiness tau1 = self.handles[fj_name+'tau1'].product() tau2 = self.handles[fj_name+'tau2'].product() tau3 = self.handles[fj_name+'tau3'].product() # Loop over jets for ij, jet in enumerate(getattr(event, fj_name)): # Fill N-Subjettiness jet.tau1 = tau1.get(ij) jet.tau2 = tau2.get(ij) jet.tau3 = tau3.get(ij) # end of loop over jets ######## # Groomed Uncalibrated Fatjets ######## for fj_name in ['ak08pruned', 'ca15trimmed', 'ca15softdrop', 'ca15pruned']: if self.skip_ca15 and ("ca15" in fj_name): continue setattr(event, fj_name, map(PhysicsObject, self.handles[fj_name].product())) ######## # Groomed Fatjets to calibrate ######## pruned_cal_jets = [] for groomed_fj in self.handles['ak08pruned'].product(): # We need the closest ungroomed fatjet to get the JEC: # - Make a list of pairs: deltaR(ungroomed fj, groomed fj) for all ungroomed fatjets # - Sort by deltaR # - And take the minimum if len(getattr(event, "ak08")): closest_ung_fj_and_dr = sorted( [(ung_fj, deltaR2(ung_fj, groomed_fj)) for ung_fj in getattr(event, "ak08")], key=lambda x:x[1])[0] else: print "WARNING: No ungroomed fatjets found in event with groomed fatjet. Skipping" continue # Use the jet cone size for matching minimal_dr_groomed_ungroomed = 0.8 if closest_ung_fj_and_dr[1] > minimal_dr_groomed_ungroomed: print "WARNING: No ungroomed fatjet found close to groomed fatjet. Skipping" continue ungroomed_jet = Jet(closest_ung_fj_and_dr[0]) c = self.jetReCalibrator.getCorrection(ungroomed_jet, rho) # Need to do a deep-copy. Otherwise the original jet will be modified cal_groomed_fj = PhysicsObject(groomed_fj).__copy__() cal_groomed_fj.scaleEnergy(c) pruned_cal_jets.append(cal_groomed_fj) setattr(event, 'ak08prunedcal', pruned_cal_jets) ######## # AK08 Regression ####### self.regressionsAK08[0].evaluateRegressionAK08(event) ######## # Subjets ######## for fj_name in ['ak08pruned','ca15pruned']: if self.skip_ca15 and ("ca15" in fj_name): continue setattr(event, fj_name + "subjets", map(PhysicsObject, self.handles[fj_name+"subjets"].product())) newtags = self.handles[fj_name+'subjetbtag'].product() for i in xrange(0,len(newtags)) : for j in getattr(event, fj_name+"subjets"): if j.physObj == newtags.key(i).get(): j.btag = newtags.value(i) ######## # HEPTopTagger ######## if not self.skip_ca15: candJets = self.handles['httCandJets'].product() candInfos = self.handles['httCandInfos'].product() event.httCandidates = map(PhysicsObject, candJets) sjbtags = self.handles['httSubjetBtags'].product() for i in xrange(0, len(candJets)): event.httCandidates[i].fRec = candInfos[i].properties().fRec event.httCandidates[i].Ropt = candInfos[i].properties().Ropt event.httCandidates[i].RoptCalc = candInfos[i].properties().RoptCalc event.httCandidates[i].ptForRoptCalc = candInfos[i].properties().ptForRoptCalc # HTT return the subjet-pair closest to the W-mass as W-subjets # Could be improved by b-tagging if we run into a problem [sj_w1, sj_w2, sj_nonw] = [con.__deref__() for con in candJets[i].getJetConstituents() if not con.isNull()] event.httCandidates[i].sjW1pt = sj_w1.pt() event.httCandidates[i].sjW1eta = sj_w1.eta() event.httCandidates[i].sjW1phi = sj_w1.phi() event.httCandidates[i].sjW1mass = sj_w1.mass() # Get the correct b-tag for ib in xrange(0, len(sjbtags)) : if sj_w1 == sjbtags.key(ib).get(): event.httCandidates[i].sjW1btag = sjbtags.value(ib) event.httCandidates[i].sjW2pt = sj_w2.pt() event.httCandidates[i].sjW2eta = sj_w2.eta() event.httCandidates[i].sjW2phi = sj_w2.phi() event.httCandidates[i].sjW2mass = sj_w2.mass() # Get the correct b-tag for ib in xrange(0, len(sjbtags)) : if sj_w2 == sjbtags.key(ib).get(): event.httCandidates[i].sjW2btag = sjbtags.value(ib) event.httCandidates[i].sjNonWpt = sj_nonw.pt() event.httCandidates[i].sjNonWeta = sj_nonw.eta() event.httCandidates[i].sjNonWphi = sj_nonw.phi() event.httCandidates[i].sjNonWmass = sj_nonw.mass() # Get the correct b-tag for ib in xrange(0, len(sjbtags)) : if sj_nonw == sjbtags.key(ib).get(): event.httCandidates[i].sjNonWbtag = sjbtags.value(ib) return True
def evaluateRegressionAK08(self, event): #self.readCollections( event.input ) reg_fj = [] for ung_fj in getattr(event, "ak08"): # We need the closest ungroomed fatjet to get the JEC: # - Make a list of pairs: deltaR(ungroomed fj, groomed fj) for all ungroomed fatjets # - Sort by deltaR # - And take the minimum if len(getattr(event, "ak08pruned")): closest_pr_fj_and_dr = sorted( [(pr_fj, deltaR2(ung_fj, pr_fj)) for pr_fj in getattr(event, "ak08pruned")], key=lambda x:x[1])[0] else: print "WARNING: No pruned fatjets found in event with ungroomed fatjet. Skipping" continue # Use the jet cone size for matching minimal_dr_groomed_ungroomed = 0.8 if closest_pr_fj_and_dr[1] > minimal_dr_groomed_ungroomed: print "WARNING: No pruned fatjet found close to ungroomed fatjet. Skipping" continue pr_jet = Jet(closest_pr_fj_and_dr[0]) if len(getattr(event, "ak08prunedcal")): closest_cal_fj_and_dr = sorted( [(cal_fj, deltaR2(ung_fj, cal_fj)) for cal_fj in getattr(event, "ak08prunedcal")], key=lambda x:x[1])[0] else: print "WARNING: No calib groomed fatjets found in event with ungroomed fatjet. Skipping" continue if closest_cal_fj_and_dr[1] > minimal_dr_groomed_ungroomed: print "WARNING: No calib fatjet found close to ungroomed fatjet. Skipping" continue cal_jet = Jet(closest_cal_fj_and_dr[0]) # now check the AK08 jet is not a lepton # if len(getattr(event, "selectedLeptons")): # closest_pr_lep_and_dr = sorted( [(lep, deltaR2(cal_jet,lep)) for lep in getattr(event, "vLeptons")], key=lambda x:x[1])[0] # if closest_pr_lep_and_dr[1] < (0.4 * 0.4): # print "WARNING: No groomed fatjet is overlapping with a vLepton. Skipping" # continue # Need to do a deep-copy. Otherwise the original jet will be modified reg_groomed_fj = PhysicsObject(closest_cal_fj_and_dr[0]).__copy__() # for j in event.FatjetAK08pruned: self.FatjetAK08ungroomed_pt[0] = ung_fj.pt() # print 'ung_fj.pt() ', ung_fj.pt() self.FatjetAK08pruned_pt[0] = pr_jet.pt() # print 'pr_jet.pt() ', pr_jet.pt() self.FatjetAK08prunedCal_pt[0] = cal_jet.pt() # print 'cal_jet.pt() ', cal_jet.pt() self.FatjetAK08prunedCal_eta[0] = cal_jet.eta() self.FatjetAK08ungroomed_vertexNTracks[0] = ung_fj.vertexNTracks self.FatjetAK08ungroomed_SV_mass_0[0] = ung_fj.SV_mass_0 self.FatjetAK08ungroomed_SV_EnergyRatio_0[0] = ung_fj.SV_EnergyRatio_0 self.FatjetAK08ungroomed_SV_EnergyRatio_1[0] = ung_fj.SV_EnergyRatio_1 self.FatjetAK08ungroomed_PFLepton_ptrel[0] = ung_fj.PFLepton_ptrel self.FatjetAK08ungroomed_nSL[0] = ung_fj.nSL # print 'ung_fj.nSL ', ung_fj.nSL reg_groomed_fj.scaleEnergy(self.reader.EvaluateRegression(self.name)[0]) reg_fj.append(reg_groomed_fj) # print 'reg_groomed_fj.pt() ', reg_groomed_fj.pt() setattr(event, 'ak08prunedreg', reg_fj )
def genMatch(event, leg, ptSelGentauleps, ptSelGenleps, ptSelGenSummary, dR=0.2, matchAll=True): dR2 = dR * dR leg.isTauHad = False leg.isTauLep = False leg.isPromptLep = False leg.genp = None best_dr2 = dR2 # if hasattr(leg, 'genJet') and leg.genJet(): # if leg.genJet().pt() > 15.: # dr2 = deltaR2(leg.eta(), leg.phi(), leg.genJet().eta(), leg.genJet().phi()) # if dr2 < best_dr2: # best_dr2 = dr2 # leg.genp = leg.genJet() # leg.genp.setPdgId(-15 * leg.genp.charge()) # leg.isTauHad = True l1match, dR2best = bestMatch(leg, event.genTauJets) if dR2best < best_dr2: best_dr2 = dR2best leg.genp = GenParticle(l1match) leg.genp.setPdgId(-15 * leg.genp.charge()) leg.isTauHad = True # to generated leptons from taus l1match, dR2best = bestMatch(leg, ptSelGentauleps) if dR2best < best_dr2: best_dr2 = dR2best leg.genp = l1match leg.isTauLep = True leg.isTauHad = False # to generated prompt leptons l1match, dR2best = bestMatch(leg, ptSelGenleps) if dR2best < best_dr2: best_dr2 = dR2best leg.genp = l1match leg.isPromptLep = True leg.isTauLep = False leg.isTauHad = False if best_dr2 < dR2: return # match with any other relevant gen particle if matchAll: l1match, dR2best = bestMatch(leg, ptSelGenSummary) if dR2best < best_dr2: leg.genp = l1match return # Ok do one more Pythia 8 trick... # This is to overcome that the GenAnalyzer doesn't like particles # that have daughters with same pdgId and status 71 if not hasattr(event, 'pythiaQuarksGluons'): event.pythiaQuarksGluons = [] for gen in event.genParticles: pdg = abs(gen.pdgId()) status = gen.status() if pdg in [1, 2, 3, 4, 5, 21] and status > 3: if gen.isMostlyLikePythia6Status3(): event.pythiaQuarksGluons.append(gen) l1match, dR2best = bestMatch(leg, event.pythiaQuarksGluons) if dR2best < best_dr2: leg.genp = l1match return # Now this may be a pileup lepton, or one whose ancestor doesn't # appear in the gen summary because it's an unclear case in Pythia 8 # To check the latter, match against jets as well... l1match, dR2best = bestMatch(leg, event.genJets) # Check if there's a gen jet with pT > 10 GeV (otherwise it's PU) if dR2best < dR2 and l1match.pt() > 10.: leg.genp = PhysicsObject(l1match) jet, dR2best = bestMatch(l1match, event.jets) if dR2best < dR2: leg.genp.detFlavour = jet.partonFlavour() else: print 'no match found', leg.pt(), leg.eta()
def genMatch(event, leg, ptSelGentauleps, ptSelGenleps, ptSelGenSummary, dR=0.2, matchAll=True): dR2 = dR * dR leg.isTauHad = False leg.isTauLep = False leg.isPromptLep = False leg.genp = None best_dr2 = dR2 # The following would work for pat::Taus, but we also want to flag a # muon/electron as coming from a hadronic tau with the usual definition # if this happens # if hasattr(leg, 'genJet') and leg.genJet(): # if leg.genJet().pt() > 15.: # dr2 = deltaR2(leg.eta(), leg.phi(), leg.genJet().eta(), leg.genJet().phi()) # if dr2 < best_dr2: # best_dr2 = dr2 # leg.genp = leg.genJet() # leg.genp.setPdgId(-15 * leg.genp.charge()) # leg.isTauHad = True # RM: needed to append genTauJets to the events, # when genMatch is used as a static method if not hasattr(event, 'genTauJets'): HTTGenAnalyzer.getGenTauJets(event) l1match, dR2best = bestMatch(leg, event.genTauJets) if dR2best < best_dr2: best_dr2 = dR2best # leg.genp = GenParticle(l1match) leg.genp = l1match leg.genp.setPdgId(-15 * leg.genp.charge()) leg.isTauHad = True # if not leg.genJet(): # print 'Warning, tau does not have matched gen tau' # elif leg.genJet().pt() < 15.: # print 'Warning, tau has matched gen jet but with pt =', leg.genJet().pt() # to generated leptons from taus l1match, dR2best = bestMatch(leg, ptSelGentauleps) if dR2best < best_dr2: best_dr2 = dR2best leg.genp = l1match leg.isTauLep = True leg.isTauHad = False # to generated prompt leptons l1match, dR2best = bestMatch(leg, ptSelGenleps) if dR2best < best_dr2: best_dr2 = dR2best leg.genp = l1match leg.isPromptLep = True leg.isTauLep = False leg.isTauHad = False if best_dr2 < dR2: return # match with any other relevant gen particle if matchAll: l1match, dR2best = bestMatch(leg, ptSelGenSummary) if dR2best < best_dr2: leg.genp = l1match return # Ok do one more Pythia 8 trick... # This is to overcome that the GenAnalyzer doesn't like particles # that have daughters with same pdgId and status 71 if not hasattr(event, 'pythiaQuarksGluons'): event.pythiaQuarksGluons = [] for gen in event.genParticles: pdg = abs(gen.pdgId()) status = gen.status() if pdg in [1, 2, 3, 4, 5, 21] and status > 3: if gen.isMostlyLikePythia6Status3(): event.pythiaQuarksGluons.append(gen) l1match, dR2best = bestMatch(leg, event.pythiaQuarksGluons) if dR2best < best_dr2: leg.genp = l1match return # Now this may be a pileup lepton, or one whose ancestor doesn't # appear in the gen summary because it's an unclear case in Pythia 8 # To check the latter, match against jets as well... l1match, dR2best = bestMatch(leg, getattr(event, 'genJets', [])) # Check if there's a gen jet with pT > 10 GeV (otherwise it's PU) if dR2best < dR2 and l1match.pt() > 10.: leg.genp = PhysicsObject(l1match) jet, dR2best = bestMatch(l1match, event.jets) if dR2best < dR2: leg.genp.detFlavour = jet.partonFlavour() else: print 'no match found', leg.pt(), leg.eta()
def evaluateRegressionAK08(self, event): #self.readCollections( event.input ) reg_fj = [] for ung_fj in getattr(event, "ak08"): # We need the closest ungroomed fatjet to get the JEC: # - Make a list of pairs: deltaR(ungroomed fj, groomed fj) for all ungroomed fatjets # - Sort by deltaR # - And take the minimum if len(getattr(event, "ak08pruned")): closest_pr_fj_and_dr = sorted( [(pr_fj, deltaR2(ung_fj, pr_fj)) for pr_fj in getattr(event, "ak08pruned")], key=lambda x: x[1])[0] else: print "WARNING: No pruned fatjets found in event with ungroomed fatjet. Skipping" continue # Use the jet cone size for matching minimal_dr_groomed_ungroomed = 0.8 if closest_pr_fj_and_dr[1] > minimal_dr_groomed_ungroomed: print "WARNING: No pruned fatjet found close to ungroomed fatjet. Skipping" continue pr_jet = Jet(closest_pr_fj_and_dr[0]) if len(getattr(event, "ak08prunedcal")): closest_cal_fj_and_dr = sorted( [(cal_fj, deltaR2(ung_fj, cal_fj)) for cal_fj in getattr(event, "ak08prunedcal")], key=lambda x: x[1])[0] else: print "WARNING: No calib groomed fatjets found in event with ungroomed fatjet. Skipping" continue if closest_cal_fj_and_dr[1] > minimal_dr_groomed_ungroomed: print "WARNING: No calib fatjet found close to ungroomed fatjet. Skipping" continue cal_jet = Jet(closest_cal_fj_and_dr[0]) # now check the AK08 jet is not a lepton # if len(getattr(event, "selectedLeptons")): # closest_pr_lep_and_dr = sorted( [(lep, deltaR2(cal_jet,lep)) for lep in getattr(event, "vLeptons")], key=lambda x:x[1])[0] # if closest_pr_lep_and_dr[1] < (0.4 * 0.4): # print "WARNING: No groomed fatjet is overlapping with a vLepton. Skipping" # continue # Need to do a deep-copy. Otherwise the original jet will be modified reg_groomed_fj = PhysicsObject(closest_cal_fj_and_dr[0]).__copy__() # for j in event.FatjetAK08pruned: self.FatjetAK08ungroomed_pt[0] = ung_fj.pt() # print 'ung_fj.pt() ', ung_fj.pt() self.FatjetAK08pruned_pt[0] = pr_jet.pt() # print 'pr_jet.pt() ', pr_jet.pt() self.FatjetAK08prunedCal_pt[0] = cal_jet.pt() # print 'cal_jet.pt() ', cal_jet.pt() self.FatjetAK08prunedCal_eta[0] = cal_jet.eta() self.FatjetAK08ungroomed_vertexNTracks[0] = ung_fj.vertexNTracks self.FatjetAK08ungroomed_SV_mass_0[0] = ung_fj.SV_mass_0 self.FatjetAK08ungroomed_SV_EnergyRatio_0[ 0] = ung_fj.SV_EnergyRatio_0 self.FatjetAK08ungroomed_SV_EnergyRatio_1[ 0] = ung_fj.SV_EnergyRatio_1 self.FatjetAK08ungroomed_PFLepton_ptrel[0] = ung_fj.PFLepton_ptrel self.FatjetAK08ungroomed_nSL[0] = ung_fj.nSL # print 'ung_fj.nSL ', ung_fj.nSL reg_groomed_fj.scaleEnergy( self.reader.EvaluateRegression(self.name)[0]) reg_fj.append(reg_groomed_fj) # print 'reg_groomed_fj.pt() ', reg_groomed_fj.pt() setattr(event, 'ak08prunedreg', reg_fj)
def process(self, event): run = event.input.eventAuxiliary().id().run() lumi = event.input.eventAuxiliary().id().luminosityBlock() eventId = event.input.eventAuxiliary().id().event() self.readCollections( event.input ) # Will need who for jet calibration later rho = self.handles["rho"].product()[0] ######## # Softdrop Fatjets + NSubjettiness ######## for fj_name in ["ca15softdropz2b1"]: if self.skip_ca15 and ("ca15" in fj_name): continue # Set the four-vector setattr(event, fj_name, map(PhysicsObject, self.handles[fj_name].product())) # N-Subjettiness tau1 = self.handles[fj_name+'tau1'].product() tau2 = self.handles[fj_name+'tau2'].product() tau3 = self.handles[fj_name+'tau3'].product() # Loop over jets for ij, jet in enumerate(getattr(event, fj_name)): # Fill N-Subjettiness jet.tau1 = tau1.get(ij) jet.tau2 = tau2.get(ij) jet.tau3 = tau3.get(ij) # end of loop over jets ######## # Groomed Uncalibrated Fatjets ######## for fj_name in ['ca15trimmed', 'ca15softdrop', 'ca15pruned']: setattr(event, fj_name, map(PhysicsObject, self.handles[fj_name].product())) # # ######## # # Groomed Fatjets to calibrate # ######## # # pruned_cal_jets = [] # # for groomed_fj in self.handles['ak08pruned'].product(): # # # We need the closest ungroomed fatjet to get the JEC: # # - Make a list of pairs: deltaR(ungroomed fj, groomed fj) for all ungroomed fatjets # # - Sort by deltaR # # - And take the minimum # # if len(getattr(event, "ak08")): # closest_ung_fj_and_dr = sorted( # [(ung_fj, deltaR2(ung_fj, groomed_fj)) for ung_fj in getattr(event, "ak08")], # key=lambda x:x[1])[0] # else: # print "WARNING: No ungroomed fatjets found in event with groomed fatjet. Skipping" # continue # # # Use the jet cone size for matching # minimal_dr_groomed_ungroomed = 0.8 # if closest_ung_fj_and_dr[1] > minimal_dr_groomed_ungroomed: # print "WARNING: No ungroomed fatjet found close to groomed fatjet. Skipping" # continue # # ungroomed_jet = Jet(closest_ung_fj_and_dr[0]) # # c = self.jetReCalibratorAK8L2L3.getCorrection(ungroomed_jet, rho) # # # # Need to do a deep-copy. Otherwise the original jet will be modified # cal_groomed_fj = PhysicsObject(groomed_fj).__copy__() # cal_groomed_fj.scaleEnergy(c) # # pruned_cal_jets.append(cal_groomed_fj) # # setattr(event, 'ak08prunedcal', pruned_cal_jets) # ######## # Subjets ######## for fj_name in ['ca15pruned']: if self.skip_ca15 and ("ca15" in fj_name): continue setattr(event, fj_name + "subjets", map(PhysicsObject, self.handles[fj_name+"subjets"].product())) newtags = self.handles[fj_name+'subjetbtag'].product() for i in xrange(0,len(newtags)) : for j in getattr(event, fj_name+"subjets"): if j.physObj == newtags.key(i).get(): j.btag = newtags.value(i) ######## # HEPTopTagger ######## if not self.skip_ca15: candJets = self.handles['httCandJets'].product() candInfos = self.handles['httCandInfos'].product() event.httCandidates = map(PhysicsObject, candJets) sjbtags = self.handles['httSubjetBtags'].product() for i in xrange(0, len(candJets)): event.httCandidates[i].fRec = candInfos[i].properties().fRec event.httCandidates[i].Ropt = candInfos[i].properties().Ropt event.httCandidates[i].RoptCalc = candInfos[i].properties().RoptCalc event.httCandidates[i].ptForRoptCalc = candInfos[i].properties().ptForRoptCalc # HTT return the subjet-pair closest to the W-mass as W-subjets # Could be improved by b-tagging if we run into a problem [sj_w1, sj_w2, sj_nonw] = [con.__deref__() for con in candJets[i].getJetConstituents() if not con.isNull()] # Calibrate the subjets: W1 sj_w1_uncal = Jet(sj_w1) c = self.jetReCalibratorAK4.getCorrection(sj_w1_uncal, rho, isHttSubjet=True) sj_w1_cal = PhysicsObject(sj_w1).__copy__() sj_w1_cal.scaleEnergy(c) # Calibrate the subjets: W2 sj_w2_uncal = Jet(sj_w2) c = self.jetReCalibratorAK4.getCorrection(sj_w2_uncal, rho, isHttSubjet=True) sj_w2_cal = PhysicsObject(sj_w2).__copy__() sj_w2_cal.scaleEnergy(c) # Calibrate the subjets: NonW sj_nonw_uncal = Jet(sj_nonw) c = self.jetReCalibratorAK4.getCorrection(sj_nonw_uncal, rho, isHttSubjet=True) sj_nonw_cal = PhysicsObject(sj_nonw).__copy__() sj_nonw_cal.scaleEnergy(c) # Make TLVs so we can add them and get the top quark # candidate tlv_sj_w1_cal = ROOT.TLorentzVector() tlv_sj_w2_cal = ROOT.TLorentzVector() tlv_sj_nonw_cal = ROOT.TLorentzVector() tlv_sj_w1_cal.SetPtEtaPhiM(sj_w1_cal.pt(), sj_w1_cal.eta(), sj_w1_cal.phi(), sj_w1_cal.mass()) tlv_sj_w2_cal.SetPtEtaPhiM(sj_w2_cal.pt(), sj_w2_cal.eta(), sj_w2_cal.phi(), sj_w2_cal.mass()) tlv_sj_nonw_cal.SetPtEtaPhiM(sj_nonw_cal.pt(), sj_nonw_cal.eta(), sj_nonw_cal.phi(), sj_nonw_cal.mass()) tlv_top_cal = tlv_sj_w1_cal + tlv_sj_w2_cal + tlv_sj_nonw_cal # Store calibrated top candidate variables event.httCandidates[i].ptcal = tlv_top_cal.Pt() event.httCandidates[i].etacal = tlv_top_cal.Eta() event.httCandidates[i].phical = tlv_top_cal.Phi() event.httCandidates[i].masscal = tlv_top_cal.M() # Store SJ W1 Variables event.httCandidates[i].sjW1ptcal = sj_w1_cal.pt() event.httCandidates[i].sjW1masscal = sj_w1_cal.mass() event.httCandidates[i].sjW1pt = sj_w1.pt() event.httCandidates[i].sjW1eta = sj_w1.eta() event.httCandidates[i].sjW1phi = sj_w1.phi() event.httCandidates[i].sjW1mass = sj_w1.mass() # Get the correct b-tag for ib in xrange(0, len(sjbtags)) : if sj_w1 == sjbtags.key(ib).get(): event.httCandidates[i].sjW1btag = sjbtags.value(ib) # Store SJ W2 Variables event.httCandidates[i].sjW2ptcal = sj_w2_cal.pt() event.httCandidates[i].sjW2masscal = sj_w2_cal.mass() event.httCandidates[i].sjW2pt = sj_w2.pt() event.httCandidates[i].sjW2eta = sj_w2.eta() event.httCandidates[i].sjW2phi = sj_w2.phi() event.httCandidates[i].sjW2mass = sj_w2.mass() # Get the correct b-tag for ib in xrange(0, len(sjbtags)) : if sj_w2 == sjbtags.key(ib).get(): event.httCandidates[i].sjW2btag = sjbtags.value(ib) # Store SJ Non W Variables event.httCandidates[i].sjNonWptcal = sj_nonw_cal.pt() event.httCandidates[i].sjNonWmasscal = sj_nonw_cal.mass() event.httCandidates[i].sjNonWpt = sj_nonw.pt() event.httCandidates[i].sjNonWeta = sj_nonw.eta() event.httCandidates[i].sjNonWphi = sj_nonw.phi() event.httCandidates[i].sjNonWmass = sj_nonw.mass() # Get the correct b-tag for ib in xrange(0, len(sjbtags)) : if sj_nonw == sjbtags.key(ib).get(): event.httCandidates[i].sjNonWbtag = sjbtags.value(ib) ######## # AK8 Jets from MiniAOD + Subjet btags ######## setattr(event, "ak08", map(PhysicsObject, self.handles["ak08"].product())) setattr(event, "ak08softdropsubjets", map(PhysicsObject, self.handles["ak08softdropsubjets"].product())) do_calc_bb = False # Calc BB tag # -- if there is a HTT candidate and at least one lepton if len(event.selectedLeptons): for cand in event.httCandidates: if cand.fRec < 0.2 and cand.mass() > 100 and cand.mass() < 200: do_calc_bb = True # -- or if there are at least two fatjets with pT > 250 GeV and the scalar sum of the jet pTs is > 600 fj_pt250 = [j for j in event.ak08 if j.pt() > 250] if len(fj_pt250) >= 2 and sum([j.pt() for j in fj_pt250]) > 600: do_calc_bb = True # bb-tag Output newtags = self.handles['ak08bbtag'].product() # Loop over jets for ij, jet in enumerate(getattr(event, "ak08")): # Fill bb-tag for i in xrange(len(newtags)) : if jet.physObj == newtags.key(i).get(): jet.bbtag = newtags.value(i) corr = self.jetReCalibratorAK8L2L3.getCorrection(Jet(jet),rho) jet.mprunedcorr= jet.userFloat("ak8PFJetsCHSPrunedMass")*corr jet.JEC_L2L3 = corr jet.JEC_L1L2L3 = self.jetReCalibratorAK8L1L2L3.getCorrection(Jet(jet),rho) # bb-tag Inputs muonTagInfos = self.handles['ak08muonTagInfos'].product()[ij] elecTagInfos = self.handles['ak08elecTagInfos'].product()[ij] ipTagInfo = self.handles['ak08ipTagInfos'].product()[ij] svTagInfo = self.handles['ak08svTagInfos'].product()[ij] orig_jet = self.handles["ak08"].product()[ij] if do_calc_bb: calcBBTagVariables(jet, orig_jet, muonTagInfos, elecTagInfos, ipTagInfo, svTagInfo, njettiness_08, maxSVDeltaRToJet = 0.7,) else: calcBBTagVariables_dummy(jet) # end of loop over jets ######## # Ungroomed Fatjets + NSubjettiness + Hbb Tagging ######## for prefix in ["ca15"]: if self.skip_ca15 and ("ca15" in prefix): continue # N-Subjettiness tau1 = self.handles[prefix+'tau1'].product() tau2 = self.handles[prefix+'tau2'].product() tau3 = self.handles[prefix+'tau3'].product() # bb-tag Output newtags = self.handles[prefix+'bbtag'].product() # Four Vector setattr(event, prefix+"ungroomed", map(PhysicsObject, self.handles[prefix+'ungroomed'].product())) # Loop over jets for ij, jet in enumerate(getattr(event, prefix+"ungroomed")): # Fill N-Subjettiness jet.tau1 = tau1.get(ij) jet.tau2 = tau2.get(ij) jet.tau3 = tau3.get(ij) # Fill bb-tag for i in xrange(len(newtags)) : if jet.physObj == newtags.key(i).get(): jet.bbtag = newtags.value(i) # bb-tag Inputs muonTagInfos = self.handles['ca15muonTagInfos'].product()[ij] elecTagInfos = self.handles['ca15elecTagInfos'].product()[ij] ipTagInfo = self.handles['ca15ipTagInfos'].product()[ij] svTagInfo = self.handles['ca15svTagInfos'].product()[ij] orig_jet = self.handles[prefix+'ungroomed'].product()[ij] if do_calc_bb: calcBBTagVariables(jet, orig_jet, muonTagInfos, elecTagInfos, ipTagInfo, svTagInfo, njettiness_15, maxSVDeltaRToJet = 1.3) else: calcBBTagVariables_dummy(jet) # end of loop over jets return True
class Kst(object): ''' Builds a K*(892) candidate out of two tracks. Assigns \pi and K mass hypothesis, find the assignment that returns the invariant mass closer to the nominal K*(892) mass. As an option, it can be required that the two tracks make a vertex. ''' def __init__(self, tk1, tk2, requireVtx=False): self.tk1_ = tk1 self.tk2_ = tk2 self.arbitrate() self.vtx = None self.vtxprob = -99. if requireVtx: # stuff I need to instantiate only once self.vtxfit = VertexFitter() # create a std::vector<reco::Track> to be passed to the fitter self.tofit = ROOT.std.vector('reco::Track')() # fill the vector self.tofit.push_back(self.tk1_.physObj) self.tofit.push_back(self.tk2_.physObj) # fit the vertex and save the information self.makeVtx_() def makeVtx_(self): # fit it! svtree = self.vtxfit.Fit(self.tofit) # actual vertex fitting # check that the vertex is good if not svtree.get().isEmpty() and svtree.get().isValid(): svtree.movePointerToTheTop() sv = svtree.currentDecayVertex().get() recoSv = makeRecoVertex( sv, kinVtxTrkSize=2) # need to do some gymastics self.vtx = recoSv self.vtxprob = ROOT.TMath.Prob(self.vtx.chi2(), int(self.vtx().ndof())) def arbitrate(self): pi1 = ROOT.Math.LorentzVector('<ROOT::Math::PxPyPzM4D<double> >')( self.tk1_.px(), self.tk1_.py(), self.tk1_.pz(), m_pi_ch) pi2 = ROOT.Math.LorentzVector('<ROOT::Math::PxPyPzM4D<double> >')( self.tk2_.px(), self.tk2_.py(), self.tk2_.pz(), m_pi_ch) k1 = ROOT.Math.LorentzVector('<ROOT::Math::PxPyPzM4D<double> >')( self.tk1_.px(), self.tk1_.py(), self.tk1_.pz(), m_k_ch) k2 = ROOT.Math.LorentzVector('<ROOT::Math::PxPyPzM4D<double> >')( self.tk2_.px(), self.tk2_.py(), self.tk2_.pz(), m_k_ch) # assign the mass hypotheses if abs((pi1 + k2).mass() - m_k_st_zero) < abs((pi2 + k1).mass() - m_k_st_zero): self.pi_ = PhysicsObject( ROOT.pat.PackedCandidate(self.tk1_.physObj)) self.k_ = PhysicsObject(ROOT.pat.PackedCandidate( self.tk2_.physObj)) else: self.pi_ = PhysicsObject( ROOT.pat.PackedCandidate(self.tk2_.physObj)) self.k_ = PhysicsObject(ROOT.pat.PackedCandidate( self.tk1_.physObj)) self.pi_.setMass(m_pi_ch) self.k_.setMass(m_k_ch) self.pi_.setPdgId(self.pi_.charge() * 211) self.k_.setPdgId(self.k_.charge() * 321) def charge(self): return self.tk1_.charge() + self.tk2_.charge() def pi(self): return self.pi_ def k(self): return self.k_ def p4(self): return self.pi().p4() + self.k().p4() def mass(self): return self.p4().mass() def eta(self): return self.p4().eta() def phi(self): return self.p4().phi() def e(self): return self.p4().e() def pt(self): return self.p4().pt() def p(self): return math.sqrt(self.p4().px()**2 + self.p4().py()**2 + self.p4().pz()**2) def px(self): return self.p4().px() def py(self): return self.p4().py() def pz(self): return self.p4().pz() def pdgId(): # FIXME! get the correct pdgId based on the kaon an pion charges return 313 if self.k().charge() > 0 else -313