def pt_wrt_axis(axis, particles): """Transverse momentum of a set of particles wrt to a given axis. axis must be a TVector3 object, particles must be a list of particle objects """ total_momentum = TLorentzVector(0, 0, 0, 0) for particle in particles: total_momentum += particle.p4() return total_momentum.Perp(axis)
def analyze(self, event): # Get Jet and Muon collections jet = Collection(event, 'Jet') muon = Collection(event, 'Muon') trigObj = Collection(event, 'TrigObj') #### Construct the trigger object collection containing muons triggering a single iso muon trigger selTrigObj = [] for tr in trigObj: if not abs(tr.id) == 13: continue #print 'Trig muon found! with filterBits: ', tr.filterBits if not (bool(tr.filterBits & 2) or bool(tr.filterBits & 8)): continue t = TLorentzVector() t.SetPtEtaPhiM(tr.pt, tr.eta, tr.phi, 0.105) selTrigObj.append(t) #print 'len(selTrigObj) = ', len(selTrigObj) #### Selection of tag and probe muons # Tag: pT, eta, tightId, iso # Probe: pT, eta tags = [] probes = [] pair = [] index = 0 for mu in muon: if not abs(mu.eta) < 2.4 or not mu.pt > self.kProbePt: index += 1 continue if mu.pt > self.kTagPt and mu.tightId and mu.pfRelIso04_all < self.kTagIso: tp = TLorentzVector() tp.SetPtEtaPhiM(mu.pt, mu.eta, mu.phi, mu.mass) if self.IsMatched(tp, selTrigObj): tags.append(index) else: probes.append(index) index += 1 if len(tags) == 0: return False if len(tags) + len(probes) < 2: return False ### Forming TnP pairs with leptons passing Tag selection ### If two tight muons, you have two TnP pairs! ### If one tag has more than one probe candidate, the pairs are not selected for t1 in tags: nProbesFound = 0 tp1 = TLorentzVector() tp1.SetPtEtaPhiM(muon[t1].pt, muon[t1].eta, muon[t1].phi, muon[t1].mass) for t2 in tags: if t2 == t1: continue tp2 = TLorentzVector() tp2.SetPtEtaPhiM(muon[t2].pt, muon[t2].eta, muon[t2].phi, muon[t2].mass) mass = (tp1 + tp2).M() if mass > self.kMaxMass or mass < self.kMinMass: continue ### The tag must match a trigger object: if nProbesFound == 0: nProbesFound += 1 pair.append([t1, t2]) else: # This tag has 2 or more probes!! pair = pair[:-1] ### Forming TnP pairs with a Tag lepton and Probe leptons for t in tags: nProbesFound = 0 tp = TLorentzVector() tp.SetPtEtaPhiM(muon[t].pt, muon[t].eta, muon[t].phi, muon[t].mass) for p in probes: pp = TLorentzVector() pp.SetPtEtaPhiM(muon[p].pt, muon[p].eta, muon[p].phi, muon[p].mass) mass = (tp + pp).M() if mass > self.kMaxMass or mass < self.kMinMass: continue ### The tag must match a trigger object: if nProbesFound == 0: nProbesFound += 1 pair.append([t, p]) else: # This tag has 2 or more probes!! pair = pair[:-1] # Check that we have at least one pair... calculate the mass of the pair if len(pair) == 0: return False # events with 1 or 2 pairs! rho = event.fixedGridRhoFastjetAll print "[%i] rho = %1.2f" % (self.i, rho) self.i += 1 # Set variables for tag, probe and event for thisPair in pair: ti, pi = thisPair ptag = TLorentzVector() ppro = TLorentzVector() ptag.SetPtEtaPhiM(muon[ti].pt, muon[ti].eta, muon[ti].phi, muon[ti].mass) ppro.SetPtEtaPhiM(muon[pi].pt, muon[pi].eta, muon[pi].phi, muon[pi].mass) mass = (ptag + ppro).M() # Trigger requirement... IsoMu27 if self.year == 17: passTrigger = event.HLT_IsoMu27 elif self.year == 16: passTrigger = event.HLT_IsoMu24 or event.HLT_IsoTkMu24 elif self.year == 18: passTrigger = event.HLT_IsoMu24 # Compute HT and MET ht = 0 met = event.METFixEE2017_pt if self.year == 17 else event.MET_pt for j in jet: if self.filenameJECrecal != "": pass else: ht += j.pt if j.pt > 30 else 0 isdata = 0 if hasattr(event, 'Muon_genPartFlav') else 1 # Tag kinematics self.out.fillBranch("Tag_pt", muon[ti].pt) self.out.fillBranch("Tag_eta", muon[ti].eta) self.out.fillBranch("Tag_phi", muon[ti].phi) self.out.fillBranch("Tag_mass", muon[ti].mass) self.out.fillBranch("Tag_charge", muon[ti].charge) self.out.fillBranch("Tag_iso", muon[ti].pfRelIso04_all) self.out.fillBranch("Tag_dz", muon[ti].dz) self.out.fillBranch("Tag_dxy", muon[ti].dxy) tagMatch = 1 if isdata else (muon[ti].genPartFlav == 1 or muon[ti].genPartFlav == 15) self.out.fillBranch("Tag_isGenMatched", tagMatch) # Probe kinematics self.out.fillBranch("Probe_pt", muon[pi].pt) self.out.fillBranch("Probe_eta", muon[pi].eta) self.out.fillBranch("Probe_phi", muon[pi].phi) self.out.fillBranch("Probe_mass", muon[pi].mass) self.out.fillBranch("Probe_charge", muon[pi].charge) self.out.fillBranch("Probe_dxy", muon[pi].dxy) self.out.fillBranch("Probe_dz", muon[pi].dz) self.out.fillBranch("Probe_SIP3D", muon[pi].sip3d) self.out.fillBranch("Probe_iso", muon[pi].pfRelIso04_all) # Probe ID and ISO flags (from nanoAOD tag IDs) self.out.fillBranch("Probe_passL", 1) self.out.fillBranch("Probe_passM", muon[pi].mediumId) self.out.fillBranch("Probe_passMP", muon[pi].mediumPromptId) self.out.fillBranch("Probe_passT", muon[pi].tightId) self.out.fillBranch("Probe_passRelIsoVL", muon[pi].pfRelIso04_all <= 0.4) self.out.fillBranch("Probe_passRelIsoM", muon[pi].pfRelIso04_all <= 0.25) self.out.fillBranch("Probe_passRelIsoL", muon[pi].pfRelIso04_all <= 0.20) self.out.fillBranch("Probe_passRelIsoT", muon[pi].pfRelIso04_all <= 0.15) self.out.fillBranch("Probe_passMiniIsoL", muon[pi].miniPFRelIso_all < 0.4) self.out.fillBranch("Probe_passMiniIsoM", muon[pi].miniPFRelIso_all < 0.2) self.out.fillBranch("Probe_passMiniIsoT", muon[pi].miniPFRelIso_all < 0.1) self.out.fillBranch("Probe_passMiniIsoVT", muon[pi].miniPFRelIso_all < 0.05) probeMatch = 1 if isdata else (muon[pi].genPartFlav == 1 or muon[pi].genPartFlav == 15) self.out.fillBranch("Probe_isGenMatched", probeMatch) # Other working points: SIP2D and dpt/pt self.out.fillBranch("Probe_passDptPt02", muon[pi].ptErr / muon[pi].pt < 0.2) self.out.fillBranch("Probe_passSIP4", muon[pi].sip3d < 4) self.out.fillBranch("Probe_passSIP8", muon[pi].sip3d < 8) # Probe Lepton MVA (from nanoAOD, for the moment) self.out.fillBranch("Probe_passMVAL", muon[pi].mvaId >= 1) self.out.fillBranch("Probe_passMVAM", muon[pi].mvaId >= 2) self.out.fillBranch("Probe_passMVAT", muon[pi].mvaId >= 3) # MultiIso... calculate jet-JecLepAware ptRel, ptRatio jetId = muon[pi].jetIdx MiniRelIso = muon[pi].miniPFRelIso_all jetRelIso = muon[pi].jetRelIso # jetRelIso = 1/ptRatio - 1 if jetId == -1: # No jet matching.... ptRel = 0 ptRatio = 1 / (jetRelIso + 1) else: # from Muon_jetRelIso in nanoAOD if doCalculateJecLepAwareFromNanoAOD: jetRelIso = muon[pi].jetRelIso # jetRelIso = 1/ptRatio - 1 ptRatio = 1 / (jetRelIso + 1) jetJECLepAwarePt = muon[pi].pt * (jetRelIso + 1) lp = TLorentzVector() jt = TLorentzVector() lp.SetPtEtaPhiM(muon[pi].pt, muon[pi].eta, muon[pi].phi, muon[pi].mass) jt.SetPtEtaPhiM(jetJECLepAwarePt, jet[jetId].eta, jet[jetId].phi, jet[jetId].mass) ptRel = lp.Perp((jt - lp).Vect()) else: j = jet[jetId] corr = self.jetReCalibrator.getCorrection(j, rho) print 'corr = %1.2f, jet Pt = %1.2f' % (corr, j.pt) ptRel = self.ptRelv2(muon[pi], j, corr) print 'ptRel = ', ptRel ptRatio = muon[pi].pt / self.jetLepAwareJEC( muon[pi], j, corr).Pt() print 'ptRatio = ', ptRatio # Definitions from https://twiki.cern.ch/twiki/bin/viewauth/CMS/SUSLeptonSF passMultiIsoL = MiniRelIso < 0.20 and (ptRatio > 0.69 or ptRel > 6.0) passMultiIsoM = MiniRelIso < 0.16 and (ptRatio > 0.76 or ptRel > 7.2) passMultiIsoM2017 = MiniRelIso < 0.12 and (ptRatio > 0.80 or ptRel > 7.5) passMultiIsoM2017v2 = MiniRelIso < 0.11 and (ptRatio > 0.74 or ptRel > 6.8) print 'passMultiIsoL = ', passMultiIsoL self.out.fillBranch("Probe_passMultiIsoL", passMultiIsoL) self.out.fillBranch("Probe_passMultiIsoM", passMultiIsoM) self.out.fillBranch("Probe_passMultiIsoM2017", passMultiIsoM2017) self.out.fillBranch("Probe_passMultiIsoM2017v2", passMultiIsoM2017v2) self.out.fillBranch("Probe_ptRatio", ptRatio) self.out.fillBranch("Probe_ptRel", ptRel) self.out.fillBranch("Probe_jetRelIso", jetRelIso) # TnP variables self.out.fillBranch("TnP_mass", mass) self.out.fillBranch("TnP_trigger", passTrigger) self.out.fillBranch("TnP_npairs", len(pair)) self.out.fillBranch("TnP_met", met) self.out.fillBranch("TnP_ht", ht) self.out.fill() return False
hCutflow.Fill(ncut, evtwt) # Pass 2D Isolation dRMin = 999999.9 for j in centjets: dR = j.DeltaR(primarylep) jet_p3 = j.Vect() delPtRel = (lep_p3.Cross(jet_p3)).Mag() / jet_p3.Mag() hDR.Fill(dR, evtwt) hDelPtRel.Fill(delPtRel, evtwt) if dR < dRMin: nearestJetP4 = j dRMin = dR dPtRel = delPtRel # Store extra variables ptRel = nearestJetP4.Perp(primarylep.Vect()) hPtRel.Fill(ptRel, evtwt) hDRMin.Fill(dRMin, evtwt) nearestJet_p3 = nearestJetP4.Vect() hDPtRel.Fill(dPtRel, evtwt) h2DPtRelDRMin.Fill(dRMin, ptRel, evtwt) h2DdPtRelDRMin.Fill(dRMin, dPtRel, evtwt) if dPtRel < 25.0 and dRMin < 0.4: continue ncut += 1 hCutflow.Fill(ncut, evtwt) hdptreldRafter.Fill(dRMin, dPtRel, evtwt) # ST greater than 400 if ST < 400: continue ncut += 1
lep_p3 = lepP4.Vect() # Pass 2D Isolation for j in jetsP4: dR = j.DeltaR(lepP4) jet_p3 = j.Vect() delPtRel = (lep_p3.Cross(jet_p3)).Mag() / jet_p3.Mag() hDR.Fill(dR, evtwt) hDelPtRel.Fill(delPtRel, evtwt) h2DdPtReldR.Fill(dR, delPtRel, evtwt) if dR < dRMin: nearestJetP4 = j dRMin = dR dPtRel = delPtRel # Store extra variables ptRel = nearestJetP4.Perp(lepP4.Vect()) hPtRel.Fill(ptRel, evtwt) hDRMin.Fill(dRMin, evtwt) hDPtRel.Fill(dPtRel, evtwt) h2DPtRelDRMin.Fill(dRMin, ptRel, evtwt) h2DdPtRelDRMin.Fill(dRMin, dPtRel, evtwt) if dPtRel < 10.0 and dRMin < 0.1: continue ncut += 1 hCutflow.Fill(ncut, evtwt) # 3 or more central jets if len(centjets) < 3: continue ncut += 1 hCutflow.Fill(ncut, evtwt) # 1 or more forward jets if len(fjets) < 1: continue