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 isKstLL(b0meson, togenmatchleptons, togenmatchhadrons, flav=13): # isB0 = (b0meson.pdgId()==511) # isAntiB0 = (not isB0) # positive-charged leptons lps = [ip for ip in b0meson.finaldaughters if ip.pdgId() == -abs(flav)] # negative-charged leptons lms = [ip for ip in b0meson.finaldaughters if ip.pdgId() == abs(flav)] # pions from K* pis = [ip for ip in b0meson.finaldaughters if abs(ip.pdgId()) == 211] # kaons from K* ks = [ip for ip in b0meson.finaldaughters if abs(ip.pdgId()) == 321] for ilep in lps + lms: # avoid matching the same particle twice, use the charge to distinguish (charge flip not accounted...) tomatch = [ jj for jj in togenmatchleptons if jj.charge() == ilep.charge() ] bm, dr = bestMatch(ilep, tomatch) if dr < 0.3: ilep.reco = bm for ihad in pis + ks: # avoid matching the same particle twice, use the charge to distinguish (charge flip not accounted...) tomatch = [ jj for jj in togenmatchhadrons if jj.charge() == ihad.charge() ] bm, dr = bestMatch(ihad, tomatch) if dr < 0.3: ihad.reco = bm if len(lps) == len(lms) == len(pis) == len(ks) == 1: return True, lps[0], lms[0], pis[0], ks[0] else: return False, None, None, None, None
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 process(self, event): if event.input.eventAuxiliary().isRealData(): return True # match the refitted tau to gen tau tau = event.tau3muRefit.p4Muons() best_match, dRmin = bestMatch(tau, event.gentaus) tau_match = best_match if dRmin < 0.3 else None muons = [ event.tau3muRefit.mu1(), event.tau3muRefit.mu2(), event.tau3muRefit.mu3() ] # now match the three muons: # first try to match to any stable gen particle stableGenParticles = [ pp for pp in event.genParticles if pp.status() == 2 ] for mu in muons: best_match, dRmin = bestMatch(mu, stableGenParticles) if dRmin < 0.1: mu.genp = best_match # then match to tau daughters # but only if the reco tau is matched to a gen tau itself if tau_match: # append the gen tau to the event event.gentau = tau_match tau_daughters = list(tau_match.daughterRefVector()) for mu in muons: best_match, dRmin = bestMatch(mu, tau_daughters) if dRmin < 0.1: mu.genp = best_match # check if the tau comes from a w tau_genw = [ pp for pp in list(tau_match.motherRefVector()) if abs(pp.pdgId()) == 24 ] if tau_genw: event.genw = tau_genw[0] neutrinos = [ pp for pp in event.genParticles if abs(pp.pdgId()) in [12, 14, 16] ] for i, nn in enumerate(neutrinos): if i == 0: event.genmet = nn.p4() else: event.genmet += nn.p4() # import pdb ; pdb.set_trace() return True
def process(self, event): self.readCollections(event.input) event.taus = [Tau(tau) for tau in self.handles['taus'].product()] event.gen = self.handles['gen'].product() event.genParticles = event.gen event.genJets = self.handles['gen_jets'].product() for pu_info in self.handles['pu'].product(): if pu_info.getBunchCrossing() == 0: event.n_true_interactions = pu_info.getTrueNumInteractions() event.genleps = [p for p in event.gen if abs(p.pdgId()) in [11, 13] and p.statusFlags().isPrompt()] event.gentauleps = [p for p in event.gen if abs(p.pdgId()) in [11, 13] and p.statusFlags().isDirectPromptTauDecayProduct()] event.gentaus = [p for p in event.gen if abs(p.pdgId()) == 15 and p.statusFlags().isPrompt() and not any(abs(HTTGenAnalyzer.getFinalTau(p).daughter(i_d).pdgId()) in [11, 13] for i_d in xrange(HTTGenAnalyzer.getFinalTau(p).numberOfDaughters()))] HTTGenAnalyzer.getGenTauJets(event) # saves event.genTauJets for gen_tau in event.genTauJets: gen_tau.charged = [d for d in gen_tau.daughters if d.charge()] gen_tau.pizeros = [daughters(d) for d in gen_tau.daughters if d.pdgId() == 111] pf_candidates = self.handles['pf_candidates'].product() for tau in event.taus: TauIsoAnalyzer.addInfo(tau, event, [c for c in pf_candidates if abs(c.pdgId()) == 211], maxDeltaR=0.8) matched_gen_jet, dr2 = bestMatch(tau, event.genJets) if dr2 < 0.25: tau.gen_jet = matched_gen_jet return True
def XZZmatchObjectCollection(objects, matchCollection, deltaR2Max, dPtMaxFactor, filter=lambda x, y: True): ''' @ Apr-6-16 Adds genJets matching for JER according to https://github.com/cms-sw/cmssw/blob/518995a62433825453d7ccf9ec222d782086cad9/PhysicsTools/PatUtils/interface/SmearedJetProducerT.h used to produce the sync table: https://twiki.cern.ch/twiki/bin/view/CMS/JERCReference ''' pairs = {} if len(objects) == 0: return pairs if len(matchCollection) == 0: return dict(zip(objects, [None] * len(objects))) for object in objects: bm, dr2 = bestMatch( object, [mob for mob in matchCollection if filter(object, mob)]) dPt = abs(bm.pt() - object.pt()) if dr2 < deltaR2Max and dPt < dPtMaxFactor * object.pt( ) * object.resolution: pairs[object] = bm else: pairs[object] = None return pairs
def genMatch(self, event, dR=0.3): dR2 = dR * dR # match the tau_h leg # to generated had taus l1match, dR2best = bestMatch(self.l1, event.gentaus) if dR2best < dR2: self.l1.genp = l1match self.l1.isTauHad = True # to generated leptons from taus if not self.l1.isTauHad: l1match, dR2best = bestMatch(self.l1, self.ptSelGentauleps) if dR2best < dR2: self.l1.genp = l1match self.l1.isTauLep = True # to generated prompt leptons elif not self.l1.isTauLep: l1match, dR2best = bestMatch(self.l1, self.ptSelGenleps) if dR2best < dR2: self.l1.genp = l1match self.l1.isPromptLep = True # match with any other gen particle elif not self.l1.isPromptLep: l1match, dR2best = bestMatch(self.l1, event.genParticles) if dR2best < dR2: self.l1.genp = l1match # match the mu leg # to generated had taus l2match, dR2best = bestMatch(self.l2, event.gentaus) if dR2best < dR2: self.l2.genp = l2match self.l2.isTauHad = True # to generated leptons from taus if not self.l2.isTauHad: l2match, dR2best = bestMatch(self.l2, self.ptSelGentauleps) if dR2best < dR2: self.l2.genp = l2match self.l2.isTauLep = True # to generated prompt leptons elif not self.l2.isTauLep: l2match, dR2best = bestMatch(self.l2, self.ptSelGenleps) if dR2best < dR2: self.l2.genp = l2match self.l2.isPromptLep = True # match with any other gen particle elif not self.l2.isPromptLep: l2match, dR2best = bestMatch(self.l2, event.genParticles) if dR2best < dR2: self.l2.genp = l2match
def attachJets(self, quad, jets): # must clean jets from the leptons in the candidate in addition to the ones already cleaned leptonsAndPhotons = quad.daughterLeptons() + quad.daughterPhotons() quad.cleanJets = [] quad.cleanJetIndices = [] for ij, j in enumerate(jets): bm, dr2 = bestMatch(j, leptonsAndPhotons) if dr2 < 0.4**2: continue quad.cleanJets.append(j) quad.cleanJetIndices.append(ij)
def matchL1TriggerObject(self, to): l1to, dR2 = bestMatch(to, self.l1tos) if hasattr(self.cfg_comp, 'channel') and self.cfg_comp.channel == 'tt': ptcut = 31.9999 else: ptcut = 0 if dR2 < 0.25 and l1to.Pt() > ptcut: return True # for l1to in self.l1tos: # if deltaR2(to.eta(),to.phi(),l1to.Eta(),l1to.Phi()) < 0.25 and l1to.Pt()>31.9999:# because some come with 31.999999999996 and are passed by KIT # return True return False
def single_muon(muons, pt, eta=2.5, qual=8, matches=[], cone=0.3, onlymuons=False, atvtx=True): cone2 = cone * cone results = [] for mu in muons: matched = False dRmin = 999. if mu.hwQual() < qual: continue if mu.pt() < pt : continue if abs(mu.eta()) > eta : continue mu_for_matching = mu.clone() if atvtx: mu_for_matching.eta = mu.etaAtVtx mu_for_matching.phi = mu.phiAtVtx match_index = -99 for ii, imatch in enumerate(matches): imatch.matched = False matched = False if onlymuons: best_match, dRmin = bestMatch(mu_for_matching, imatch.finalmuondaughters) else: best_match, dRmin = bestMatch(mu_for_matching, imatch.finalchargeddaughters) matched = dRmin<cone2 if matched: match_index = ii imatch.matched = True break results.append((1, int(matched), match_index)) if len(results)>0: results.sort(key = lambda x : (x[0], x[1]), reverse=True) return int(results[0][0]), int(results[0][1]), int(results[0][2]) return 0, 0, -1
def makeVetoLeptons(self, event): ### selected leptons = subset of inclusive leptons passing some basic id definition and pt requirement ### other leptons = subset of inclusive leptons failing some basic id definition and pt requirement event.vetoLeptons = [] event.vetoMuons = [] event.vetoElectrons = [] #the selected leptons are the ones with the corrections / calibrations applied # make veto leptons for mu in event.selectedMuons: if (mu.pt() > self.cfg_ana.veto_muon_pt and abs(mu.eta()) < self.cfg_ana.veto_muon_eta and abs(mu.dxy()) < self.cfg_ana.veto_muon_dxy and abs(mu.dz()) < self.cfg_ana.veto_muon_dz and self.muIsoCut(mu)): mu.vetoIdMonoX = True event.vetoLeptons.append(mu) event.vetoMuons.append(mu) else: mu.vetoIdMonoX = False vetoMuons = event.vetoLeptons[:] for ele in event.selectedElectrons: if (ele.pt() > self.cfg_ana.veto_electron_pt and abs(ele.eta()) < self.cfg_ana.veto_electron_eta and (abs(ele.dxy()) < (self.cfg_ana.veto_electron_dxy[0] if ele.isEB() else self.cfg_ana.veto_electron_dxy[1]) and abs(ele.dz()) < (self.cfg_ana.veto_electron_dz[0] if ele.isEB() else self.cfg_ana.veto_electron_dxy[1])) and self.eleIsoCut(ele) and ele.passConversionVeto() and ele.lostInner() <= (self.cfg_ana.veto_electron_lostHits[0] if ele.isEB() else self.cfg_ana.veto_electron_lostHits[1]) and (True if getattr(self.cfg_ana, 'notCleaningElectrons', False) else (bestMatch(ele, vetoMuons)[1] > (self.cfg_ana.min_dr_electron_muon**2)))): event.vetoLeptons.append(ele) event.vetoElectrons.append(ele) ele.vetoIdMonoX = True else: ele.vetoIdMonoX = False event.vetoLeptons.sort(key=lambda l: l.pt(), reverse=True) event.vetoMuons.sort(key=lambda l: l.pt(), reverse=True) event.vetoElectrons.sort(key=lambda l: l.pt(), reverse=True) for lepton in event.vetoLeptons: if hasattr(self, 'efficiency'): self.efficiency.attachToObject(lepton)
def genMatch(self, event, leg, dR=0.3, matchAll=True): dR2 = dR * dR leg.isTauHad = False leg.isTauLep = False leg.isPromptLep = False leg.genp = None # match the tau_h leg # to generated had taus l1match, dR2best = bestMatch(leg, event.gentaus) if dR2best < dR2: leg.genp = l1match leg.isTauHad = True return # to generated leptons from taus l1match, dR2best = bestMatch(leg, self.ptSelGentauleps) if dR2best < dR2: leg.genp = l1match leg.isTauLep = True return # to generated prompt leptons l1match, dR2best = bestMatch(leg, self.ptSelGenleps) if dR2best < dR2: leg.genp = l1match leg.isPromptLep = True return # match with any other relevant gen particle if matchAll: l1match, dR2best = bestMatch(leg, self.ptSelGenSummary) if dR2best < dR2: leg.genp = l1match
def MatchTausToJets(refObjs): # For each Jet, get the closest RecoTau Match = {} for jetidx, refObj in enumerate(refObjs): tau, _dr2_ = bestMatch(refObj, taus) # dR2=0.25 == dR=0.5 for tauidx, itau in enumerate(taus): if itau == tau: break if _dr2_ < 0.25: Match[jetidx] = tauidx # Is the same Tau assinged to more than one Jet? DoubleCheck = [] for ijet, itau in Match.iteritems(): for jjet, jtau in Match.iteritems(): if jjet >= ijet: continue if itau == jtau: if ijet not in DoubleCheck: DoubleCheck.append(ijet) if jjet not in DoubleCheck: DoubleCheck.append(jjet) # Get all distances between all conflicting Jets and corresponding Taus Distances = {} for ijet in DoubleCheck: for jjet in DoubleCheck: itau = Match[jjet] Distances[str(ijet) + "_" + str(itau)] = deltaR( taus[itau].eta(), taus[itau].phi(), refObjs[ijet].eta(), refObjs[ijet].phi()) #print Distances # Remove all conflicting Jets, to re-assign later for ijet in DoubleCheck: del Match[ijet] # Assign shortest distance between Tau and Jet, then move on ignoring the already assigned Taus/Jets while Distances != {}: keepthis = min(Distances, key=Distances.get) thisjet = int(keepthis[:keepthis.find("_")]) thistau = int(keepthis[keepthis.rfind("_") + 1:]) Match[thisjet] = thistau deletethis = [] for element in Distances: if element.startswith(str(thisjet)) or element.endswith( str(thistau)): deletethis.append(element) for element in deletethis: del Distances[element] return Match
def makeVetoLeptons(self, event): ### selected leptons = subset of inclusive leptons passing some basic id definition and pt requirement ### other leptons = subset of inclusive leptons failing some basic id definition and pt requirement event.vetoLeptons = [] event.vetoMuons = [] event.vetoElectrons = [] #the selected leptons are the ones with the corrections / calibrations applied # make veto leptons for mu in event.selectedMuons: if (mu.pt() > self.cfg_ana.veto_muon_pt and abs(mu.eta()) < self.cfg_ana.veto_muon_eta and abs(mu.dxy()) < self.cfg_ana.veto_muon_dxy and abs(mu.dz()) < self.cfg_ana.veto_muon_dz and self.muIsoCut(mu)): mu.vetoIdMonoX = True event.vetoLeptons.append(mu) event.vetoMuons.append(mu) else: mu.vetoIdMonoX = False vetoMuons = event.vetoLeptons[:] for ele in event.selectedElectrons: if ( ele.pt() > self.cfg_ana.veto_electron_pt and abs(ele.eta())<self.cfg_ana.veto_electron_eta and (abs(ele.dxy()) < (self.cfg_ana.veto_electron_dxy[0] if ele.isEB() else self.cfg_ana.veto_electron_dxy[1]) and abs(ele.dz()) < (self.cfg_ana.veto_electron_dz[0] if ele.isEB() else self.cfg_ana.veto_electron_dxy[1])) and self.eleIsoCut(ele) and ele.passConversionVeto() and ele.lostInner() <= (self.cfg_ana.veto_electron_lostHits[0] if ele.isEB() else self.cfg_ana.veto_electron_lostHits[1]) and ( True if getattr(self.cfg_ana,'notCleaningElectrons',False) else (bestMatch(ele, vetoMuons)[1] > (self.cfg_ana.min_dr_electron_muon**2)) )): event.vetoLeptons.append(ele) event.vetoElectrons.append(ele) ele.vetoIdMonoX = True else: ele.vetoIdMonoX = False event.vetoLeptons.sort(key = lambda l : l.pt(), reverse = True) event.vetoMuons.sort(key = lambda l : l.pt(), reverse = True) event.vetoElectrons.sort(key = lambda l : l.pt(), reverse = True) for lepton in event.vetoLeptons: if hasattr(self,'efficiency'): self.efficiency.attachToObject(lepton)
def process(self, event): self.counters.counter('LegTriggerMatcher').inc('all events') dR2max = getattr(self.cfg_ana, 'dRmax', 0.1)**2 collection = getattr(event, self.cfg_ana.collection) tomatch = self.cfg_ana.paths_and_filters for icoll in collection: if not hasattr(icoll, 'trig_obj'): icoll.trig_obj = OrderedDict() for ihlt, ifilter in tomatch.iteritems(): infos = [info for info in event.trigger_infos if ihlt=='_'.join(info.name.split('_')[:-1])] if len(infos)!=1: continue else: info = infos[0] objects = info.objects objects = [obj for obj in objects if obj.filter(ifilter[0]) and obj.triggerObjectTypes()[0]==ifilter[1]] # temporary collection to save only trig matched objects tmp_coll = [] for icoll in collection: icoll.trig_obj[ifilter] = -1 bestmatch, dR2 = bestMatch(icoll, objects) if dR2 < dR2max: icoll.trig_obj[ifilter] = bestmatch tmp_coll.append(icoll) if getattr(self.cfg_ana, 'filter', False): setattr(event, self.cfg_ana.collection + '_matched', tmp_coll) if len(tmp_coll)>0: self.counters.counter('LegTriggerMatcher').inc('matched events')
#### Fill tree #### tree.kaonCharged = abs_final_part.count(321) tree.pionCharged = abs_final_part.count(211) tree.kaonNeutrals = abs_final_part.count(130)+abs_final_part.count(310) tree.pionNeutrals = abs_final_part.count(111) tree.muons = abs_final_part.count(13) tree.electrons = abs_final_part.count(11) tree.neutrals = abs_final_part.count(130)+abs_final_part.count(310)+abs_final_part.count(111)+abs_final_part.count(16)+abs_final_part.count(14)+abs_final_part.count(12) tree.charged = abs_final_part.count(321)+abs_final_part.count(211)+abs_final_part.count(13)+abs_final_part.count(11) tree.dMeson = dMeson ####### Let's match the jets ####### jets = [jet for jet in recoJets] matchedJet, _ = bestMatch(maj_neutrinos[0], jets) #pt eta phi mass btagging discriminator #isolamento #B tagging discriminator: look for displaced vertexes and traks in a jet if matchedJet: tree.pt_Jet = matchedJet.pt() tree.eta_Jet= matchedJet.eta() tree.phi_Jet= matchedJet.phi() tree.mass_Jet= matchedJet.mass() tree.et_Jet= matchedJet.et() jet_particles = matchedJet.getPFConstituents() deposits = [0]*9 for prt in jet_particles: dr = deltaR(prt, matchedJet) idx = min(int(floor(dr/0.05)), 8)
def makeLeptons(self, event): ### inclusive leptons = all leptons that could be considered somewhere in the analysis, with minimal requirements (used e.g. to match to MC) event.inclusiveLeptons = [] ### selected leptons = subset of inclusive leptons passing some basic id definition and pt requirement ### other leptons = subset of inclusive leptons failing some basic id definition and pt requirement event.selectedLeptons = [] event.selectedMuons = [] event.selectedElectrons = [] event.otherLeptons = [] if self.doMiniIsolation: self.IsolationComputer.setPackedCandidates(self.handles['packedCandidates'].product()) if self.miniIsolationVetoLeptons == "any": for lep in self.handles['muons'].product(): self.IsolationComputer.addVeto(lep) for lep in self.handles['electrons'].product(): self.IsolationComputer.addVeto(lep) #muons allmuons = self.makeAllMuons(event) #electrons allelectrons = self.makeAllElectrons(event) #make inclusive leptons inclusiveMuons = [] inclusiveElectrons = [] for mu in allmuons: if (mu.track().isNonnull() and mu.muonID(self.cfg_ana.inclusive_muon_id) and mu.pt()>self.cfg_ana.inclusive_muon_pt and abs(mu.eta())<self.cfg_ana.inclusive_muon_eta and abs(mu.dxy())<self.cfg_ana.inclusive_muon_dxy and abs(mu.dz())<self.cfg_ana.inclusive_muon_dz): inclusiveMuons.append(mu) for ele in allelectrons: if ( ele.electronID(self.cfg_ana.inclusive_electron_id) and ele.pt()>self.cfg_ana.inclusive_electron_pt and abs(ele.eta())<self.cfg_ana.inclusive_electron_eta and abs(ele.dxy())<self.cfg_ana.inclusive_electron_dxy and abs(ele.dz())<self.cfg_ana.inclusive_electron_dz and ele.lostInner()<=self.cfg_ana.inclusive_electron_lostHits ): inclusiveElectrons.append(ele) event.inclusiveLeptons = inclusiveMuons + inclusiveElectrons if self.doMiniIsolation: if self.miniIsolationVetoLeptons == "inclusive": for lep in event.inclusiveLeptons: self.IsolationComputer.addVeto(lep) for lep in event.inclusiveLeptons: self.attachMiniIsolation(lep) # make loose leptons (basic selection) for mu in inclusiveMuons: if (mu.muonID(self.cfg_ana.loose_muon_id) and mu.pt() > self.cfg_ana.loose_muon_pt and abs(mu.eta()) < self.cfg_ana.loose_muon_eta and abs(mu.dxy()) < self.cfg_ana.loose_muon_dxy and abs(mu.dz()) < self.cfg_ana.loose_muon_dz and self.muIsoCut(mu)): mu.looseIdSusy = True event.selectedLeptons.append(mu) event.selectedMuons.append(mu) else: mu.looseIdSusy = False event.otherLeptons.append(mu) looseMuons = event.selectedLeptons[:] for ele in inclusiveElectrons: if (ele.electronID(self.cfg_ana.loose_electron_id) and ele.pt()>self.cfg_ana.loose_electron_pt and abs(ele.eta())<self.cfg_ana.loose_electron_eta and abs(ele.dxy()) < self.cfg_ana.loose_electron_dxy and abs(ele.dz())<self.cfg_ana.loose_electron_dz and self.eleIsoCut(ele) and ele.lostInner() <= self.cfg_ana.loose_electron_lostHits and ( True if getattr(self.cfg_ana,'notCleaningElectrons',False) else (bestMatch(ele, looseMuons)[1] > (self.cfg_ana.min_dr_electron_muon**2)) )): event.selectedLeptons.append(ele) event.selectedElectrons.append(ele) ele.looseIdSusy = True else: event.otherLeptons.append(ele) ele.looseIdSusy = False event.otherLeptons.sort(key = lambda l : l.pt(), reverse = True) event.selectedLeptons.sort(key = lambda l : l.pt(), reverse = True) event.selectedMuons.sort(key = lambda l : l.pt(), reverse = True) event.selectedElectrons.sort(key = lambda l : l.pt(), reverse = True) event.inclusiveLeptons.sort(key = lambda l : l.pt(), reverse = True) for lepton in event.selectedLeptons: if hasattr(self,'efficiency'): self.efficiency.attachToObject(lepton)
def genMatch(event, leg, ptSelGentauleps, ptSelGenleps, ptSelGenSummary, dR=0.3, matchAll=True): dR2 = dR * dR leg.isTauHad = False leg.isTauLep = False leg.isPromptLep = False leg.genp = None # match the tau_h leg # to generated had taus l1match, dR2best = bestMatch(leg, event.gentaus) if dR2best < dR2: leg.genp = l1match leg.isTauHad = True return # to generated leptons from taus l1match, dR2best = bestMatch(leg, ptSelGentauleps) if dR2best < dR2: leg.genp = l1match leg.isTauLep = True return # to generated prompt leptons l1match, dR2best = bestMatch(leg, ptSelGenleps) if dR2best < dR2: leg.genp = l1match leg.isPromptLep = True return # match with any other relevant gen particle if matchAll: l1match, dR2best = bestMatch(leg, ptSelGenSummary) if dR2best < 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 < 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.0: 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 process(self, event): self.readCollections(event.input) self.counters.counter('RecoGenTreeAnalyzer').inc('all events') # produce collections and map our objects to convenient Heppy objects event.muons = map(Muon, self.handles['muons'].product()) event.electrons = map(Electron, self.handles['electrons'].product()) event.photons = map(Photon, self.handles['photons'].product()) event.taus = map(Tau, self.handles['taus'].product()) event.jets = map(Jet, self.handles['jets'].product()) event.dsmuons = self.buildDisplacedMuons( self.handles['dsmuons'].product()) event.dgmuons = self.buildDisplacedMuons( self.handles['dgmuons'].product()) # vertex stuff event.pvs = self.handles['pvs'].product() event.svs = self.handles['svs'].product() event.beamspot = self.handles['beamspot'].product() # met event.met = self.handles['met'].product().at(0) # assign to the leptons the primary vertex, will be needed to compute a few quantities # FIXME! understand exactly to which extent it is reasonable to assign the PV to *all* leptons # regardless whether they're displaced or not if len(event.pvs): myvtx = event.pvs[0] else: myvtx = event.beamspot self.assignVtx(event.muons, myvtx) self.assignVtx(event.electrons, myvtx) self.assignVtx(event.photons, myvtx) self.assignVtx(event.taus, myvtx) # all matchable objects # matchable = event.electrons + event.photons + event.muons + event.taus + event.dsmuons + event.dgmuons # matchable = event.electrons + event.photons + event.muons + event.taus + event.dsmuons # matchable = event.electrons + event.photons + event.taus + event.muons + event.dsmuons + event.dgmuons matchable = event.electrons + event.photons + event.taus + event.muons #define the dr to cut on dr_cut = 0.2 # match gen to reco for ip in [event.the_hnl.l0(), event.the_hnl.l1(), event.the_hnl.l2()]: ip.bestmatch = None ip.bestmatchtype = None ip.matches = inConeCollection( ip, matchable, getattr(self.cfg_ana, 'drmax', dr_cut), 0.) # matches the corresponding "slimmed electron" to the gen particle if len(event.electrons): dr2 = np.inf match, dr2 = bestMatch(ip, event.electrons) if dr2 < dr_cut * dr_cut: ip.bestelectron = match # # matches the corresponding "slimmed photon" to the gen particle # if len(event.photons): # dr2 = np.inf # match, dr2 = bestMatch(ip,event.photons) # if dr2 < dr_cut * dr_cut: # ip.bestphoton = match # matches the corresponding "slimmed muon" to the gen particle if len(event.muons): dr2 = np.inf match, dr2 = bestMatch(ip, event.muons) if dr2 < dr_cut * dr_cut: ip.bestmuon = match # # matches the corresponding "slimmed tau" to the gen particle # if len(event.taus): # dr2 = np.inf # match, dr2 = bestMatch(ip,event.taus) # if dr2 < dr_cut * dr_cut: # ip.besttau = match # matches the corresponding "displaced stand alone muon" to the gen particle if len(event.dsmuons): dr2 = np.inf match, dr2 = bestMatch(ip, event.dsmuons) if dr2 < dr_cut * dr_cut: ip.bestdsmuon = match # matches the corresponding "displaced global muon" to the gen particle if len(event.dgmuons): dr2 = np.inf match, dr2 = bestMatch(ip, event.dgmuons) if dr2 < dr_cut * dr_cut: ip.bestdgmuon = match # to find the best match, give precedence to any matched # particle in the matching cone with the correct PDG ID # then to the one which is closest ip.matches.sort(key=lambda x: (x.pdgId() == ip.pdgId(), -deltaR(x, ip)), reverse=True) if len(ip.matches) and abs(ip.pdgId()) == abs( ip.matches[0].pdgId()): ip.bestmatch = ip.matches[0] ip.bestmatchdR = deltaR(ip, ip.bestmatch) # remove already matched particles, avoid multiple matches to the same candidate while recording the type of reconstruction matchable.remove(ip.bestmatch) # record which is which if ip.bestmatch in event.electrons: ip.bestmatchtype = 11 if ip.bestmatch in event.photons: ip.bestmatchtype = 22 if ip.bestmatch in event.muons: ip.bestmatchtype = 13 if ip.bestmatch in event.taus: ip.bestmatchtype = 15 if ip.bestmatch in event.dsmuons: ip.bestmatchtype = 26 if ip.bestmatch in event.dgmuons: ip.bestmatchtype = 39 else: ip.bestmatchtype = -1 # clear it before doing it again event.recoSv = None # let's refit the secondary vertex, IF both leptons match to some reco particle pair = [event.the_hnl.l1().bestmatch, event.the_hnl.l2().bestmatch] if (pair[0] != None) and\ (pair[1] != None) and\ (pair[0].physObj != pair[1].physObj): event.recoSv = fitVertex(pair) if event.recoSv: # primary vertex pv = event.goodVertices[0] event.recoSv.disp3DFromBS = ROOT.VertexDistance3D().distance( event.recoSv, pv) event.recoSv.disp3DFromBS_sig = event.recoSv.disp3DFromBS.significance( ) # create an 'ideal' vertex out of the BS point = ROOT.reco.Vertex.Point( event.beamspot.position().x(), event.beamspot.position().y(), event.beamspot.position().z(), ) error = event.beamspot.covariance3D() chi2 = 0. ndof = 0. bsvtx = ROOT.reco.Vertex(point, error, chi2, ndof, 2) # size? say 3? does it matter? event.recoSv.disp2DFromBS = ROOT.VertexDistanceXY().distance( event.recoSv, bsvtx) event.recoSv.disp2DFromBS_sig = event.recoSv.disp2DFromBS.significance( ) event.recoSv.prob = ROOT.TMath.Prob(event.recoSv.chi2(), int(event.recoSv.ndof())) dilep_p4 = event.the_hnl.l1().bestmatch.p4( ) + event.the_hnl.l2().bestmatch.p4() perp = ROOT.math.XYZVector(dilep_p4.px(), dilep_p4.py(), 0.) dxybs = ROOT.GlobalPoint( -1 * ((event.beamspot.x0() - event.recoSv.x()) + (event.recoSv.z() - event.beamspot.z0()) * event.beamspot.dxdz()), -1 * ((event.beamspot.y0() - event.recoSv.y()) + (event.recoSv.z() - event.beamspot.z0()) * event.beamspot.dydz()), 0) vperp = ROOT.math.XYZVector(dxybs.x(), dxybs.y(), 0.) cos = vperp.Dot(perp) / (vperp.R() * perp.R()) event.recoSv.disp2DFromBS_cos = cos return True
'<ROOT::Math::PtEtaPhiM4D<double> >')() for idau in xrange(itau.numberOfDaughters()): if abs(itau.daughter(idau).pdgId()) not in [12, 14, 16]: itau_vis += itau.daughter(idau).p4() # gen decay mode itau.gen_dm = tauDecayModes.genDecayModeInt([ d for d in finalDaughters(itau) if abs(d.pdgId()) not in [12, 14, 16] ]) # reco tau reco_tau = None match = None dr2 = 1e3 match, dr2 = bestMatch(itau_vis, event.taus) if dr2 < 0.2 * 0.2: reco_tau = match # reco tau reco_tau_bis = None match = None dr2 = 1e3 match, dr2 = bestMatch(itau_vis, event.taus_bis) if dr2 < 0.2 * 0.2: reco_tau_bis = match # identify the primary vertex event.the_pv = event.the_hn.vertex()
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 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()
final_particles_pi0.append(p) else: final_particles.append(p) tree.numbOfDaughters = len(final_particles) muon_gen = [(x,x.pt()) for x in final_particles if (abs(x.pdgId())==13)] muon_gen.sort(key=lambda tup: tup[1], reverse=True) ####### Let's match the jets ####### jets = [jet for jet in recoJets if jet.pt() > 20] #print len(jets) if len(jets)!=0: jet_HNL, deltaR_HNL = bestMatch(maj_neutrinos[0], jets) tree.deltaR_HNL = deltaR_HNL #tree.jet_HNL_p = jet_HNL.p() tree.jet_HNL_pt = jet_HNL.pt() tree.jet_HNL_eta = jet_HNL.eta() tree.jet_HNL_phi = jet_HNL.phi() #let's check the fraction of the HNL daughters within a cone of .4 from the jet axes daughter_deltaR_HNL = [] for part in final_particles: daughter_deltaR_HNL.append(deltaR(part,jet_HNL)) tree.frac_HNLjet = float(sum(i < 0.4 for i in daughter_deltaR_HNL))/float(len(daughter_deltaR_HNL)) matchJetlist = bestMatchedJet(muon_gen[0][0], jets)
def makeLeptons(self, event): ### inclusive leptons = all leptons that could be considered somewhere in the analysis, with minimal requirements (used e.g. to match to MC) event.inclusiveLeptons = [] ### selected leptons = subset of inclusive leptons passing some basic id definition and pt requirement ### other leptons = subset of inclusive leptons failing some basic id definition and pt requirement event.selectedLeptons = [] event.selectedMuons = [] event.selectedElectrons = [] event.otherLeptons = [] #muons allmuons = self.makeAllMuons(event) for mu in allmuons: # inclusive, very loose, selection if (mu.track().isNonnull() and mu.muonID(self.cfg_ana.inclusive_muon_id) and mu.pt()>self.cfg_ana.inclusive_muon_pt and abs(mu.eta())<self.cfg_ana.inclusive_muon_eta and abs(mu.dxy())<self.cfg_ana.inclusive_muon_dxy and abs(mu.dz())<self.cfg_ana.inclusive_muon_dz): event.inclusiveLeptons.append(mu) # basic selection if (mu.muonID(self.cfg_ana.loose_muon_id) and mu.pt() > self.cfg_ana.loose_muon_pt and abs(mu.eta()) < self.cfg_ana.loose_muon_eta and abs(mu.dxy()) < self.cfg_ana.loose_muon_dxy and abs(mu.dz()) < self.cfg_ana.loose_muon_dz and mu.relIso03 < self.cfg_ana.loose_muon_relIso and mu.absIso03 < (self.cfg_ana.loose_muon_absIso if hasattr(self.cfg_ana,'loose_muon_absIso') else 9e99)): mu.looseIdSusy = True event.selectedLeptons.append(mu) event.selectedMuons.append(mu) else: mu.looseIdSusy = False event.otherLeptons.append(mu) #electrons allelectrons = self.makeAllElectrons(event) looseMuons = event.selectedLeptons[:] for ele in allelectrons: ## remove muons if muForEleCrossCleaning is not empty ## apply selection if ( ele.electronID(self.cfg_ana.inclusive_electron_id) and ele.pt()>self.cfg_ana.inclusive_electron_pt and abs(ele.eta())<self.cfg_ana.inclusive_electron_eta and abs(ele.dxy())<self.cfg_ana.inclusive_electron_dxy and abs(ele.dz())<self.cfg_ana.inclusive_electron_dz and ele.lostInner()<=self.cfg_ana.inclusive_electron_lostHits ): event.inclusiveLeptons.append(ele) # basic selection if (ele.electronID(self.cfg_ana.loose_electron_id) and ele.pt()>self.cfg_ana.loose_electron_pt and abs(ele.eta())<self.cfg_ana.loose_electron_eta and abs(ele.dxy()) < self.cfg_ana.loose_electron_dxy and abs(ele.dz())<self.cfg_ana.loose_electron_dz and ele.relIso03 <= self.cfg_ana.loose_electron_relIso and ele.absIso03 < (self.cfg_ana.loose_electron_absIso if hasattr(self.cfg_ana,'loose_electron_absIso') else 9e99) and ele.lostInner() <= self.cfg_ana.loose_electron_lostHits and ( True if (hasattr(self.cfg_ana,'notCleaningElectrons') and self.cfg_ana.notCleaningElectrons) else (bestMatch(ele, looseMuons)[1] > self.cfg_ana.min_dr_electron_muon) )): event.selectedLeptons.append(ele) event.selectedElectrons.append(ele) ele.looseIdSusy = True else: event.otherLeptons.append(ele) ele.looseIdSusy = False event.otherLeptons.sort(key = lambda l : l.pt(), reverse = True) event.selectedLeptons.sort(key = lambda l : l.pt(), reverse = True) event.selectedMuons.sort(key = lambda l : l.pt(), reverse = True) event.selectedElectrons.sort(key = lambda l : l.pt(), reverse = True) event.inclusiveLeptons.sort(key = lambda l : l.pt(), reverse = True) for lepton in event.selectedLeptons: if hasattr(self,'efficiency'): self.efficiency.attachToObject(lepton)
d for d in finalDaughters(refObj) if abs(d.pdgId()) not in [12, 14, 16] ]) all_var_dict['tau_gendm'].fill(gen_dm) all_var_dict['tau_gendm_rough'].fill(returnRough(gen_dm)) all_var_dict['tau_genpt'].fill(visP4.pt()) all_var_dict['tau_geneta'].fill(visP4.eta()) all_var_dict['tau_genphi'].fill(visP4.phi()) else: all_var_dict['tau_gendm'].fill(-1) all_var_dict['tau_gendm_rough'].fill(-1) all_var_dict['tau_genpt'].fill(refObj.pt()) all_var_dict['tau_geneta'].fill(refObj.eta()) all_var_dict['tau_genphi'].fill(refObj.phi()) tau, _dr_ = bestMatch(refObj, taus) if _dr_ > 0.5: tau = None tau_vtxTovtx_dz = 99 for i in range(0, len(vertices) - 1): for j in range(i + 1, len(vertices)): vtxdz = abs(vertices[i].z() - vertices[j].z()) if vtxdz < tau_vtxTovtx_dz: tau_vtxTovtx_dz = vtxdz all_var_dict['tau_vtxTovtx_dz'].fill(tau_vtxTovtx_dz) # Fill reco-tau variables if it exists... if tau != None: all_var_dict['tau_dm'].fill(tau.decayMode())
def process(self, event): if not self.enable: self.dummyProcess(event) return True self.readCollections( event.input ) pf = self.handles['pf'].product() leptons = getattr(event,self.leptonTag) self.IsolationComputer.setPackedCandidates(self.handles['pf'].product()) forIso = [] for ipf,p in enumerate(pf): if p.pdgId() != 22 or not( p.pt() > 2.0 and abs(p.eta()) < 2.4 ): continue if self.cfg_ana.electronVeto != None: scVetoed = False for l in leptons: if abs(l.pdgId())==11 and self.electronID(l): #print "Testing photon pt %5.1f eta %+7.4f phi %+7.4f vs ele pt %.1f eta %+7.4f phi %+7.4f sc eta %+7.4f phi %+7.4f" % ( p.pt(), p.eta(), p.phi(), l.pt(), l.eta(), l.phi(), l.superCluster().eta(), l.superCluster().phi() ) #print "Testing deta %+7.4f dphi %+7.4f sc deta %+7.4f dphi %+7.4f" % ( abs(p.eta()-l.eta()), deltaPhi(p.phi(),l.phi()), abs(p.eta()-l.superCluster().eta()), deltaPhi(p.phi(),l.superCluster().phi())) if self.cfg_ana.electronVeto == "superclusterEta": if (abs(p.eta()-l.superCluster().eta())<0.05 and abs(deltaPhi(p.phi(),l.superCluster().phi()))<2) or deltaR(p.eta(),p.phi(),l.superCluster().eta(),l.superCluster().phi())<0.15: scVetoed = True; break elif self.cfg_ana.electronVeto == "electronEta": if (abs(p.eta()-l.eta())<0.05 and abs(deltaPhi(p.phi(),l.phi()))<2) or deltaR(p.eta(),p.phi(),l.eta(),l.phi())<0.15: scVetoed = True; break elif self.cfg_ana.electronVeto == "pfCandReference": pfcrefs = l.associatedPackedPFCandidates() for iref in xrange(pfcrefs.size()): pfcref = pfcrefs[iref] if pfcref.key() == ipf: #print "Testing photon pt %5.1f eta %+7.4f phi %+7.4f " % ( p.pt(), p.eta(), p.phi() ) #print " pfcand ref pt %5.1f eta %+7.4f phi %+7.4f " % ( pfcref.get().pt(), pfcref.get().eta(), pfcref.get().phi() ) #print " from elec pt %5.1f eta %+7.4f phi %+7.4f " % ( l.pt(), l.eta(), l.phi() ) scVetoed = True; else: raise RuntimeError, "electronVeto option %r not implemented" % self.cfg_ana.electronVeto if scVetoed: continue closestLepton, minDR2 = bestMatch(p, leptons) if minDR2 >= 0.5*0.5: continue p.globalClosestLepton = closestLepton forIso.append(p) isolatedPhotons = [] relIsoCut = self.cfg_ana.relIsoCut for g in forIso: g.absIsoCH = self.IsolationComputer.chargedAbsIso(g,0.3,0.0001,0.2) g.absIsoPU = self.IsolationComputer.puAbsIso(g,0.3,0.0001,0.2) g.absIsoNH = self.IsolationComputer.neutralHadAbsIsoRaw(g,0.3,0.01,0.5) g.absIsoPH = self.IsolationComputer.photonAbsIsoRaw(g,0.3,0.01,0.5) g.relIso = (g.absIsoCH+g.absIsoPU+g.absIsoNH+g.absIsoPH)/g.pt() if g.relIso < relIsoCut: isolatedPhotons.append(g) event.fsrPhotonsNoIso = forIso event.fsrPhotonsIso = isolatedPhotons event.attachedFsrPhotons = [] drOverET2Cut = self.cfg_ana.drOverET2Cut for l in leptons: best = None for p in event.fsrPhotonsIso: if p.globalClosestLepton != l: continue drOverET2 = deltaR(p.eta(),p.phi(),l.eta(),l.phi())/p.et2() if drOverET2 >= drOverET2Cut: continue p.drOverET2 = drOverET2 if best == None or best.drOverET2 > drOverET2: best = p if best: event.attachedFsrPhotons.append(best) l.ownFsrPhotons = [ best ] else: l.ownFsrPhotons = [ ] #now attach FSR photons to all leptons (for isolation) for l in leptons: l.fsrPhotons = inConeCollection(l, event.attachedFsrPhotons, 0.5, -1) l.relIsoAfterFSR = l.absIsoWithFSR(R=0.3)/l.pt() #define list of FSR photons attached to photons that pass post-FSR iso, for jet cleaning event.selectedPhotons = [] for l in leptons: if l.tightId() and l.relIsoAfterFSR < 0.35: event.selectedPhotons += l.ownFsrPhotons return True
def process(self, event): self.readCollections(event.input) self.counters.counter('BKstLLGenAnalyzer').inc('all events') # attach qscale (pt hat) to the event event.qscale = self.mchandles['genInfo'].product().qScale() # get the tracks allpf = map(PhysicsObject, self.handles['pfcands'].product()) losttracks = map(PhysicsObject, self.handles['losttracks'].product()) # merge the track collections event.alltracks = sorted([ tt for tt in allpf + losttracks if tt.charge() != 0 and abs(tt.pdgId()) not in (11, 13) ], key=lambda x: x.pt(), reverse=True) # import pdb ; pdb.set_trace() # get the offline electrons and muons event.electrons = map(Electron, self.handles['electrons'].product()) event.muons = map(Muon, self.handles['muons'].product()) # find the gen B mesons from the hard scattering pruned_gen_particles = self.mchandles['prunedGenParticles'].product() packed_gen_particles = self.mchandles['packedGenParticles'].product() all_gen_particles = [ip for ip in pruned_gen_particles ] + [ip for ip in packed_gen_particles] # match gen mu to offline mu genmus = [ ii for ii in all_gen_particles if abs(ii.pdgId()) == 13 and ii.status() == 1 ] for imu in genmus: bm, dr = bestMatch(imu, event.muons) if dr < 0.3: imu.reco = bm if len(genmus) > 0: event.thetagmu = sorted(genmus, key=lambda x: x.pt(), reverse=True)[0] # match gen ele to offline ele geneles = [ ii for ii in all_gen_particles if abs(ii.pdgId()) == 11 and ii.status() == 1 ] for iele in geneles: bm, dr = bestMatch(iele, event.electrons) if dr < 0.3: iele.reco = bm event.gen_bmesons = [ pp for pp in pruned_gen_particles if abs(pp.pdgId()) > 500 and abs(pp.pdgId()) < 600 and pp.isPromptDecayed() ] event.gen_b0mesons = [ pp for pp in pruned_gen_particles if abs(pp.pdgId()) == 511 ] # walk down the lineage of the B mesons and find the final state muons and charged particles for ip in event.gen_b0mesons + event.gen_bmesons: if getattr(self.cfg_ana, 'verbose', False): print 'PdgId : %s pt : %s eta : %s phi : %s' % ( ip.pdgId(), ip.pt(), ip.eta(), ip.phi()) print ' daughters' finaldaughters = [] finalcharged = [] finalmuons = [] for ipp in packed_gen_particles: mother = ipp.mother(0) if mother and self.isAncestor(ip, mother): if abs(ipp.pdgId()) == 13: finalmuons.append(ipp) if abs(ipp.charge()) == 1: finalcharged.append(ipp) if getattr(self.cfg_ana, 'verbose', False): print ' PdgId : %s pt : %s eta : %s phi : %s' % ( ipp.pdgId(), ipp.pt(), ipp.eta(), ipp.phi()) finaldaughters.append(ipp) if getattr(self.cfg_ana, 'verbose', False): print ' PdgId : %s pt : %s eta : %s phi : %s' % ( ipp.pdgId(), ipp.pt(), ipp.eta(), ipp.phi()) ip.finalmuondaughters = sorted(finalmuons, key=lambda x: x.pt(), reverse=True) ip.finalchargeddaughters = sorted(finalcharged, key=lambda x: x.pt(), reverse=True) ip.finaldaughters = sorted(finaldaughters, key=lambda x: x.pt(), reverse=True) for ib0 in event.gen_b0mesons: if abs(self.cfg_ana.flavour) == 11: togenmatchleptons = event.electrons elif abs(self.cfg_ana.flavour) == 13: togenmatchleptons = event.muons else: print 'you can only pick either pdgId 11 or 13' raise isit, lp, lm, pi, k = self.isKstLL(ib0, togenmatchleptons, event.alltracks, abs(self.cfg_ana.flavour)) if isit: event.kstll = ib0 event.kstll.lp = lp event.kstll.lm = lm event.kstll.pi = pi event.kstll.k = k event.kstll.dr = min( [deltaR(event.kstll, jj) for jj in [lp, lm, pi, k]]) break # yeah, only one at a time, mate! # if hasattr(event.kstll.lp, 'reco') and hasattr(event.kstll.lm, 'reco'): # if event.kstll.lp.reco.pt() == event.kstll.lm.reco.pt(): # import pdb ; pdb.set_trace() if not hasattr(event, 'kstll'): return False self.counters.counter('BKstLLGenAnalyzer').inc( 'has a good gen B0->K*LL') toclean = None if event.kstll.isPromptDecayed(): toclean = event.kstll else: for ip in event.gen_bmesons: if self.isAncestor(ip, event.kstll): toclean = ip break # if toclean is None: # print 'nothing to clean lumi %d, ev %d' %(event.lumi, event.eventId) # return False # import pdb ; pdb.set_trace() # # self.counters.counter('BKstLLGenAnalyzer').inc('no f**k ups') # elif abs(event.kstll.mother(0).pdgId())>500 and abs(event.kstll.mother(0).pdgId())<600: # if toclean = event.kstll.mother(0) # elif abs(event.kstll.mother(0).mother(0).pdgId())>500 and abs(event.kstll.mother(0).mother(0).pdgId())<600: # else: # print 'nothing to clean lumi %d, ev %d' %(event.lumi, event.eventId) # import pdb ; pdb.set_trace() if toclean is not None: event.clean_gen_bmesons = [ ib for ib in event.gen_bmesons if ib != toclean ] else: event.clean_gen_bmesons = event.gen_bmesons # import pdb ; pdb.set_trace() # now find the L1 muons from BX = 0 L1muons_allbx = self.handles['L1muons'].product() L1_muons = [] for jj in range(L1muons_allbx.size(0)): L1_muons.append(L1muons_allbx.at(0, jj)) event.L1_muons = L1_muons event.selectedLeptons = [ ] # don't really care about isolated leptons, right? return True
def process(self, event): ''' ''' self.readCollections(event.input) self.tree.reset() self.event = event # event variables self.fillEvent(self.tree, event) self.fill(self.tree, 'n_cands', len(event.dimuonsvtx)) self.fill(self.tree, 'rho', event.rho) # reco HNL self.fillHNL(self.tree, 'hnl', event.the_3lep_cand) self.fill(self.tree, 'hnl_iso03_abs_rhoArea', event.the_3lep_cand.abs_tot_iso03_rhoArea) self.fill(self.tree, 'hnl_iso04_abs_rhoArea', event.the_3lep_cand.abs_tot_iso04_rhoArea) self.fill(self.tree, 'hnl_iso05_abs_rhoArea', event.the_3lep_cand.abs_tot_iso05_rhoArea) self.fill(self.tree, 'hnl_iso03_abs_deltaBeta', event.the_3lep_cand.abs_tot_iso03_deltaBeta) self.fill(self.tree, 'hnl_iso04_abs_deltaBeta', event.the_3lep_cand.abs_tot_iso04_deltaBeta) self.fill(self.tree, 'hnl_iso05_abs_deltaBeta', event.the_3lep_cand.abs_tot_iso05_deltaBeta) # self.fill (self.tree, 'hnl_iso_abs_met' , event.the_3lep_cand.abs_ch_iso_met ) self.fill(self.tree, 'hnl_iso03_rel_rhoArea', event.the_3lep_cand.rel_tot_iso03_rhoArea) self.fill(self.tree, 'hnl_iso04_rel_rhoArea', event.the_3lep_cand.rel_tot_iso04_rhoArea) self.fill(self.tree, 'hnl_iso05_rel_rhoArea', event.the_3lep_cand.rel_tot_iso05_rhoArea) self.fill(self.tree, 'hnl_iso03_rel_deltaBeta', event.the_3lep_cand.rel_tot_iso03_deltaBeta) self.fill(self.tree, 'hnl_iso04_rel_deltaBeta', event.the_3lep_cand.rel_tot_iso04_deltaBeta) self.fill(self.tree, 'hnl_iso05_rel_deltaBeta', event.the_3lep_cand.rel_tot_iso05_deltaBeta) # self.fill (self.tree, 'hnl_iso_rel_met' , event.the_3lep_cand.rel_ch_iso_met ) self.fillMuon(self.tree, 'l1', event.the_3lep_cand.l1()) self.fillMuon(self.tree, 'l2', event.the_3lep_cand.l2()) if self.cfg_ana.promptLepType == 'ele': self.fillEle(self.tree, 'l0', event.the_3lep_cand.l0()) if self.cfg_ana.promptLepType == 'mu': self.fillMuon(self.tree, 'l0', event.the_3lep_cand.l0()) # output of MC analysis ONLY FOR SIGNAL if hasattr(event, 'the_hnl'): self.fillHNL(self.tree, 'hnl_gen', event.the_hnl) self.fillParticle(self.tree, 'l0_gen', event.the_hnl.l0()) self.fillParticle(self.tree, 'l1_gen', event.the_hnl.l1()) self.fillParticle(self.tree, 'l2_gen', event.the_hnl.l2()) self.fillParticle(self.tree, 'n_gen', event.the_hnl.met()) # reco primary vertex pv = event.goodVertices[0] self.fill(self.tree, 'pv_x', pv.x()) self.fill(self.tree, 'pv_y', pv.y()) self.fill(self.tree, 'pv_z', pv.z()) self.fill(self.tree, 'pv_xe', pv.xError()) self.fill(self.tree, 'pv_ye', pv.yError()) self.fill(self.tree, 'pv_ze', pv.zError()) # true primary vertex if hasattr(event, 'the_hnl'): self.fill(self.tree, 'pv_gen_x', event.the_hn.vx()) self.fill(self.tree, 'pv_gen_y', event.the_hn.vy()) self.fill(self.tree, 'pv_gen_z', event.the_hn.vz()) # beamspot self.fill(self.tree, 'bs_x', event.beamspot.x0()) self.fill(self.tree, 'bs_y', event.beamspot.y0()) self.fill(self.tree, 'bs_z', event.beamspot.z0()) self.fill(self.tree, 'bs_sigma_x', event.beamspot.BeamWidthX()) self.fill(self.tree, 'bs_sigma_y', event.beamspot.BeamWidthY()) self.fill(self.tree, 'bs_sigma_z', event.beamspot.sigmaZ()) self.fill(self.tree, 'bs_dxdz', event.beamspot.dxdz()) self.fill(self.tree, 'bs_dydz', event.beamspot.dydz()) # true HN decay vertex if hasattr(event, 'the_hn'): self.fill(self.tree, 'sv_gen_x', event.the_hn.lep1.vertex().x() ) # don't use the final lepton to get the vertex from! self.fill(self.tree, 'sv_gen_y', event.the_hn.lep1.vertex().y() ) # don't use the final lepton to get the vertex from! self.fill(self.tree, 'sv_gen_z', event.the_hn.lep1.vertex().z() ) # don't use the final lepton to get the vertex from! # displacements self.fill(self.tree, 'hnl_2d_gen_disp', displacement2D(event.the_hn.lep1, event.the_hn)) self.fill(self.tree, 'hnl_3d_gen_disp', displacement3D(event.the_hn.lep1, event.the_hn)) # HLT bits & matches trig_list = [trig.name for trig in event.trigger_infos if trig.fired] if self.cfg_ana.promptLepType == 'ele': self.fill( self.tree, 'hlt_Ele27_WPTight_Gsf', any('HLT_Ele27_WPTight_Gsf' in name for name in trig_list)) self.fill( self.tree, 'hlt_Ele32_WPTight_Gsf', any('HLT_Ele32_WPTight_Gsf' in name for name in trig_list)) self.fill( self.tree, 'hlt_Ele35_WPTight_Gsf', any('HLT_Ele35_WPTight_Gsf' in name for name in trig_list)) self.fill( self.tree, 'hlt_Ele115_CaloIdVT_GsfTrkIdT', any('HLT_Ele115_CaloIdVT_GsfTrkIdT' in name for name in trig_list)) self.fill( self.tree, 'hlt_Ele135_CaloIdVT_GsfTrkIdT', any('HLT_Ele135_CaloIdVT_GsfTrkIdT' in name for name in trig_list)) if self.cfg_ana.promptLepType == 'mu': self.fill(self.tree, 'hlt_soMu24', any('HLT_IsoMu24' in name for name in trig_list)) self.fill(self.tree, 'hlt_soMu27', any('HLT_IsoMu27' in name for name in trig_list)) self.fill(self.tree, 'hlt_u50', any('HLT_Mu50' in name for name in trig_list)) # reco secondary vertex and displacement self.fill(self.tree, 'sv_x', event.recoSv.x()) self.fill(self.tree, 'sv_y', event.recoSv.y()) self.fill(self.tree, 'sv_z', event.recoSv.z()) self.fill(self.tree, 'sv_xe', event.recoSv.xError()) self.fill(self.tree, 'sv_ye', event.recoSv.yError()) self.fill(self.tree, 'sv_ze', event.recoSv.zError()) self.fill(self.tree, 'sv_prob', event.recoSv.prob) self.fill(self.tree, 'sv_cos', event.recoSv.disp2DFromBS_cos) self.fill(self.tree, 'hnl_2d_disp', event.recoSv.disp2DFromBS.value()) # from beamspot self.fill(self.tree, 'hnl_3d_disp', event.recoSv.disp3DFromBS.value()) # from PV self.fill(self.tree, 'hnl_2d_disp_sig', event.recoSv.disp2DFromBS_sig) # from beamspot self.fill(self.tree, 'hnl_3d_disp_sig', event.recoSv.disp3DFromBS_sig) # from PV # jet/met variables self.fillExtraMetInfo(self.tree, event) # set_trace() # met filter flags self.fill(self.tree, 'Flag_goodVertices', event.Flag_goodVertices) self.fill(self.tree, 'Flag_globalSuperTightHalo2016Filter', event.Flag_globalSuperTightHalo2016Filter) self.fill(self.tree, 'Flag_HBHENoiseFilter', event.Flag_HBHENoiseFilter) self.fill(self.tree, 'Flag_HBHENoiseIsoFilter', event.Flag_HBHENoiseIsoFilter) self.fill(self.tree, 'Flag_EcalDeadCellTriggerPrimitiveFilter', event.Flag_EcalDeadCellTriggerPrimitiveFilter) self.fill(self.tree, 'Flag_BadPFMuonFilter', event.Flag_BadPFMuonFilter) self.fill(self.tree, 'Flag_BadChargedCandidateFilter', event.Flag_BadChargedCandidateFilter) self.fill(self.tree, 'Flag_eeBadScFilter', event.Flag_eeBadScFilter) self.fill(self.tree, 'Flag_ecalBadCalibFilter', event.Flag_ecalBadCalibFilter) # self.fill(self.tree, 'Flag_any_met_filters', event.Flag_goodVertices or event.Flag_globalSuperTightHalo2016Filter or event.Flag_HBHENoiseFilter or event.Flag_HBHENoiseIsoFilter or event.Flag_EcalDeadCellTriggerPrimitiveFilter or event.Flag_BadPFMuonFilter or event.Flag_BadChargedCandidateFilter or event.Flag_eeBadScFilter or event.Flag_ecalBadCalibFilter) if len(event.cleanJets) > 0: self.fillJet(self.tree, 'j1', event.cleanJets[0], fill_extra=False) if len(event.cleanJets) > 1: self.fillJet(self.tree, 'j2', event.cleanJets[1], fill_extra=False) if len(event.cleanBJets) > 0: self.fillJet(self.tree, 'bj1', event.cleanBJets[0], fill_extra=False) if len(event.cleanBJets) > 1: self.fillJet(self.tree, 'bj2', event.cleanBJets[1], fill_extra=False) self.fill(self.tree, 'htj', event.HT_cleanJets) self.fill(self.tree, 'htbj', event.HT_bJets) self.fill(self.tree, 'nj', len(event.cleanJets)) self.fill(self.tree, 'nbj', len(event.cleanBJets)) # gen match if self.cfg_comp.isMC == True: stable_genp = [ pp for pp in event.genParticles if ((pp.status() == 23 or pp.status() == 1) and ( pp.vertex().z() != 0)) ] stable_genp += [ pp for pp in event.genp_packed if ((pp.status() == 23 or pp.status() == 1) and ( pp.vertex().z() != 0)) ] # particle status: http://home.thep.lu.se/~torbjorn/pythia81html/ParticleProperties.html # 1 ... stable; 23 ... from hardest scattering subprocess tomatch = [(event.the_3lep_cand.l0(), 0.05 * 0.05), (event.the_3lep_cand.l1(), 0.2 * 0.2), (event.the_3lep_cand.l2(), 0.2 * 0.2)] for ilep, idr2 in tomatch: bestmatch, dr2 = bestMatch(ilep, stable_genp) if (dr2 < idr2 and abs( (ilep.pt() - bestmatch.pt()) / ilep.pt()) < 0.2): ilep.bestmatch = bestmatch # relevant for signal: check if reco matched with gen, save a bool if hasattr(event.the_3lep_cand.l0(), 'bestmatch'): self.fillSimpleGenParticle(self.tree, 'l0_gen_match', event.the_3lep_cand.l0().bestmatch) if hasattr(event.the_3lep_cand.l1(), 'bestmatch'): self.fillSimpleGenParticle(self.tree, 'l1_gen_match', event.the_3lep_cand.l1().bestmatch) if hasattr(event.the_3lep_cand.l2(), 'bestmatch'): self.fillSimpleGenParticle(self.tree, 'l2_gen_match', event.the_3lep_cand.l2().bestmatch) # FIXME! matching by pointer does not work, so let's trick it with deltaR if hasattr(event, 'the_hnl'): if hasattr(event.the_3lep_cand.l0(), 'bestmatch'): self.fill( self.tree, 'l0_is_real', deltaR(event.the_3lep_cand.l0().bestmatch, event.the_hnl.l0()) < 0.01) if hasattr(event.the_3lep_cand.l1(), 'bestmatch'): self.fill( self.tree, 'l1_is_real', deltaR(event.the_3lep_cand.l1().bestmatch, event.the_hnl.l1()) < 0.05) if hasattr(event.the_3lep_cand.l2(), 'bestmatch'): self.fill( self.tree, 'l2_is_real', deltaR(event.the_3lep_cand.l2().bestmatch, event.the_hnl.l2()) < 0.05) # extra lepton veto self.fill(self.tree, 'pass_e_veto', len(event.veto_eles) == 0) self.fill(self.tree, 'pass_m_veto', len(event.veto_mus) == 0) # save vetoing lepton invariant masses if len(event.veto_eles): self.fillEle(self.tree, 'veto_ele', event.veto_save_ele) self.fill(self.tree, 'hnl_m_0Vele', (event.veto_save_ele.p4() + event.the_3lep_cand.l0().p4()).mass()) self.fill(self.tree, 'hnl_m_1Vele', (event.veto_save_ele.p4() + event.the_3lep_cand.l1().p4()).mass()) self.fill(self.tree, 'hnl_m_2Vele', (event.veto_save_ele.p4() + event.the_3lep_cand.l2().p4()).mass()) if len(event.veto_mus): self.fillMuon(self.tree, 'veto_mu', event.veto_save_mu) self.fill(self.tree, 'hnl_m_0Vmu', (event.veto_save_mu.p4() + event.the_3lep_cand.l0().p4()).mass()) self.fill(self.tree, 'hnl_m_1Vmu', (event.veto_save_mu.p4() + event.the_3lep_cand.l1().p4()).mass()) self.fill(self.tree, 'hnl_m_2Vmu', (event.veto_save_mu.p4() + event.the_3lep_cand.l2().p4()).mass()) # LHE weight self.fill(self.tree, 'lhe_weight', np.sign(getattr(event, 'LHE_originalWeight', 1.))) self.fillTree(event)
def makeLeptons(self, event): ### inclusive leptons = all leptons that could be considered somewhere in the analysis, with minimal requirements (used e.g. to match to MC) event.inclusiveLeptons = [] ### selected leptons = subset of inclusive leptons passing some basic id definition and pt requirement ### other leptons = subset of inclusive leptons failing some basic id definition and pt requirement event.selectedLeptons = [] event.selectedMuons = [] event.selectedElectrons = [] event.otherLeptons = [] #muons allmuons = self.makeAllMuons(event) for mu in allmuons: # inclusive, very loose, selection if (mu.track().isNonnull() and mu.muonID(self.cfg_ana.inclusive_muon_id) and mu.pt()>self.cfg_ana.inclusive_muon_pt and abs(mu.eta())<self.cfg_ana.inclusive_muon_eta and abs(mu.dxy())<self.cfg_ana.inclusive_muon_dxy and abs(mu.dz())<self.cfg_ana.inclusive_muon_dz): event.inclusiveLeptons.append(mu) # basic selection if (mu.muonID(self.cfg_ana.loose_muon_id) and mu.pt() > self.cfg_ana.loose_muon_pt and abs(mu.eta()) < self.cfg_ana.loose_muon_eta and abs(mu.dxy()) < self.cfg_ana.loose_muon_dxy and abs(mu.dz()) < self.cfg_ana.loose_muon_dz and mu.relIso03 < self.cfg_ana.loose_muon_relIso and mu.absIso03 < (self.cfg_ana.loose_muon_absIso if hasattr(self.cfg_ana,'loose_muon_absIso') else 9e99)): mu.looseIdSusy = True event.selectedLeptons.append(mu) event.selectedMuons.append(mu) else: mu.looseIdSusy = False event.otherLeptons.append(mu) #electrons allelectrons = self.makeAllElectrons(event) looseMuons = event.selectedLeptons[:] for ele in allelectrons: ## remove muons if muForEleCrossCleaning is not empty ## apply selection if ( ele.electronID(self.cfg_ana.inclusive_electron_id) and ele.pt()>self.cfg_ana.inclusive_electron_pt and abs(ele.eta())<self.cfg_ana.inclusive_electron_eta and abs(ele.dxy())<self.cfg_ana.inclusive_electron_dxy and abs(ele.dz())<self.cfg_ana.inclusive_electron_dz and ele.lostInner()<=self.cfg_ana.inclusive_electron_lostHits ): event.inclusiveLeptons.append(ele) # basic selection if (ele.electronID(self.cfg_ana.loose_electron_id) and ele.pt()>self.cfg_ana.loose_electron_pt and abs(ele.eta())<self.cfg_ana.loose_electron_eta and abs(ele.dxy()) < self.cfg_ana.loose_electron_dxy and abs(ele.dz())<self.cfg_ana.loose_electron_dz and ele.relIso03 <= self.cfg_ana.loose_electron_relIso and ele.absIso03 < (self.cfg_ana.loose_electron_absIso if hasattr(self.cfg_ana,'loose_electron_absIso') else 9e99) and ele.lostInner() <= self.cfg_ana.loose_electron_lostHits and ( True if (hasattr(self.cfg_ana,'notCleaningElectrons') and self.cfg_ana.notCleaningElectrons) else (bestMatch(ele, looseMuons)[1] > (self.cfg_ana.min_dr_electron_muon**2)) )): event.selectedLeptons.append(ele) event.selectedElectrons.append(ele) ele.looseIdSusy = True else: event.otherLeptons.append(ele) ele.looseIdSusy = False event.otherLeptons.sort(key = lambda l : l.pt(), reverse = True) event.selectedLeptons.sort(key = lambda l : l.pt(), reverse = True) event.selectedMuons.sort(key = lambda l : l.pt(), reverse = True) event.selectedElectrons.sort(key = lambda l : l.pt(), reverse = True) event.inclusiveLeptons.sort(key = lambda l : l.pt(), reverse = True) for lepton in event.selectedLeptons: if hasattr(self,'efficiency'): self.efficiency.attachToObject(lepton)
abs(jet.eta()) < 3.0 and jet.pt() < 200.5) ] jets = removeOverlap(all_jets, genLeptons) event.getByLabel("slimmedGenJets", genJetH) all_gen_jets = [ jet for jet in genJetH.product() if (jet.pt() > 20 and abs(jet.eta()) < 3.0 and jet.pt() < 200.5) ] gen_jets = removeOverlap(all_gen_jets, genLeptons) matched_jets = [] for jet in jets: genjet, dr2 = bestMatch(jet, gen_jets) if dr2 < 0.01: matched_jets.append(jet) refObjs = copy.deepcopy(matched_jets) elif runtype in ele_run_types: refObjs = copy.deepcopy(genElectrons) elif runtype in muon_run_types: refObjs = copy.deepcopy(genMuons) ### Matched = MatchTausToJets(refObjs) ### h_ngen.Fill(len(refObjs)) for refidx,refObj in enumerate(refObjs): for var in all_vars:
def process(self, event, fill=True): ''' ''' self.readCollections(event.input) self.tree.reset() self.counters.counter('HNLTreeProducer').inc('all events') # save the event only if it is in the correct final state if not eval(self.finalStateFilter): return True self.counters.counter('HNLTreeProducer').inc('pass final state') # get ahold of the objects to save final_state = self.cfg_ana.promptLepType + self.cfg_ana.L1L2LeptonType dileptonsvtx = event.dileptonsvtx_dict[final_state] the_3lep_cand = event.the_3lep_cand_dict[final_state] recoSv = event.recoSv_dict[final_state] # save the event only if it passes the skim selection (if it exists) # import pdb ; pdb.set_trace() if not eval(self.skimFilter): return True self.counters.counter('HNLTreeProducer').inc('pass skim') # also cleaned jet collections depend on the final state cleanJets = event.cleanJets[final_state] cleanBJets = event.cleanBJets[final_state] cleanJets30 = event.cleanJets30[final_state] # adjust the weights, according to the final state event.eventWeight = getattr(event, 'puWeight', 1.) * \ getattr(event, 'LHE_originalWeight', 1.) * \ getattr(event, 'weight_%s' %final_state, 1.) the_3lep_cand.l0().weight = getattr(the_3lep_cand.l0(), 'weight_%s' % final_state, 1.) the_3lep_cand.l0().weight_id = getattr(the_3lep_cand.l0(), 'weight_%s_id' % final_state, 1.) the_3lep_cand.l0().weight_iso = getattr(the_3lep_cand.l0(), 'weight_%s_iso' % final_state, 1.) the_3lep_cand.l0().weight_reco = getattr( the_3lep_cand.l0(), 'weight_%s_reco' % final_state, 1.) the_3lep_cand.l0().weight_idiso = getattr( the_3lep_cand.l0(), 'weight_%s_idiso' % final_state, 1.) the_3lep_cand.l0().weight_trigger = getattr( the_3lep_cand.l0(), 'weight_%s_trigger' % final_state, 1.) the_3lep_cand.l0().weight_tracking = getattr( the_3lep_cand.l0(), 'weight_%s_tracking' % final_state, 1.) the_3lep_cand.l1().weight = getattr(the_3lep_cand.l1(), 'weight_%s' % final_state, 1.) the_3lep_cand.l1().weight_id = getattr(the_3lep_cand.l1(), 'weight_%s_id' % final_state, 1.) the_3lep_cand.l1().weight_iso = getattr(the_3lep_cand.l1(), 'weight_%s_iso' % final_state, 1.) the_3lep_cand.l1().weight_reco = getattr( the_3lep_cand.l1(), 'weight_%s_reco' % final_state, 1.) the_3lep_cand.l1().weight_idiso = getattr( the_3lep_cand.l1(), 'weight_%s_idiso' % final_state, 1.) the_3lep_cand.l1().weight_trigger = getattr( the_3lep_cand.l1(), 'weight_%s_trigger' % final_state, 1.) the_3lep_cand.l1().weight_tracking = getattr( the_3lep_cand.l1(), 'weight_%s_tracking' % final_state, 1.) the_3lep_cand.l2().weight = getattr(the_3lep_cand.l2(), 'weight_%s' % final_state, 1.) the_3lep_cand.l2().weight_id = getattr(the_3lep_cand.l2(), 'weight_%s_id' % final_state, 1.) the_3lep_cand.l2().weight_iso = getattr(the_3lep_cand.l2(), 'weight_%s_iso' % final_state, 1.) the_3lep_cand.l2().weight_reco = getattr( the_3lep_cand.l2(), 'weight_%s_reco' % final_state, 1.) the_3lep_cand.l2().weight_idiso = getattr( the_3lep_cand.l2(), 'weight_%s_idiso' % final_state, 1.) the_3lep_cand.l2().weight_trigger = getattr( the_3lep_cand.l2(), 'weight_%s_trigger' % final_state, 1.) the_3lep_cand.l2().weight_tracking = getattr( the_3lep_cand.l2(), 'weight_%s_tracking' % final_state, 1.) # event variables self.fillEvent(self.tree, event) self.fill(self.tree, 'n_cands', len(dileptonsvtx)) # these are PRESELECTED leptons according to the preselection given via cfg # reco HNL self.fillHNL(self.tree, 'hnl', the_3lep_cand) if self.cfg_ana.L1L2LeptonType == 'mm': self.fillMuon(self.tree, 'l1', the_3lep_cand.l1()) self.fillMuon(self.tree, 'l2', the_3lep_cand.l2()) if self.cfg_ana.L1L2LeptonType == 'ee': self.fillEle(self.tree, 'l1', the_3lep_cand.l1()) self.fillEle(self.tree, 'l2', the_3lep_cand.l2()) if self.cfg_ana.L1L2LeptonType == 'em': self.fillEle(self.tree, 'l1', the_3lep_cand.l1()) self.fillMuon(self.tree, 'l2', the_3lep_cand.l2()) if self.cfg_ana.promptLepType == 'e': self.fillEle(self.tree, 'l0', the_3lep_cand.l0()) if self.cfg_ana.promptLepType == 'm': self.fillMuon(self.tree, 'l0', the_3lep_cand.l0()) # output of MC analysis ONLY FOR SIGNAL if hasattr(event, 'the_hnl'): self.fillHNL(self.tree, 'hnl_gen', event.the_hnl) self.fillParticle(self.tree, 'l0_gen', event.the_hnl.l0()) self.fillParticle(self.tree, 'l1_gen', event.the_hnl.l1()) self.fillParticle(self.tree, 'l2_gen', event.the_hnl.l2()) self.fillParticle(self.tree, 'n_gen', event.the_hnl.met()) # reco primary vertex pv = event.goodVertices[0] self.fill(self.tree, 'pv_x', pv.x()) self.fill(self.tree, 'pv_y', pv.y()) self.fill(self.tree, 'pv_z', pv.z()) self.fill(self.tree, 'pv_xe', pv.xError()) self.fill(self.tree, 'pv_ye', pv.yError()) self.fill(self.tree, 'pv_ze', pv.zError()) # true primary vertex if hasattr(event, 'the_hnl'): self.fill(self.tree, 'pv_gen_x', event.the_hn.vx()) self.fill(self.tree, 'pv_gen_y', event.the_hn.vy()) self.fill(self.tree, 'pv_gen_z', event.the_hn.vz()) # beamspot self.fill(self.tree, 'bs_x', event.beamspot.x0()) self.fill(self.tree, 'bs_y', event.beamspot.y0()) self.fill(self.tree, 'bs_z', event.beamspot.z0()) self.fill(self.tree, 'bs_sigma_x', event.beamspot.BeamWidthX()) self.fill(self.tree, 'bs_sigma_y', event.beamspot.BeamWidthY()) self.fill(self.tree, 'bs_sigma_z', event.beamspot.sigmaZ()) self.fill(self.tree, 'bs_dxdz', event.beamspot.dxdz()) self.fill(self.tree, 'bs_dydz', event.beamspot.dydz()) # true HN decay vertex if hasattr(event, 'the_hn'): self.fill(self.tree, 'sv_gen_x', event.the_hn.lep1.vertex().x() ) # don't use the final lepton to get the vertex from! self.fill(self.tree, 'sv_gen_y', event.the_hn.lep1.vertex().y() ) # don't use the final lepton to get the vertex from! self.fill(self.tree, 'sv_gen_z', event.the_hn.lep1.vertex().z() ) # don't use the final lepton to get the vertex from! # displacements self.fill(self.tree, 'hnl_2d_gen_disp', displacement2D(event.the_hn.lep1, event.the_hn)) self.fill(self.tree, 'hnl_3d_gen_disp', displacement3D(event.the_hn.lep1, event.the_hn)) # HLT bits & matches trig_list = [trig.name for trig in event.trigger_infos if trig.fired] if self.cfg_ana.promptLepType == 'e': self.fill( self.tree, 'hlt_Ele25_eta2p1_WPTight_Gsf', any('HLT_Ele25_eta2p1_WPTight_Gsf' in name for name in trig_list)) self.fill( self.tree, 'hlt_Ele27_WPTight_Gsf', any('HLT_Ele27_WPTight_Gsf' in name for name in trig_list)) self.fill( self.tree, 'hlt_Ele32_WPTight_Gsf', any('HLT_Ele32_WPTight_Gsf' in name for name in trig_list)) self.fill( self.tree, 'hlt_Ele35_WPTight_Gsf', any('HLT_Ele35_WPTight_Gsf' in name for name in trig_list)) self.fill( self.tree, 'hlt_Ele115_CaloIdVT_GsfTrkIdT', any('HLT_Ele115_CaloIdVT_GsfTrkIdT' in name for name in trig_list)) self.fill( self.tree, 'hlt_Ele135_CaloIdVT_GsfTrkIdT', any('HLT_Ele135_CaloIdVT_GsfTrkIdT' in name for name in trig_list)) if self.cfg_ana.promptLepType == 'm': self.fill(self.tree, 'hlt_IsoMu22', any('HLT_IsoMu22' in name for name in trig_list)) self.fill(self.tree, 'hlt_IsoTkMu22', any('HLT_IsoTkMu22' in name for name in trig_list)) self.fill(self.tree, 'hlt_IsoMu22_eta2p1', any('HLT_IsoMu22_eta2p1' in name for name in trig_list)) self.fill( self.tree, 'hlt_IsoTkMu22_eta2p1', any('HLT_IsoTkMu22_eta2p1' in name for name in trig_list)) self.fill(self.tree, 'hlt_IsoMu24', any('HLT_IsoMu24' in name for name in trig_list)) self.fill(self.tree, 'hlt_IsoTkMu24', any('HLT_IsoTkMu24' in name for name in trig_list)) self.fill(self.tree, 'hlt_IsoMu27', any('HLT_IsoMu27' in name for name in trig_list)) self.fill(self.tree, 'hlt_IsoTkMu27', any('HLT_IsoTkMu27' in name for name in trig_list)) self.fill(self.tree, 'hlt_Mu50', any('HLT_Mu50' in name for name in trig_list)) self.fill(self.tree, 'hlt_TkMu50', any('HLT_TkMu50' in name for name in trig_list)) # reco secondary vertex and displacement self.fillVertex(self.tree, 'sv', recoSv) self.fill(self.tree, 'hnl_2d_disp', recoSv.disp2DFromBS.value()) # from beamspot self.fill(self.tree, 'hnl_3d_disp', recoSv.disp3DFromBS.value()) # from PV self.fill(self.tree, 'hnl_2d_disp_sig', recoSv.disp2DFromBS_sig) # from beamspot self.fill(self.tree, 'hnl_3d_disp_sig', recoSv.disp3DFromBS_sig) # from PV # jet/met variables self.fillExtraMetInfo(self.tree, event) # met filter flags self.fill(self.tree, 'pass_met_filters', event.pass_met_filters) if len(cleanJets) > 0: self.fillJet(self.tree, 'j1', cleanJets[0], fill_extra=False) if len(cleanJets) > 1: self.fillJet(self.tree, 'j2', cleanJets[1], fill_extra=False) if len(cleanBJets) > 0: self.fillJet(self.tree, 'bj1', cleanBJets[0], fill_extra=False) if len(cleanBJets) > 1: self.fillJet(self.tree, 'bj2', cleanBJets[1], fill_extra=False) self.fill(self.tree, 'nj', len(cleanJets)) self.fill(self.tree, 'nj30', len(cleanJets30)) self.fill(self.tree, 'nbj', len(cleanBJets)) # FIXME! RM what is this? # gen match if self.cfg_comp.isMC == True and hasattr(event, 'genParticles'): stable_genp = [ pp for pp in event.genParticles if pp.status() == 1 ] # and pp.vertex().z()!=0)] stable_genp += [ pp for pp in event.genp_packed if pp.status() == 1 ] # and pp.vertex().z()!=0)] # particle status: http://home.thep.lu.se/~torbjorn/pythia81html/ParticleProperties.html # 1 ... stable; 23 ... from hardest scattering subprocess # stable_genp += [pp for pp in event.genParticles if (pp.status()==23 and pp.vertex().z()!=0)] # stable_genp += [pp for pp in event.genp_packed if (pp.status()==23 and pp.vertex().z()!=0)] tomatch = [(the_3lep_cand.l0(), 0.05 * 0.05), (the_3lep_cand.l1(), 0.2 * 0.2), (the_3lep_cand.l2(), 0.2 * 0.2)] for ilep, idr2 in tomatch: bestmatch, dr2 = bestMatch(ilep, stable_genp) if (dr2 < idr2 and abs( (ilep.pt() - bestmatch.pt()) / ilep.pt()) < 0.2): ilep.bestmatch = bestmatch # relevant for mc: check if reco matched with gen, save a float if hasattr(the_3lep_cand.l0(), 'bestmatch'): LEP0 = the_3lep_cand.l0() self.fillSimpleGenParticle(self.tree, 'l0_gen_match', LEP0.bestmatch) self.fill(self.tree, 'l0_good_match', deltaR(LEP0.bestmatch, LEP0)) # if deltaR(LEP0.bestmatch, LEP0) < 0.04 and LEP0.pdgId() == LEP0.bestmatch.pdgId(): # self.fill(self.tree, 'l0_good_match', 1) if hasattr(the_3lep_cand.l1(), 'bestmatch'): LEP1 = the_3lep_cand.l1() self.fillSimpleGenParticle(self.tree, 'l1_gen_match', LEP1.bestmatch) self.fill(self.tree, 'l1_good_match', deltaR(LEP1.bestmatch, LEP1)) # if deltaR(LEP1.bestmatch, LEP1) < 0.04 and LEP1.pdgId() == LEP1.bestmatch.pdgId(): # self.fill(self.tree, 'l1_good_match', 1) if hasattr(the_3lep_cand.l2(), 'bestmatch'): LEP2 = the_3lep_cand.l2() self.fillSimpleGenParticle(self.tree, 'l2_gen_match', LEP2.bestmatch) self.fill(self.tree, 'l2_good_match', deltaR(LEP2.bestmatch, LEP2)) # if deltaR(LEP2.bestmatch, LEP2) < 0.04 and LEP2.pdgId() == LEP2.bestmatch.pdgId(): # self.fill(self.tree, 'l2_good_match', 1) # matching by pointer does not work, so let's trick it with deltaR if hasattr(event, 'the_hnl'): if hasattr(the_3lep_cand.l0(), 'bestmatch'): self.fill( self.tree, 'l0_is_real', deltaR(the_3lep_cand.l0().bestmatch, event.the_hnl.l0()) < 0.01) if hasattr(the_3lep_cand.l1(), 'bestmatch'): self.fill( self.tree, 'l1_is_real', deltaR(the_3lep_cand.l1().bestmatch, event.the_hnl.l1()) < 0.05) if hasattr(the_3lep_cand.l2(), 'bestmatch'): self.fill( self.tree, 'l2_is_real', deltaR(the_3lep_cand.l2().bestmatch, event.the_hnl.l2()) < 0.05) # print('event:', event.eventId, 'lumi:', event.lumi) # extra lepton veto self.fill(self.tree, 'pass_e_veto', len(event.veto_eles) == 0) self.fill(self.tree, 'pass_m_veto', len(event.veto_mus) == 0) # LHE weight self.fill(self.tree, 'lhe_weight', np.sign(getattr(event, 'LHE_originalWeight', 1.))) # weights for ctau reweighing (only for signal!) if 'HN3L' in self.cfg_comp.name: for iv2 in new_v2s: # 'stringify' the coupling # reduce precision to avoid nasty numbers e.g. 6.000000000000001e-05 iv2_name = np.format_float_scientific(iv2, unique=False, precision=1, exp_digits=2) iv2_name = iv2_name.replace('-', 'm') self.fill(self.tree, 'ctau_w_v2_%s' % iv2_name, event.ctau_weights[iv2]['ctau_weight']) self.fill(self.tree, 'xs_w_v2_%s' % iv2_name, event.ctau_weights[iv2]['xs_weight']) if event.the_gen_w is not None: self.fillParticle(self.tree, 'w_gen', event.the_gen_w) self.fill(self.tree, 'pass_mmm', getattr(event, 'pass_mmm', -1.)) self.fill(self.tree, 'pass_mem', getattr(event, 'pass_mem', -1.)) self.fill(self.tree, 'pass_eee', getattr(event, 'pass_eee', -1.)) self.fill(self.tree, 'pass_eem', getattr(event, 'pass_eem', -1.)) # import pdb ; pdb.set_trace() if fill: self.fillTree(event)
def process(self, event): self.tree.reset() ntuple.fillEvent(self.tree, event) ntuple.fillParticle(self.tree, 'b', event.theb) ntuple.fillParticle(self.tree, 'jpsi', event.theb.jpsi()) ntuple.fillMuon(self.tree, 'mu1' , event.theb.l0()) ntuple.fillParticle(self.tree, 'tk2' , event.theb.l1()) mu2, dR2 = bestMatch(event.theb.l1(), event.muons) if dR2<0.005*0.005 and mu2.physObj != event.theb.l0().physObj: ntuple.fillMuon(self.tree, 'mu2', mu2) ntuple.fillParticle(self.tree, 'k', event.theb.k()) ntuple.fill(self.tree, 'dr_mm' , deltaR(event.theb.l0() , event.theb.l1())) ntuple.fill(self.tree, 'dr_jpsi_k' , deltaR(event.theb.jpsi() , event.theb.k() )) ntuple.fill(self.tree, 'dr_jpsi_mu1' , deltaR(event.theb.jpsi() , event.theb.l0())) ntuple.fill(self.tree, 'dr_jpsi_mu2' , deltaR(event.theb.jpsi() , event.theb.l1())) ntuple.fill(self.tree, 'dr_mu1_k' , deltaR(event.theb.l0() , event.theb.k() )) ntuple.fill(self.tree, 'dr_mu2_k' , deltaR(event.theb.l1() , event.theb.k() )) ntuple.fill(self.tree, 'dphi_mm' , deltaPhi(event.theb.l0() .phi(), event.theb.l1().phi())) ntuple.fill(self.tree, 'dphi_jpsi_k' , deltaPhi(event.theb.jpsi().phi(), event.theb.k() .phi())) ntuple.fill(self.tree, 'dphi_jpsi_mu1', deltaPhi(event.theb.jpsi().phi(), event.theb.l0().phi())) ntuple.fill(self.tree, 'dphi_jpsi_mu2', deltaPhi(event.theb.jpsi().phi(), event.theb.l1().phi())) ntuple.fill(self.tree, 'dphi_mu1_k' , deltaPhi(event.theb.l0() .phi(), event.theb.k() .phi())) ntuple.fill(self.tree, 'dphi_mu2_k' , deltaPhi(event.theb.l1() .phi(), event.theb.k() .phi())) ntuple.fill(self.tree, 'b_cone' , event.theb.bcone()) ntuple.fill(self.tree, 'bs_x', event.beamspot.x0()) ntuple.fill(self.tree, 'bs_y', event.beamspot.y0()) ntuple.fill(self.tree, 'bs_z', event.beamspot.z0()) ntuple.fill(self.tree, 'pv_x', event.pv.x()) ntuple.fill(self.tree, 'pv_y', event.pv.y()) ntuple.fill(self.tree, 'pv_z', event.pv.z()) if event.theb.vtx().isValid(): ntuple.fill(self.tree, 'sv_x', event.theb.vtx().position().x()) ntuple.fill(self.tree, 'sv_y', event.theb.vtx().position().y()) ntuple.fill(self.tree, 'sv_z', event.theb.vtx().position().z()) ntuple.fill(self.tree, 'sv_chi2', event.theb.vtx().normalisedChiSquared()) ntuple.fill(self.tree, 'sv_prob', ROOT.TMath.Prob(event.theb.vtx().normalisedChiSquared(), 1)) ntuple.fill(self.tree, 'sv_2d_disp' , event.theb.disp2d().value()) ntuple.fill(self.tree, 'sv_2d_disp_err' , event.theb.disp2d().error()) ntuple.fill(self.tree, 'sv_2d_disp_sig' , event.theb.ls2d()) ntuple.fill(self.tree, 'sv_2d_cos' , event.theb.vtxcos()) for info, hlt in product(event.trigger_infos, ['HLT_Mu7p5_Track2_Jpsi', 'HLT_Mu7p5_Track3p5_Jpsi', 'HLT_Mu7p5_Track7_Jpsi']): if hlt in info.name: ntuple.fill(self.tree, hlt, info.fired) ntuple.fill(self.tree, hlt+'_ps', info.prescale) # ntuple.fill(self.tree, 'HLT_Mu7p5_Track2_Jpsi_v9' , any([True for info in event.trigger_infos if info.name == 'HLT_Mu7p5_Track2_Jpsi_v9' and info.fired])) # ntuple.fill(self.tree, 'HLT_Mu7p5_Track3p5_Jpsi_v9', any([True for info in event.trigger_infos if info.name == 'HLT_Mu7p5_Track3p5_Jpsi_v9' and info.fired])) # ntuple.fill(self.tree, 'HLT_Mu7p5_Track7_Jpsi_v9' , any([True for info in event.trigger_infos if info.name == 'HLT_Mu7p5_Track7_Jpsi_v9' and info.fired])) # # ntuple.fill(self.tree, 'HLT_Mu7p5_Track2_Jpsi_v9_ps' , any([True for info in event.trigger_infos if info.name == 'HLT_Mu7p5_Track2_Jpsi_v9' and info.fired])) # ntuple.fill(self.tree, 'HLT_Mu7p5_Track3p5_Jpsi_v9_ps', any([True for info in event.trigger_infos if info.name == 'HLT_Mu7p5_Track3p5_Jpsi_v9' and info.fired])) # ntuple.fill(self.tree, 'HLT_Mu7p5_Track7_Jpsi_v9_ps' , any([True for info in event.trigger_infos if info.name == 'HLT_Mu7p5_Track7_Jpsi_v9' and info.fired])) self.tree.tree.Fill()
charged_p4 = sum( (d.p4() for d in refObj.final_ds if d.charge()), ROOT.math.XYZTLorentzVectorD()) neutral_p4 = sum( (d.p4() for d in refObj.final_ds if abs(d.pdgId()) not in [12, 14, 16] and not d.charge()), ROOT.math.XYZTLorentzVectorD()) all_var_dict['gen_charged_pt'].fill(charged_p4.pt()) all_var_dict['gen_neutral_pt'].fill(neutral_p4.pt()) else: all_var_dict['gen_dm'].fill(-1) all_var_dict['gen_pt'].fill(refObj.pt()) all_var_dict['gen_eta'].fill(refObj.eta()) all_var_dict['gen_phi'].fill(refObj.phi()) electron, dr = bestMatch(refObj, electrons) if dr < 0.5: # Fill reco-tau variables if it exists... NMatchedTaus += 1 all_var_dict['electron_pt'].fill(electron.pt()) all_var_dict['electron_eta'].fill(electron.eta()) all_var_dict['electron_phi'].fill(electron.phi()) e_p = electron.trackMomentumAtVtx().R() e_sc = electron.eSuperClusterOverP() * e_p e_sc_o_p = 2 * e_sc / (e_p + e_sc) all_var_dict['electron_eSuperClusterOverP_norm'].fill(e_sc_o_p) e_seed = electron.eSeedClusterOverP() * e_p hcal = electron.hcalOverEcal() * e_seed
def process(self, event): self.readCollections(event.input) self.counters.counter('RecoGenTreeAnalyzer').inc('all events') # produce collections and map our objects to convenient Heppy objects event.muons = map(Muon, self.handles['muons'].product()) event.electrons = map(Electron, self.handles['electrons'].product()) event.photons = map(Photon, self.handles['photons'].product()) event.taus = map(Tau, self.handles['taus'].product()) event.jets = map(Jet, self.handles['jets'].product()) event.dsmuons = self.buildDisplacedMuons( self.handles['dsmuons'].product()) event.dgmuons = self.buildDisplacedMuons( self.handles['dgmuons'].product()) # vertex stuff event.pvs = self.handles['pvs'].product() event.svs = self.handles['svs'].product() event.beamspot = self.handles['beamspot'].product() # met event.met = self.handles['met'].product().at(0) # assign to the leptons the primary vertex, will be needed to compute a few quantities # FIXME! understand exactly to which extent it is reasonable to assign the PV to *all* leptons # regardless whether they're displaced or not if len(event.pvs): myvtx = event.pvs[0] else: myvtx = event.beamspot self.assignVtx(event.muons, myvtx) self.assignVtx(event.electrons, myvtx) self.assignVtx(event.photons, myvtx) self.assignVtx(event.taus, myvtx) # all matchable objects # matchable = event.electrons + event.photons + event.muons + event.taus + event.dsmuons + event.dgmuons matchable = event.electrons + event.photons + event.muons + event.taus + event.dsmuons # match gen to reco for ip in [event.the_hnl.l0(), event.the_hnl.l1(), event.the_hnl.l2()]: ip.bestmatch = None ip.bestmatchtype = None ip.matches = inConeCollection(ip, matchable, getattr(self.cfg_ana, 'drmax', 0.2), 0.) # matches the corresponding "slimmed electron" to the gen particle if len(event.electrons): dr2 = np.inf match, dr2 = bestMatch(ip, event.electrons) if dr2 < 0.04: ip.bestelectron = match # matches the corresponding "slimmed photon" to the gen particle if len(event.photons): dr2 = np.inf match, dr2 = bestMatch(ip, event.photons) if dr2 < 0.04: ip.bestphoton = match # matches the corresponding "slimmed muon" to the gen particle if len(event.muons): dr2 = np.inf match, dr2 = bestMatch(ip, event.muons) if dr2 < 0.04: ip.bestmuon = match # matches the corresponding "slimmed tau" to the gen particle if len(event.taus): dr2 = np.inf match, dr2 = bestMatch(ip, event.taus) if dr2 < 0.04: ip.besttau = match # matches the corresponding "displaced stand alone muon" to the gen particle if len(event.dsmuons): dr2 = np.inf match, dr2 = bestMatch(ip, event.dsmuons) if dr2 < 0.04: ip.bestdsmuon = match # matches the corresponding "displaced global muon" to the gen particle if len(event.dgmuons): dr2 = np.inf match, dr2 = bestMatch(ip, event.dgmuons) if dr2 < 0.04: ip.bestdgmuon = match # to find the best match, give precedence to any matched # particle in the matching cone with the correct PDG ID # then to the one which is closest ip.matches.sort(key=lambda x: (x.pdgId() == ip.pdgId(), -deltaR(x, ip)), reverse=True) if len(ip.matches) and abs(ip.pdgId()) == abs( ip.matches[0].pdgId()): ip.bestmatch = ip.matches[0] # remove already matched particles, avoid multiple matches to the same candidate while recording the type of reconstruction matchable.remove(ip.bestmatch) # record which is which if ip.bestmatch in event.electrons: ip.bestmatchtype = 11 if ip.bestmatch in event.photons: ip.bestmatchtype = 22 if ip.bestmatch in event.muons: ip.bestmatchtype = 13 if ip.bestmatch in event.taus: ip.bestmatchtype = 15 if ip.bestmatch in event.dsmuons: ip.bestmatchtype = 26 if ip.bestmatch in event.dgmuons: ip.bestmatchtype = 39 else: ip.bestmatchtype = -1 # clear it before doing it again event.recoSv = None # if hasattr(event.the_hnl.l2().bestmatch, 'pt'): # set_trace() # if (abs(event.the_hnl.l1().pt()-13.851562)<0.001): # set_trace() ######### DEBUG VTX MADE OUT OF DSA MUONS # if len(event.dsmuons) > 2: # # clear the vector # self.tofit.clear() # # create a RecoChargedCandidate for each reconstructed lepton and flush it into the vector # for il in [event.dsmuons[0], event.dsmuons[1]]: # # if the reco particle is a displaced thing, it does not have the p4() method, so let's build it # myp4 = ROOT.Math.LorentzVector('<ROOT::Math::PxPyPzE4D<double> >')(il.px(), il.py(), il.pz(), math.sqrt(il.mass()**2 + il.px()**2 + il.py()**2 + il.pz()**2)) # ic = ROOT.reco.RecoChargedCandidate() # instantiate a dummy RecoChargedCandidate # ic.setCharge(il.charge()) # assign the correct charge # ic.setP4(myp4) # assign the correct p4 # ic.setTrack(il.track()) # set the correct TrackRef # if ic.track().isNonnull(): # check that the track is valid, there are photons around too! # self.tofit.push_back(ic) # # further sanity check: two *distinct* tracks # if self.tofit.size()==2 and self.tofit[0].track() != self.tofit[1].track(): # # 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() # event.recoSv = makeRecoVertex(sv, kinVtxTrkSize=2) # need to do some gymastics # print 'good double dsa vertex! vx=%.2f, vy=%.2f, vz=%.2f' %(event.recoSv.x(), event.recoSv.y(), event.recoSv.z()) # import pdb ; pdb.set_trace() # let's refit the secondary vertex, IF both leptons match to some reco particle if not(event.the_hnl.l1().bestmatch is None or \ event.the_hnl.l2().bestmatch is None): # clear the vector self.tofit.clear() # create a RecoChargedCandidate for each reconstructed lepton and flush it into the vector for il in [ event.the_hnl.l1().bestmatch, event.the_hnl.l2().bestmatch ]: # if the reco particle is a displaced thing, it does not have the p4() method, so let's build it myp4 = ROOT.Math.LorentzVector( '<ROOT::Math::PxPyPzE4D<double> >')( il.px(), il.py(), il.pz(), math.sqrt(il.mass()**2 + il.px()**2 + il.py()**2 + il.pz()**2)) ic = ROOT.reco.RecoChargedCandidate( ) # instantiate a dummy RecoChargedCandidate ic.setCharge(il.charge()) # assign the correct charge ic.setP4(myp4) # assign the correct p4 ic.setTrack(il.track()) # set the correct TrackRef if ic.track().isNonnull( ): # check that the track is valid, there are photons around too! self.tofit.push_back(ic) # further sanity check: two *distinct* tracks if self.tofit.size( ) == 2 and self.tofit[0].track() != self.tofit[1].track(): # 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() event.recoSv = makeRecoVertex( sv, kinVtxTrkSize=2) # need to do some gymastics if event.recoSv: # primary vertex pv = event.goodVertices[0] event.recoSv.disp3DFromBS = ROOT.VertexDistance3D().distance( event.recoSv, pv) event.recoSv.disp3DFromBS_sig = event.recoSv.disp3DFromBS.significance( ) # create an 'ideal' vertex out of the BS point = ROOT.reco.Vertex.Point( event.beamspot.position().x(), event.beamspot.position().y(), event.beamspot.position().z(), ) error = event.beamspot.covariance3D() chi2 = 0. ndof = 0. bsvtx = ROOT.reco.Vertex(point, error, chi2, ndof, 2) # size? say 3? does it matter? event.recoSv.disp2DFromBS = ROOT.VertexDistanceXY().distance( event.recoSv, bsvtx) event.recoSv.disp2DFromBS_sig = event.recoSv.disp2DFromBS.significance( ) event.recoSv.prob = ROOT.TMath.Prob(event.recoSv.chi2(), int(event.recoSv.ndof())) dilep_p4 = event.the_hnl.l1().bestmatch.p4( ) + event.the_hnl.l2().bestmatch.p4() perp = ROOT.math.XYZVector(dilep_p4.px(), dilep_p4.py(), 0.) dxybs = ROOT.GlobalPoint( -1 * ((event.beamspot.x0() - event.recoSv.x()) + (event.recoSv.z() - event.beamspot.z0()) * event.beamspot.dxdz()), -1 * ((event.beamspot.y0() - event.recoSv.y()) + (event.recoSv.z() - event.beamspot.z0()) * event.beamspot.dydz()), 0) vperp = ROOT.math.XYZVector(dxybs.x(), dxybs.y(), 0.) cos = vperp.Dot(perp) / (vperp.R() * perp.R()) event.recoSv.disp2DFromBS_cos = cos # if (abs(event.the_hnl.l1().pdgId()) == 11 or abs(event.the_hnl.l2().pdgId()) == 11): # if (abs(event.the_hnl.l1().bestmatch.pdgId()) == 11 or abs(event.the_hnl.l2().bestmatch.pdgId()) == 11): # if event.recoSv: # print 'lept1 \t', event.the_hnl.l1() # print 'lept2 \t', event.the_hnl.l2() # print 'lept1 match\t', event.the_hnl.l1().bestmatch # print 'lept2 match\t', event.the_hnl.l2().bestmatch # import pdb ; pdb.set_trace() return True
mcmatch = dict((d,[]) for d in matches ) # first, match and remove the charged charged = [d for d in matches if d.charge() != 0] neutral = [d for d in matches if d.charge() == 0] ch_match = matchObjectCollection3( charged, c_tomatch, 0.07, filter = lambda d,g: abs(d.pt()-g.pt())/(d.pt()+g.pt()) < 0.2 ) gen_notused = a_tomatch[:] reco_notused = matches[:] for c in charged: g = ch_match[c] if g == None: continue mcmatch[c] = [g] gen_notused.remove(g) reco_notused.remove(c) # then assign each gen to the nearest unmatched reco that has reco pt > 0.5 * gen pt for g in gen_notused[:]: d, dr2 = bestMatch(g, reco_notused) if dr2 < 0.01 and d.pt() > 0.5*g.pt(): gen_notused.remove(g) mcmatch[d].append(g) # then take any remaining gen and just attach it to the nearest reco, except well-matched tracks rematch = neutral + [ c for c in charged if c in reco_notused ] for g in gen_notused: d, dr2 = bestMatch(g, rematch) if dr2 < 0.01: mcmatch[d].append(g) matchletters = [ "X" for mm in matchmaps ] allmatches = [ [] for mm in matchmaps ] for im,d in enumerate(matches): keyer[d.uid()] = "%s%02d" % (layerlabel,im) revkey["%s%02d" % (layerlabel,im)] = d if d.pt() < 0.8: continue print " %s%02d pt %6.2f eta %+5.2f phi %+5.2f ch %+1d dr %.2f id % +5d" % (layerlabel,im, d.pt(), d.eta(), d.phi(), d.charge(), d.dr, d.pdgId()),