def match_jets_to_quarks(jetcoll, quarkcoll, label, label_numeric): for ij, j in enumerate(jetcoll): for iq, q in enumerate(quarkcoll): # Set to 1 for bs from hadronic top # Set to 0 for bs from hadronic top # Set to -1 for other stuff if label == "tb": if q.from_had_t == 1: numeric_b_from_had_t = 1 elif q.from_had_t == 0: numeric_b_from_had_t = 0 else: numeric_b_from_had_t = -1 else: numeric_b_from_had_t = -1 #find DeltaR between jet and quark l1 = lvec(q) l2 = lvec(j) dr = l1.DeltaR(l2) if dr < 0.3: #Jet already had a match: take the one with smaller dR if not matched_pairs.has_key(ij): matched_pairs[ij] = [] matched_pairs[ij] += [(label, iq, dr, label_numeric, numeric_b_from_had_t)]
def match_jets_to_quarks(jetcoll, quarkcoll, label, label_numeric): for ij, j in enumerate(jetcoll): for iq, q in enumerate(quarkcoll): # Set to 1 for bs from hadronic top # Set to 0 for bs from hadronic top # Set to -1 for other stuff if label == "tb": if q.from_had_t == 1: numeric_b_from_had_t = 1 elif q.from_had_t == 0: numeric_b_from_had_t = 0 else: numeric_b_from_had_t = -1 else: numeric_b_from_had_t = -1 #find DeltaR between jet and quark l1 = lvec(q) l2 = lvec(j) dr = l1.DeltaR(l2) if dr < 0.3: #Jet already had a match: take the one with smaller dR if matched_pairs.has_key(ij): if matched_pairs[ij][1] > dr: matched_pairs[ij] = (label, iq, dr, label_numeric, numeric_b_from_had_t) else: matched_pairs[ij] = (label, iq, dr, label_numeric, numeric_b_from_had_t)
def _process(self, event): if "debug" in self.conf.general["verbosity"]: autolog("CommonClassifierAnalyzer started") selectedLeptonP4 = CvectorTLorentzVector() selectedLeptonCharge = Cvectordouble() selectedJetsP4 = CvectorTLorentzVector() selectedJetsCSV = Cvectordouble() looseJetsP4 = CvectorTLorentzVector() looseJetsCSV = Cvectordouble() for lep in event.good_leptons: selectedLeptonP4.push_back(lvec(lep)) selectedLeptonCharge.push_back(lep.charge) for jet in event.good_jets: selectedJetsP4.push_back(lvec(jet)) selectedJetsCSV.push_back(jet.btagCSV) looseJetsP4.push_back(lvec(jet)) looseJetsCSV.push_back(jet.btagCSV) for jet in event.loose_jets: looseJetsP4.push_back(lvec(jet)) looseJetsCSV.push_back(jet.btagCSV) metP4s = CvectorTLorentzVector() met_p4 = ROOT.TLorentzVector() met_p4.SetPtEtaPhiM(event.MET.pt, 0, event.MET.phi, 0) metP4s.push_back(met_p4) event.common_mem = [ROOT.MEMResult()] event.common_bdt = -2.0 event.common_bdt_withmem1 = -2.0 event.common_bdt_withmem2 = -2.0 if event.category_string.startswith("sl_"): event.common_bdt = self.bdtcalc_sl.GetBDTOutput(selectedLeptonP4, selectedJetsP4, selectedJetsCSV, looseJetsP4, looseJetsCSV, met_p4) if hasattr(event, "mem_results_tth"): mem_p_sig = event.mem_results_tth[self.conf.mem["methodOrder"].index("SL_0w2h2t")] mem_p_bkg = event.mem_results_ttbb[self.conf.mem["methodOrder"].index("SL_0w2h2t")] event.common_bdt_withmem1 = self.bdtcalc_sl_mem1.GetBDTOutput( selectedLeptonP4, selectedJetsP4, selectedJetsCSV, looseJetsP4, looseJetsCSV, met_p4, mem_p_sig.p/(mem_p_sig.p + 0.15 * mem_p_bkg.p) ) event.common_bdt_withmem2 = self.bdtcalc_sl_mem2.GetBDTOutput( selectedLeptonP4, selectedJetsP4, selectedJetsCSV, looseJetsP4, looseJetsCSV, met_p4, mem_p_sig.p, mem_p_bkg.p ) #FIXME #mem = self.memcalc.GetOutput(selectedLeptonP4, selectedLeptonCharge, selectedJetsP4, selectedJetsCSV, looseJetsP4, looseJetsCSV, met_p4) #event.common_mem = [mem] if event.category_string.startswith("dl_"): bdt = self.bdtcalc_dl.GetBDTOutput(selectedLeptonP4, selectedLeptonCharge, selectedJetsP4, selectedJetsCSV, met_p4) event.common_bdt = bdt if "debug" in self.conf.general["verbosity"]: print "bdt", event.category_string, event.common_bdt return event
def pair_mass(self, j1, j2): """ Calculates the invariant mass of a two-particle system. """ lv1, lv2 = [lvec(j) for j in [j1, j2]] tot = lv1 + lv2 return tot.M()
def calcFoxWolfram(objects, orders, weight_func): """ http://arxiv.org/pdf/1212.4436v1.pdf """ lvecs = [lvec(o) for o in objects] h = np.zeros(len(orders)) for i in range(len(lvecs)): for j in range(len(lvecs)): cos_omega_ij = (lvecs[i].CosTheta() * lvecs[j].CosTheta() + math.sqrt((1.0 - lvecs[i].CosTheta()**2) * (1.0 - lvecs[j].CosTheta()**2)) * (math.cos(lvecs[i].Phi() - lvecs[j].Phi())) ) w_ij = weight_func(lvecs, lvecs[i], lvecs[j]) vals = np.array([cos_omega_ij]*len(orders)) p_l = np.array(eval_legendre(orders, vals)) h += w_ij * p_l return h
def _process(self, event): if "debug" in self.conf.general["verbosity"]: autolog("GenTTHAnalyzer started") event.nMatchSimB = 0 event.nMatchSimC = 0 lv_bs = map(lvec, event.GenBQuarkFromTop) for jet in event.good_jets: lv_j = lvec(jet) if (lv_j.Pt() > 20 and abs(lv_j.Eta()) < 2.5): if any([lv_b.DeltaR(lv_j) < 0.5 for lv_b in lv_bs]): continue absid = abs(jet.mcFlavour) if absid == 5: event.nMatchSimB += 1 if absid == 4: event.nMatchSimC += 1 return event
def _process(self, event): if "debug" in self.conf.general["verbosity"]: autolog("GenTTHAnalyzer started") #Get light quarks from W/Z event.l_quarks_w = event.GenWZQuark #Get b quarks from top event.b_quarks_t = event.GenBQuarkFromTop #Get b-quarks from H event.b_quarks_h = event.GenBQuarkFromH #Get leptonic top children #note that the tau lepton might be missing event.lep_top = event.GenLepFromTop event.nu_top = event.GenNuFromTop #cat_gen - a string specifying the ttbar decay mode event.cat_gen = None #cat_gen_n - a numerical value corresponding to the string event.cat_gen_n = -1 #all leptonic and hadronic gen tops event.genTopLep = [] event.genTopHad = [] #Only run top algos if len(event.GenTop) == 2: #Gen tops might be in random order gt1 = event.GenTop[0] gt2 = event.GenTop[1] dm1 = getattr(gt1, "decayMode", -1) dm2 = getattr(gt2, "decayMode", -1) #single-leptonic if ((dm1 == 0 and dm2==1) or (dm2==0 and dm1==1)): #First top is leptonic if dm1 == 0: event.genTopLep = [gt1] event.genTopHad = [gt2] #Second top is leptonic else: event.genTopLep = [gt2] event.genTopHad = [gt1] event.cat_gen = "sl" event.cat_gen_n = 0 elif (dm1 == 0 and dm2 == 0): event.cat_gen = "dl" event.cat_gen_n = 1 event.genTopLep = [gt1, gt2] event.genTopHad = [] elif (dm1 == 1 and dm2 == 1): event.cat_gen = "fh" event.cat_gen_n = 2 event.genTopHad = [gt1, gt2] event.genTopLep = [] else: event.genTopLep = [] event.genTopHad = [] #these are the quarks that would pass selection event.l_quarks_gen = [] event.b_quarks_gen_t = [] event.b_quarks_gen_h = [] nq = 0 #Find the light quarks from W that would pass jet selection #associate them with a transfer function for q in event.l_quarks_w: nq += 1 if self.pass_jet_selection(q): q.btagFlag = 0.0 q.tth_match_label = "wq" q.tth_match_index = nq attach_jet_transfer_function(q, self.conf) event.l_quarks_gen += [q] #Find the b quarks from top that would pass jet selection #associate them with a transfer function for q in event.b_quarks_t: nq += 1 if self.pass_jet_selection(q): q.btagFlag = 1.0 q.tth_match_label = "tb" q.tth_match_index = nq attach_jet_transfer_function(q, self.conf) event.b_quarks_gen_t += [q] #Find the b quarks from Higgs that would pass jet selection #associate them with a transfer function for q in event.b_quarks_h: nq += 1 if self.pass_jet_selection(q): q.btagFlag = 1.0 q.tth_match_label = "hb" q.tth_match_index = nq attach_jet_transfer_function(q, self.conf) event.b_quarks_gen_h += [q] #Number of reco jets matched to quarks from W, top, higgs event.nSelected_wq = len(event.l_quarks_gen) event.nSelected_tb = len(event.b_quarks_gen_t) event.nSelected_hb = len(event.b_quarks_gen_h) #Get the total MET from the neutrinos spx = 0 spy = 0 for nu in event.nu_top: p4 = lvec(nu) spx += p4.Px() spy += p4.Py() event.MET_tt = MET(px=spx, py=spy) #Get the total ttH visible pt at gen level spx = 0 spy = 0 for p in (event.l_quarks_w + event.b_quarks_t + event.b_quarks_h + event.lep_top): p4 = lvec(p) spx += p4.Px() spy += p4.Py() event.tth_px_gen = spx event.tth_py_gen = spy #Calculate tth recoil #rho = -met - tth_matched event.tth_rho_px_gen = -event.MET_gen.px - event.tth_px_gen event.tth_rho_py_gen = -event.MET_gen.py - event.tth_py_gen if "gen" in self.conf.general["verbosity"]: for j in event.l_quarks_w: autolog("gen q(W)", j.pt, j.eta, j.phi, j.mass, j.pdgId) for j in event.b_quarks_t: autolog("gen b(t)", j.pt, j.eta, j.phi, j.mass, j.pdgId) for j in event.lep_top: autolog("gen l(t)", j.pt, j.eta, j.phi, j.mass, j.pdgId) for j in event.nu_top: autolog("gen n(t)", j.pt, j.eta, j.phi, j.mass, j.pdgId) for j in event.b_quarks_h: autolog("gen b(h)", j.pt, j.eta, j.phi, j.mass, j.pdgId) autolog("gen cat", event.cat_gen, event.cat_gen_n) # In semi-leptonic events we need to figure out which top b is from if event.cat_gen == "sl": # If b pdgId has same sign as hadronic top pdgId, it's the one if event.b_quarks_t[0].pdgId * event.genTopHad[0].pdgId > 0: event.b_quarks_t[0].from_had_t = 1 event.b_quarks_t[1].from_had_t = 0 else: event.b_quarks_t[0].from_had_t = 0 event.b_quarks_t[1].from_had_t = 1 # In Di leptonic events no b quarks come from hadronic top elif event.cat_gen == "dl": for b in event.b_quarks_t: b.from_had_t = 0 # In All hadronic events both b quarks come from hadronic top elif event.cat_gen == "fh": for b in event.b_quarks_t: b.from_had_t = 1 else: for b in event.b_quarks_t: b.from_had_t = -1 #Store for each jet, specified by it's index in the jet #vector, if it is matched to any gen-level quarks matched_pairs = {} def match_jets_to_quarks(jetcoll, quarkcoll, label, label_numeric): for ij, j in enumerate(jetcoll): for iq, q in enumerate(quarkcoll): # Set to 1 for bs from hadronic top # Set to 0 for bs from hadronic top # Set to -1 for other stuff if label == "tb": if q.from_had_t == 1: numeric_b_from_had_t = 1 elif q.from_had_t == 0: numeric_b_from_had_t = 0 else: numeric_b_from_had_t = -1 else: numeric_b_from_had_t = -1 #find DeltaR between jet and quark l1 = lvec(q) l2 = lvec(j) dr = l1.DeltaR(l2) if dr < 0.3: #Jet already had a match: take the one with smaller dR if matched_pairs.has_key(ij): if matched_pairs[ij][1] > dr: matched_pairs[ij] = (label, iq, dr, label_numeric, numeric_b_from_had_t) else: matched_pairs[ij] = (label, iq, dr, label_numeric, numeric_b_from_had_t) #Find the best possible match for each individual jet match_jets_to_quarks(event.good_jets, event.l_quarks_gen, "wq", 0) match_jets_to_quarks(event.good_jets, event.b_quarks_gen_t, "tb", 1) match_jets_to_quarks(event.good_jets, event.b_quarks_gen_h, "hb", 2) #Number of reco jets matched to quarks from W, top, higgs event.nMatch_wq = 0 event.nMatch_tb = 0 event.nMatch_hb = 0 #As above, but also required to be tagged/untagged for b/light respectively. event.nMatch_wq_btag = 0 event.nMatch_tb_btag = 0 event.nMatch_hb_btag = 0 #Now check what each jet was matched to for ij, jet in enumerate(event.good_jets): jet.tth_match_label = None jet.tth_match_index = -1 jet.tth_match_dr = -1 jet.tth_match_label_numeric = -1 #Jet did not have a match (no jet index in matched_pairs) if not matched_pairs.has_key(ij): continue #continue jet loop #mlabel - string label of quark collection, e.g. "wq" #midx - index of quark in vector that the jet was matched to #mdr - delta R between jet and matched quark #mlabel_num - numeric label of quark collection, e.g. 0 #mlabel_num_bfromhadt - numeric label if the b is from hadronic top # -1 if not b or not from top # 0 if from leptonic top # 1 if from hadronic top mlabel, midx, mdr, mlabel_num, mlabel_num_bfromhadt = matched_pairs[ij] jet.tth_match_label = mlabel jet.tth_match_index = midx jet.tth_match_dr = mdr jet.tth_match_label_numeric = mlabel_num jet.tth_match_label_bfromhadt = mlabel_num_bfromhadt if mlabel == "wq": event.nMatch_wq += 1 #If this jet is considered to be un-tagged if jet.btagFlag == 0.0: event.nMatch_wq_btag += 1 elif mlabel == "tb": event.nMatch_tb += 1 #If this jet is considered to be b-tagged if jet.btagFlag == 1.0: event.nMatch_tb_btag += 1 elif mlabel == "hb": event.nMatch_hb += 1 if jet.btagFlag == 1.0: event.nMatch_hb_btag += 1 if "debug" in self.conf.general["verbosity"]: autolog("nSel {0}_{1}_{2} nMatch {3}_{4}_{5} nMatch_btag {6}_{7}_{8}".format( event.nSelected_wq, event.nSelected_tb, event.nSelected_hb, event.nMatch_wq, event.nMatch_tb, event.nMatch_hb, event.nMatch_wq_btag, event.nMatch_tb_btag, event.nMatch_hb_btag, )) if "matching" in self.conf.general["verbosity"]: matches = {"wq":event.l_quarks_w, "tb": event.b_quarks_t, "hb":event.b_quarks_h} for ij, jet in enumerate(event.good_jets): if not matched_pairs.has_key(ij): continue mlabel, midx, mdr, mlabel_num = matched_pairs[ij] autolog("jet match", ij, mlabel, midx, mdr, jet.pt, matches[mlabel][midx].pt) #reco-level tth-matched system spx = 0.0 spy = 0.0 for jet in event.good_jets: if not (jet.tth_match_label is None): p4 = lvec(jet) spx += p4.Px() spy += p4.Py() for lep in event.good_leptons: p4 = lvec(lep) match = False for glep in event.lep_top: p4g = lvec(glep) if p4g.DeltaR(p4) < 0.3: match = True break if match: spx += p4.Px() spy += p4.Py() event.tth_px_reco = spx event.tth_py_reco = spy #Calculate tth recoil #rho = -met - tth_matched event.tth_rho_px_reco = -event.MET.px - event.tth_px_reco event.tth_rho_py_reco = -event.MET.py - event.tth_py_reco #print out gen-level quarks if "input" in self.conf.general["verbosity"]: print "gen Q" for q in event.l_quarks_gen: print q.pt, q.eta, q.phi, q.mass, q.pdgId print "gen B" for q in event.b_quarks_gen: print q.pt, q.eta, q.phi, q.mass, q.pdgId return event
def _process(self, event): event.passes_subjet = True if "debug" in self.conf.general["verbosity"]: autolog("SubjetAnalyzer started") if "subjet" in self.conf.general["verbosity"]: print 'Printing from SubjetAnalyzer! iEv = {0}'.format(event.iEv) # Is set to True only after the event passed all criteria setattr( event, 'PassedSubjetAnalyzer', False ) # Create two new lists for selected_btagged_jets and wquark_candidate_jets # Needs to be done here because the lists are needed in the mem config setattr( event, 'boosted_bjets', [] ) setattr( event, 'boosted_ljets', [] ) setattr( event, 'topCandidate', [] ) setattr( event, 'topCandidatesSync', [] ) setattr( event, 'othertopCandidate', [] ) setattr( event, 'higgsCandidate', [] ) setattr( event, 'higgsCandidateForSync', [] ) event.n_bjets = len( event.selected_btagged_jets_high ) event.n_ljets = len( list( event.wquark_candidate_jets ) ) ######################################## # Minimal event suitability: # - Needs to be single leptonic # - At least 1 httCandidate ######################################## # Check if the event is single leptonic if not (event.is_sl or event.is_fh): #LC return event # Get the top candidates # ====================================== # Keep track of number of httCandidates that passed the cut setattr( event, 'nhttCandidate', len( event.httCandidates ) ) setattr( event, 'nhttCandidate_aftercuts', 0 ) # Just run normal mem if there is no httCandidate present # Check if there is an httCandidate # if len( event.httCandidates ) == 0: # return event # All HTT candidates for sync all_tops = [] for candidate in event.httCandidates: all_tops.append( copy.deepcopy(candidate) ) # Match the top to a fat jet # - Copies bbtag and tau_N, calculates n_subjettiness # - DOES NOT apply the n_subjettiness cut all_tops = self.Match_top_to_fatjet( event, all_tops, False ) for top in all_tops: top.fj_index = event.FatjetCA15ungroomed.index(top.matched_fatjet) # Sort by which ungroomed fj they are matched to all_tops = sorted(all_tops, key=lambda x: x.fj_index ) # Apply the cuts on the httCandidate tops = [] for candidate in event.httCandidates: if self.Apply_Cut_criteria( candidate ): tops.append( copy.deepcopy(candidate) ) # Match the top to a fat jet # - Copies bbtag and tau_N, calculates n_subjettiness # - Applies the n_subjettiness cut tops = self.Match_top_to_fatjet( event, tops, True ) other_tops = [] # Calculate delR with the lepton for all tops that survived the cut if event.is_sl: #LC for top in tops + all_tops: setattr( top, 'delR_lepton' , self.Get_DeltaR_two_objects( top, event.good_leptons[0] ) ) else: for top in tops + all_tops: setattr( top, 'delR_lepton' , -1 ) # Keep track of how many httCandidates passed event.nhttCandidate_aftercuts = len( tops ) #Find the best hadronic gen top match for each top candidate if self.cfg_comp.isMC: gentops = getattr(event, "genTopHad", []) if len(gentops)>0: for topcandidate in tops: lv1 = lvec(topcandidate) drs = [] for igentop, gentop in enumerate(gentops): lv2 = lvec(gentop) drs += [(lv1.DeltaR(lv2), gentop, igentop)] drs = sorted(drs, key=lambda x: x[0]) best = drs[0] topcandidate.genTopHad_dr = best[0] topcandidate.genTop = best[1] topcandidate.genTopHad_index = best[2] # Just run normal mem if there is no httCandidate surviving the cuts # Check if any candidates survived the cutoff criteria # if len(tops) == 0: # return event # If exactly 1 survived, simply continue with that candidate other_top_present = False top = None if len(tops) == 0: other_top_present = False elif len(tops) == 1: top = tops[0] other_top_present = False # If more than 1 candidate survived the cutoff criteria, choose the # one whose delR with the lepton was biggest else: if event.is_sl: #LC tops = sorted( tops, key=lambda x: -x.delR_lepton ) else: tops = sorted( tops, key=lambda x: x.pt) other_top_present = True top = tops[0] other_tops = tops[1:] if "subjet" in self.conf.general["verbosity"]: print "Number of top candidates ", len(tops) # Get a Higgs candidate # ====================================== #Types of fatjets to match to Higgs candidate fatjets_to_match = ["softdropz2b1", "softdrop", "pruned", "subjetfiltered"] extra_higgs_vars = ["mass", "nallsubjets", "sj1pt", "sj1eta", "sj1phi", "sj1mass", "sj1btag", "sj2pt", "sj2eta", "sj2phi", "sj2mass", "sj2btag", "sj3pt", "sj3eta", "sj3phi", "sj3mass", "sj3btag", "sj12mass"] # TODO: # -add groomed n-subjettiness for fatjet_name in fatjets_to_match: self.Add_Higgs_Subjets_To_Fatjet(event, fatjet_name) higgs_present = False higgsCandidates = [] for fatjet in event.FatjetCA15ungroomed: # Turned off for now. TODO: Revisit Higgs/Top overlap removal # # Choose only fatjets that were not HTTv2 candidates for the higgs reco # # Check if the fatjet is not already matched to the chosen top candidate # if top and hasattr(fatjet, 'matched_top') and fatjet == top.matched_fatjet: # continue fatjet.n_subjettiness = -1 if fatjet.tau1 > 0: fatjet.n_subjettiness = fatjet.tau2 / fatjet.tau1 if top: fatjet.dr_top = self.Get_DeltaR_two_objects(fatjet, top) #set default extra variables for all fatjet types for fatjetkind in fatjets_to_match: for var in extra_higgs_vars: setattr(fatjet, var + "_" + fatjetkind, -9999) genhiggs = getattr(event, "GenHiggsBoson", []) #match higgs candidate to generated higgs if self.cfg_comp.isMC and len(genhiggs) >= 1: lv1 = lvec(fatjet) lv2 = lvec(genhiggs[0]) fatjet.dr_genHiggs = lv1.DeltaR(lv2) higgsCandidates.append( fatjet ) higgs_present = True # Sort by pT # TODO: for now. Revisit and change to subjet b-tag/bbtag we decide on higgsCandidates = sorted( higgsCandidates, key=lambda x: -x.pt ) # Match higgs candidates to various fat jets for fatjetkind in fatjets_to_match: nmatch = self.Match_two_lists( higgsCandidates, 'higgs', getattr(event, "FatjetCA15" + fatjetkind), 'fatjet_' + fatjetkind, R_cut = self.R_cut_fatjets ) # Add properties of the matched fatjet to the higgs candidate for higgsCandidate in higgsCandidates: for fatjetkind in fatjets_to_match: matchjet = getattr(higgsCandidate, "matched_fatjet_" + fatjetkind, None) if matchjet != None: for var in extra_higgs_vars: if hasattr(matchjet,var): setattr(higgsCandidate, var + "_" + fatjetkind, getattr(matchjet,var)) ######################################## # Get the lists of particles: quarks, jets and subjets ######################################## # Get the subjets from the httCandidate # - Also sets transfer functions as attributes # - Returns subjets ordered by decreasing btag # - First subjet has btagFlag==1.0, the other two btagFlag==0.0 top_subjets = self.Get_Subjets( top ) if "subjet" in self.conf.general["verbosity"]: print "subjets" for subjet in top_subjets: print subjet if other_top_present: for top in other_tops: self.Get_Subjets( top ) # Set 'PDGID' to 1 for light, and to 5 for b for subjet in top_subjets: if subjet.btagFlag == 1.0: setattr( subjet, 'PDGID', 5 ) if subjet.btagFlag == 0.0: setattr( subjet, 'PDGID', 1 ) # Create two new lists for btagged_jets and wquark_candidate_jets in the # original events if event.is_sl: #LC reco_btagged_jets = copy.deepcopy( event.selected_btagged_jets_high ) reco_ltagged_jets = copy.deepcopy( list( event.wquark_candidate_jets ) ) else: #LC reco_ltagged_jets = event.buntagged_jets_bdisc reco_btagged_jets = event.btagged_jets_bdisc if len(tops) > 0: top_subjets = self.Get_Subjets( top ) if "subjet" in self.conf.general["verbosity"]: print "subjets" for subjet in top_subjets: print subjet if other_top_present: for top in other_tops: self.Get_Subjets( top ) # Set 'PDGID' to 1 for light, and to 5 for b # FIXME: do not use PDGID currently, as it ONLY works with the HEPTopTagger perm pruning strat #for subjet in top_subjets: # if subjet.btagFlag == 1.0: setattr( subjet, 'PDGID', 5 ) # if subjet.btagFlag == 0.0: setattr( subjet, 'PDGID', 1 ) # Create two new lists for btagged_jets and wquark_candidate_jets in the # original events reco_btagged_jets = copy.deepcopy( event.selected_btagged_jets_high ) reco_ltagged_jets = copy.deepcopy( list( event.wquark_candidate_jets ) ) for jet in reco_btagged_jets: setattr( jet, 'btag', getattr(jet,self.btagAlgo) ) setattr( jet, 'btagFlag', 1.0 ) #setattr( jet, 'PDGID', 0 ) for jet in reco_ltagged_jets: setattr( jet, 'btag', getattr(jet,self.btagAlgo) ) setattr( jet, 'btagFlag', 0.0 ) #setattr( jet, 'PDGID', 0 ) ######################################## # Matching ######################################## # Whenever a subjet has a 'match' (dR < dR_cut), the matched object should # excluded from the event # Match subjet to a bjet n_excluded_bjets = self.Match_two_lists( top_subjets, 'top_subjet', reco_btagged_jets, 'bjet' ) # Match subjet to a ljet n_excluded_ljets = self.Match_two_lists( top_subjets , 'top_subjet', reco_ltagged_jets, 'ljet' ) if "subjet" in self.conf.general["verbosity"]: print "subjet nMatchB={0} nMatchL={1}".format(n_excluded_bjets, n_excluded_ljets) #FIXME: Unify this for SL/DL/FH #from FH branch # # Stop adding after 4 b-jets # if event.is_sl:#LC # if len(boosted_bjets) == 4: break # event.PassedSubjetAnalyzer = True # # if event.is_fh: #LC: also add other light jets # for ljet in reco_ltagged_jets: # # Check if the l-jet is not excluded # if not hasattr( ljet, 'matched_top_subjet' ): # boosted_ljets.append( ljet ) # # # # # # If too many events are excluded, just run the default hypothesis # else: # if "subjet" in self.conf.general["verbosity"]: # print "[SubjetAnalyzer] subjet has too many overlaps, using reco" # boosted_bjets = reco_btagged_jets # boosted_ljets = reco_ltagged_jets # event.PassedSubjetAnalyzer = False #======= end from FH branch # In case of double matching, choose the match with lowest delR # (This is not expected to happen often) for subjet in top_subjets: if hasattr( subjet, 'matched_bjet' ) and \ hasattr( subjet, 'matched_ljet' ) : print '[SubjetAnalyzer] Double match detected' if subjet.matched_bjet_delR < subjet.matched_ljet_delR: del subjet.matched_ljet del subjet.matched_ljet_delR n_excluded_bjets -= 1 else: del subjet.matched_bjet del subjet.matched_bjet_delR n_excluded_ljets -= 1 ######################################## # Modifying the bjets and ljets lists ######################################## boosted_bjets = [] boosted_ljets = [] if n_excluded_bjets <= 1: if "subjet" in self.conf.general["verbosity"]: print "subjet replacing" # Add the subjets to the final output lists first for subjet in top_subjets: if subjet.btagFlag == 1.0: boosted_bjets.append( subjet ) if subjet.btagFlag == 0.0: boosted_ljets.append( subjet ) # Sort tl btagged jets by decreasing btag (to be sure, but should # already be done in previous analyzer) # Only resolved b-jets reco_btagged_jets = sorted( reco_btagged_jets, key=lambda x: -x.btag ) # Add up to 4 reco btagged jets to the output lists for bjet in reco_btagged_jets: # Check if the b-jet is not excluded if not hasattr( bjet, 'matched_top_subjet' ): boosted_bjets.append( bjet ) # Stop adding after 4 b-jets if len(boosted_bjets) == 4: break event.PassedSubjetAnalyzer = True # If too many events are excluded, just run the default hypothesis else: if "subjet" in self.conf.general["verbosity"]: print "[SubjetAnalyzer] subjet has too many overlaps, using reco" boosted_bjets = reco_btagged_jets boosted_ljets = reco_ltagged_jets event.PassedSubjetAnalyzer = False ######################################## # Write to event ######################################## # Store output lists in event event.higgsCandidate = higgsCandidates all_tops_to_add = [] # Add top matched to leading fatjet OR dummy for top in all_tops: if top.fj_index == 0: all_tops_to_add.append(top) break if len(all_tops_to_add) == 0: all_tops_to_add.append(DummyTop()) # Add top matched to sub-leading fatjet OR dummy for top in all_tops: if top.fj_index == 1: all_tops_to_add.append( top) break if len(all_tops_to_add) == 1: all_tops_to_add.append(DummyTop()) event.topCandidatesSync = all_tops_to_add if len(tops)>0: event.topCandidate = [ top ] event.othertopCandidate = other_tops event.boosted_bjets = boosted_bjets event.boosted_ljets = boosted_ljets event.n_boosted_bjets = len( boosted_bjets ) event.n_boosted_ljets = len( boosted_ljets ) event.n_excluded_bjets = n_excluded_bjets event.n_excluded_ljets = n_excluded_ljets #pdb.set_trace() if "subjet" in self.conf.general["verbosity"]: print '[SubjetAnalyzer] Exiting SubjetAnalyzer! event.PassedSubjetAnalyzer = {0}'.format( event.PassedSubjetAnalyzer ) ######################################## # Matching to Gen top ########################################### event.n_matched_TTgentop = -1 event.matched_TTgentop_pt = -1 event.n_matched_TTgenb = -1 event.n_matched_TTgenW = -1 if len(tops)>0: self.Do_GenTop_Matching(event) return event ######################################## # Quark Matching ######################################## # This section is only useful for truth-level comparison, and can be turned # off if this is not needed. # Do_Quark_Matching( event ) sets number of matches with quarks as branches # in the event, but these branches do not have to be filled (they will be # automatically set to -1 in the final output root file). self.Do_Quark_Matching( event )
def _process(self, event): #FIXME: NEED COMMENTS HERE sumP2 = 0.0 sumPxx = 0.0 sumPxy = 0.0 sumPxz = 0.0 sumPyy = 0.0 sumPyz = 0.0 sumPzz = 0.0 vecs = CvectorTLorentzVector() for jet in event.good_jets: obj = lvec(jet) vecs.push_back(lvec(jet)) sumP2 += obj.P() * obj.P() sumPxx += obj.Px() * obj.Px() sumPxy += obj.Px() * obj.Py() sumPxz += obj.Px() * obj.Pz() sumPyy += obj.Py() * obj.Py() sumPyz += obj.Py() * obj.Pz() sumPzz += obj.Pz() * obj.Pz() evshape = EventShapeVariables(vecs) eigs = evshape.compEigenValues(2.0) #difference: this takes T^2-x^2-y^2-z^2 for P2 event.momentum_eig0 = eigs[0] event.momentum_eig1 = eigs[1] event.momentum_eig2 = eigs[2] ##---- compute sphericity --------------------#DS Txx = sumPxx/sumP2 Tyy = sumPyy/sumP2 Tzz = sumPzz/sumP2 Txy = sumPxy/sumP2 Txz = sumPxz/sumP2 Tyz = sumPyz/sumP2 T = TMatrixDSym(3) T[0,0] = Txx T[0,1] = Txy T[0,2] = Txz T[1,0] = Txy T[1,1] = Tyy T[1,2] = Tyz T[2,0] = Txz T[2,1] = Tyz T[2,2] = Tzz TEigen = TMatrixDSymEigen(T) eigenValues = TEigen.GetEigenValues() event.sphericity = 1.5*(eigenValues(1)+eigenValues(2)) event.aplanarity = 1.5*eigenValues(2) event.C = 3.0*(eigenValues(0)*eigenValues(1) + eigenValues(0)*eigenValues(2) + eigenValues(1)*eigenValues(2)) event.D = 27.*eigenValues(0)*eigenValues(1)*eigenValues(2) #---------DS event.isotropy = evshape.isotropy() event.sphericity = 1.5*(eigs[1]+eigs[2]) #evshape.sphericity(eigs) #DS event.aplanarity = 1.5*eigs[2] #evshape.aplanarity(eigs) #DS event.C = 3.0*(eigs[0]*eigs[1] + eigs[0]*eigs[2] + eigs[1]*eigs[2]) #evshape.C(eigs) #DS event.D = 27.*eigs[0]*eigs[1]*eigs[2] #evshape.D(eigs) #DS event.mean_bdisc = np.mean([j.btagCSV for j in event.good_jets]) event.mean_bdisc_btag = np.mean([j.btagCSV for j in event.selected_btagged_jets]) event.std_bdisc = np.std([j.btagCSV for j in event.good_jets]) event.std_bdisc_btag = np.std([j.btagCSV for j in event.selected_btagged_jets]) drs = [] for j1 in event.selected_btagged_jets: for j2 in event.selected_btagged_jets: if j1==j2: continue l1 = lvec(j1) l2 = lvec(j2) drs += [(l1.DeltaR(l2), l1, l2)] drs = sorted(drs, key=lambda x: x[0]) if len(drs)>0: lv = drs[0][1] + drs[0][2] event.mass_drpair_btag = lv.M() event.eta_drpair_btag = abs(lv.Eta()) event.pt_drpair_btag = lv.Pt() event.min_dr_btag = drs[0][0] event.mean_dr_btag = np.mean([dr[0] for dr in drs], -1) event.std_dr_btag = np.std([dr[0] for dr in drs], -1) else: event.min_dr_btag = -1.0 event.mean_dr_btag = -1.0 event.std_dr_btag = -1.0 event.mass_drpair_btag = -1.0 event.eta_drpair_btag = -99 event.pt_drpair_btag = -1.0 for i in range(min(4, len(event.selected_btagged_jets_high))): setattr(event, "jet_btag_{0}".format(i), event.selected_btagged_jets_high[i]) event.ht = np.sum([j.pt for j in event.good_jets]) lvecs = [lvec(x) for x in event.good_jets + event.good_leptons] event.centrality = np.sum([l.Pt() / l.E() for l in lvecs]) #orders of momenta to calculate orders = np.array([0, 1, 2, 3, 4, 5, 6, 7]) event.fw_h_alljets = FoxWolfram.calcFoxWolfram(event.good_jets, orders, FoxWolfram.w_s) event.fw_h_btagjets = FoxWolfram.calcFoxWolfram(event.selected_btagged_jets_high, orders, FoxWolfram.w_s) event.fw_h_untagjets = FoxWolfram.calcFoxWolfram(event.buntagged_jets, orders, FoxWolfram.w_s) for ij in range(6): setattr(event, "jet{0}_pt".format(ij), 0) setattr(event, "jet{0}_aeta".format(ij), 0) setattr(event, "jet{0}_btag".format(ij), 0) for ij, jet in enumerate(event.good_jets): setattr(event, "jet{0}_pt".format(ij), jet.pt) setattr(event, "jet{0}_aeta".format(ij), abs(jet.eta)) setattr(event, "jet{0}_btag".format(ij), jet.btagCSV) for i in range(2): setattr(event, "lep{0}_pt".format(i), 0.0) setattr(event, "lep{0}_aeta".format(i), 0.0) for ij, lep in enumerate(event.good_leptons): setattr(event, "lep{0}_pt".format(ij), lep.pt) setattr(event, "lep{0}_aeta".format(ij), abs(lep.eta)) for io in orders: setattr(event, "fw_h{0}".format(io), event.fw_h_alljets[io]) vararray = np.array([getattr(event, vname) for vname in self.conf.tth_mva["varlist"]]) vararray[np.isnan(vararray)] = 0 event.tth_mva = 0 if mva_enabled: event.tth_mva = self.cls.predict_proba(vararray)[0,1] event.passes_mva = True return event
def process(self, event): event.mu = filter( lambda x: abs(x.pdgId) == 13, event.selLeptons, ) if "debug" in self.conf.general["verbosity"]: autolog("input muons: ", len(event.mu)) for it in event.mu: (self.conf.leptons["mu"]["debug"])(it) event.el = filter( lambda x: abs(x.pdgId) == 11, event.selLeptons, ) if "debug" in self.conf.general["verbosity"]: autolog("input electrons: ", len(event.el)) for it in event.el: (self.conf.leptons["el"]["debug"])(it) for id_type in ["SL", "DL", "veto"]: sumleps = [] for lep_flavour in ["mu", "el"]: lepcuts = self.conf.leptons[lep_flavour][id_type] incoll = getattr(event, lep_flavour) isotype = self.conf.leptons[lep_flavour]["isotype"] isocut = lepcuts.get("iso", 99) if "debug" in self.conf.general["verbosity"]: autolog("input collection", id_type, lep_flavour) for lep in incoll: autolog(lep.pt, lep.eta, lep.pdgId) leps = filter( lambda x, lepcuts=lepcuts: ( x.pt > lepcuts.get( "pt", 0) #pt cut may be optional in case of DL and abs(x.eta) < lepcuts["eta"]), incoll) if "debug" in self.conf.general["verbosity"]: autolog("after eta") for lep in leps: autolog(lep.pt, lep.eta, lep.pdgId) #Apply isolation cut if isotype != "none": leps = filter(lambda x, isotype=isotype, isocut=isocut: abs(getattr(x, isotype)) < isocut, leps) if "debug" in self.conf.general["verbosity"]: autolog("after iso", isotype) for lep in leps: autolog(lep.pt, lep.eta, lep.pdgId) #Apply ID cut leps = filter(lepcuts["idcut"], leps) if "debug" in self.conf.general["verbosity"]: autolog("after id") for lep in leps: autolog(lep.pt, lep.eta, lep.pdgId) sumleps += leps lepname = lep_flavour + "_" + id_type setattr(event, lepname, leps) setattr(event, "n_" + lepname, len(leps)) #end of lep_flavour loop setattr(event, "lep_{0}".format(id_type), sumleps) setattr(event, "n_lep_{0}".format(id_type), len(sumleps)) #end of id_type loop event.lep_SL = sorted(event.lep_SL, key=lambda x: x.pt, reverse=True) event.lep_DL = sorted(event.lep_DL, key=lambda x: x.pt, reverse=True) event.lep_veto = sorted(event.lep_veto, key=lambda x: x.pt, reverse=True) #Apply two-stage pt cut on DL leptons lep_DL_afterpt = [] for lep in event.lep_DL: if len(lep_DL_afterpt) == 0: ptcut = self.conf.leptons["DL"]["pt_leading"] else: ptcut = self.conf.leptons["DL"]["pt_subleading"] if lep.pt > ptcut: lep_DL_afterpt += [lep] event.lep_DL = lep_DL_afterpt event.n_lep_DL = len(event.lep_DL) if "debug" in self.conf.general["verbosity"]: for lep in event.lep_SL + event.lep_DL + event.lep_veto: if lep in event.mu: f = self.conf.leptons["mu"]["debug"] elif lep in event.el: f = self.conf.leptons["el"]["debug"] else: f = lambda x: x prefix = "" if lep in event.lep_SL: prefix += "SL " if lep in event.lep_DL: prefix += "DL " if lep in event.lep_DL: prefix += "veto " autolog(prefix) f(lep) autolog("n_lep_tight={0}, n_lep_loose={1}, n_lep_tight_veto={2}". format(event.n_lep_SL, event.n_lep_DL, event.n_lep_veto)) event.is_sl = (event.n_lep_SL == 1 and event.n_lep_veto == 1) event.is_dl = (event.n_lep_DL == 2 and event.n_lep_veto == 2) event.is_fh = (not event.is_sl and not event.is_dl) if "debug" in self.conf.general["verbosity"]: autolog("is_sl, is_dl, is_fh", event.is_sl, event.is_dl, event.is_fh) #Calculate di-lepton system momentum event.dilepton_p4 = ROOT.TLorentzVector() if event.is_sl: event.good_leptons = event.lep_SL event.veto_leptons = event.lep_veto elif event.is_dl: event.good_leptons = event.lep_DL event.veto_leptons = event.lep_veto for lv in [lvec(l) for l in event.good_leptons]: event.dilepton_p4 += lv elif event.is_fh: event.good_leptons = [] event.veto_leptons = [] event.good_leptons = sorted(event.good_leptons, key=lambda x: x.pt, reverse=True) event.veto_leptons = sorted(event.veto_leptons, key=lambda x: x.pt, reverse=True) #Match good signal leptons to gen-leptons if self.cfg_comp.isMC: from PhysicsTools.HeppyCore.utils.deltar import matchObjectCollection #matchObjectCollection(event.good_leptons, event.GenLepFromTop, 0.3) #apply configuration-dependent selection passes = self.conf.leptons["selection"](event) if "debug" in self.conf.general["verbosity"]: autolog("LeptonAnalyzer selection", passes) if event.is_sl and event.is_dl: autolog("The event (%s,%s,%s) is both sl and dl" % (event.input.run, event.input.lumi, event.input.evt)) autolog("SL mu") for lep in event.mu_SL: (self.conf.leptons["mu"]["debug"])(lep) autolog("DL mu") for lep in event.mu_DL: (self.conf.leptons["mu"]["debug"])(lep) autolog("SL el") for lep in event.el_SL: (self.conf.leptons["el"]["debug"])(lep) autolog("DL el") for lep in event.el_DL: (self.conf.leptons["el"]["debug"])(lep) autolog("veto mu") for lep in event.mu_veto: (self.conf.leptons["mu"]["debug"])(lep) autolog("veto el") for lep in event.mu_veto: (self.conf.leptons["el"]["debug"])(lep) passes = False autolog("WARNING: Overlapping event") return self.conf.general["passall"] or passes
def process(self, event): event.mu = filter( lambda x: abs(x.pdgId) == 13, event.selLeptons, ) if "debug" in self.conf.general["verbosity"]: autolog("input muons: ", len(event.mu)) for it in event.mu: (self.conf.leptons["mu"]["debug"])(it) event.el = filter( lambda x: abs(x.pdgId) == 11, event.selLeptons, ) if "debug" in self.conf.general["verbosity"]: autolog("input electrons: ", len(event.el)) for it in event.el: (self.conf.leptons["el"]["debug"])(it) for id_type in ["SL", "DL", "veto"]: sumleps = [] for lep_flavour in ["mu", "el"]: lepcuts = self.conf.leptons[lep_flavour][id_type] incoll = getattr(event, lep_flavour) isotype = self.conf.leptons[lep_flavour]["isotype"] isocut = lepcuts.get("iso", 99) if "debug" in self.conf.general["verbosity"]: autolog("input collection", id_type, lep_flavour) for lep in incoll: autolog(lep.pt, lep.eta, lep.pdgId) leps = filter( lambda x, lepcuts=lepcuts: ( x.pt > lepcuts.get("pt", 0) #pt cut may be optional in case of DL and abs(x.eta) < lepcuts["eta"] ), incoll ) if "debug" in self.conf.general["verbosity"]: autolog("after eta") for lep in leps: autolog(lep.pt, lep.eta, lep.pdgId) #Apply isolation cut if isotype != "none": leps = filter( lambda x, isotype=isotype, isocut=isocut: abs(getattr(x, isotype)) < isocut, leps ) if "debug" in self.conf.general["verbosity"]: autolog("after iso", isotype) for lep in leps: autolog(lep.pt, lep.eta, lep.pdgId) #Apply ID cut leps = filter(lepcuts["idcut"], leps) if "debug" in self.conf.general["verbosity"]: autolog("after id") for lep in leps: autolog(lep.pt, lep.eta, lep.pdgId) sumleps += leps lepname = lep_flavour + "_" + id_type setattr(event, lepname, leps) setattr(event, "n_"+ lepname, len(leps)) #end of lep_flavour loop setattr(event, "lep_{0}".format(id_type), sumleps) setattr(event, "n_lep_{0}".format(id_type), len(sumleps)) #end of id_type loop event.lep_SL = sorted(event.lep_SL, key=lambda x: x.pt, reverse=True) event.lep_DL = sorted(event.lep_DL, key=lambda x: x.pt, reverse=True) event.lep_veto = sorted(event.lep_veto, key=lambda x: x.pt, reverse=True) #Apply two-stage pt cut on DL leptons lep_DL_afterpt = [] for lep in event.lep_DL: if len(lep_DL_afterpt) == 0: ptcut = self.conf.leptons["DL"]["pt_leading"] else: ptcut = self.conf.leptons["DL"]["pt_subleading"] if lep.pt > ptcut: lep_DL_afterpt += [lep] event.lep_DL = lep_DL_afterpt event.n_lep_DL = len(event.lep_DL) if "debug" in self.conf.general["verbosity"]: for lep in event.lep_SL + event.lep_DL + event.lep_veto: if lep in event.mu: f = self.conf.leptons["mu"]["debug"] elif lep in event.el: f = self.conf.leptons["el"]["debug"] else: f = lambda x: x prefix = "" if lep in event.lep_SL: prefix += "SL " if lep in event.lep_DL: prefix += "DL " if lep in event.lep_DL: prefix += "veto " autolog(prefix) f(lep) autolog("n_lep_tight={0}, n_lep_loose={1}, n_lep_tight_veto={2}".format( event.n_lep_SL, event.n_lep_DL, event.n_lep_veto) ) event.is_sl = (event.n_lep_SL == 1 and event.n_lep_veto == 1) event.is_dl = (event.n_lep_DL == 2 and event.n_lep_veto == 2) event.is_fh = (not event.is_sl and not event.is_dl) if "debug" in self.conf.general["verbosity"]: autolog("is_sl, is_dl, is_fh", event.is_sl, event.is_dl, event.is_fh) #Calculate di-lepton system momentum event.dilepton_p4 = ROOT.TLorentzVector() if event.is_sl: event.good_leptons = event.lep_SL event.veto_leptons = event.lep_veto elif event.is_dl: event.good_leptons =event.lep_DL event.veto_leptons = event.lep_veto for lv in [lvec(l) for l in event.good_leptons]: event.dilepton_p4 += lv elif event.is_fh: event.good_leptons = [] event.veto_leptons = [] event.good_leptons = sorted(event.good_leptons, key=lambda x: x.pt, reverse=True) event.veto_leptons = sorted(event.veto_leptons, key=lambda x: x.pt, reverse=True) #Match good signal leptons to gen-leptons if self.cfg_comp.isMC: from PhysicsTools.HeppyCore.utils.deltar import matchObjectCollection #matchObjectCollection(event.good_leptons, event.GenLepFromTop, 0.3) #apply configuration-dependent selection passes = self.conf.leptons["selection"](event) if "debug" in self.conf.general["verbosity"]: autolog("LeptonAnalyzer selection", passes) if event.is_sl and event.is_dl: autolog("The event (%s,%s,%s) is both sl and dl" % ( event.input.run,event.input.lumi,event.input.evt) ) autolog("SL mu") for lep in event.mu_SL: (self.conf.leptons["mu"]["debug"])(lep) autolog("DL mu") for lep in event.mu_DL: (self.conf.leptons["mu"]["debug"])(lep) autolog("SL el") for lep in event.el_SL: (self.conf.leptons["el"]["debug"])(lep) autolog("DL el") for lep in event.el_DL: (self.conf.leptons["el"]["debug"])(lep) autolog("veto mu") for lep in event.mu_veto: (self.conf.leptons["mu"]["debug"])(lep) autolog("veto el") for lep in event.mu_veto: (self.conf.leptons["el"]["debug"])(lep) passes = False autolog("WARNING: Overlapping event") return self.conf.general["passall"] or passes
def _process(self, event): if not self.cfg_comp.isMC: return event if "debug" in self.conf.general["verbosity"]: autolog("GenTTHAnalyzer started") #Get light quarks from W/Z event.l_quarks_w = event.GenWZQuark #Get b quarks from top event.b_quarks_t = event.GenBQuarkFromTop #Get b-quarks from H event.b_quarks_h = event.GenBQuarkFromH #Get leptonic top children #note that the tau lepton might be missing event.lep_top = event.GenLepFromTop event.nu_top = event.GenNuFromTop #cat_gen - a string specifying the ttbar decay mode event.cat_gen = None #cat_gen_n - a numerical value corresponding to the string event.cat_gen_n = -1 #all leptonic and hadronic gen tops event.genTopLep = [] event.genTopHad = [] #Only run top algos if len(event.GenTop) == 2: #Gen tops might be in random order gt1 = event.GenTop[0] gt2 = event.GenTop[1] dm1 = getattr(gt1, "decayMode", -1) dm2 = getattr(gt2, "decayMode", -1) #single-leptonic if ((dm1 == 0 and dm2 == 1) or (dm2 == 0 and dm1 == 1)): #First top is leptonic if dm1 == 0: event.genTopLep = [gt1] event.genTopHad = [gt2] #Second top is leptonic else: event.genTopLep = [gt2] event.genTopHad = [gt1] event.cat_gen = "sl" event.cat_gen_n = 0 elif (dm1 == 0 and dm2 == 0): event.cat_gen = "dl" event.cat_gen_n = 1 event.genTopLep = [gt1, gt2] event.genTopHad = [] elif (dm1 == 1 and dm2 == 1): event.cat_gen = "fh" event.cat_gen_n = 2 event.genTopHad = [gt1, gt2] event.genTopLep = [] else: event.genTopLep = [] event.genTopHad = [] #these are the quarks that would pass selection event.l_quarks_gen = [] event.b_quarks_gen_t = [] event.b_quarks_gen_h = [] nq = 0 #Find the light quarks from W that would pass jet selection #associate them with a transfer function for q in event.l_quarks_w: nq += 1 if self.pass_jet_selection(q): q.btagFlag = 0.0 q.tth_match_label = "wq" q.tth_match_index = nq attach_jet_transfer_function(q, self.conf) event.l_quarks_gen += [q] #Find the b quarks from top that would pass jet selection #associate them with a transfer function for q in event.b_quarks_t: nq += 1 if self.pass_jet_selection(q): q.btagFlag = 1.0 q.tth_match_label = "tb" q.tth_match_index = nq attach_jet_transfer_function(q, self.conf) event.b_quarks_gen_t += [q] #Find the b quarks from Higgs that would pass jet selection #associate them with a transfer function for q in event.b_quarks_h: nq += 1 if self.pass_jet_selection(q): q.btagFlag = 1.0 q.tth_match_label = "hb" q.tth_match_index = nq attach_jet_transfer_function(q, self.conf) event.b_quarks_gen_h += [q] #Number of reco jets matched to quarks from W, top, higgs event.nSelected_wq = len(event.l_quarks_gen) event.nSelected_tb = len(event.b_quarks_gen_t) event.nSelected_hb = len(event.b_quarks_gen_h) #Get the total MET from the neutrinos spx = 0 spy = 0 for nu in event.nu_top: p4 = lvec(nu) spx += p4.Px() spy += p4.Py() event.MET_tt = MET(px=spx, py=spy) #Get the total ttH visible pt at gen level spx = 0 spy = 0 for p in (event.l_quarks_w + event.b_quarks_t + event.b_quarks_h + event.lep_top): p4 = lvec(p) spx += p4.Px() spy += p4.Py() event.tth_px_gen = spx event.tth_py_gen = spy #Calculate tth recoil #rho = -met - tth_matched event.tth_rho_px_gen = -event.MET_gen.px - event.tth_px_gen event.tth_rho_py_gen = -event.MET_gen.py - event.tth_py_gen if "gen" in self.conf.general["verbosity"]: for j in event.l_quarks_w: autolog("gen q(W)", j.pt, j.eta, j.phi, j.mass, j.pdgId) for j in event.b_quarks_t: autolog("gen b(t)", j.pt, j.eta, j.phi, j.mass, j.pdgId) for j in event.lep_top: autolog("gen l(t)", j.pt, j.eta, j.phi, j.mass, j.pdgId) for j in event.nu_top: autolog("gen n(t)", j.pt, j.eta, j.phi, j.mass, j.pdgId) for j in event.b_quarks_h: autolog("gen b(h)", j.pt, j.eta, j.phi, j.mass, j.pdgId) autolog("gen cat", event.cat_gen, event.cat_gen_n) # In semi-leptonic events we need to figure out which top b is from if event.cat_gen == "sl": # If b pdgId has same sign as hadronic top pdgId, it's the one if event.b_quarks_t[0].pdgId * event.genTopHad[0].pdgId > 0: event.b_quarks_t[0].from_had_t = 1 event.b_quarks_t[1].from_had_t = 0 else: event.b_quarks_t[0].from_had_t = 0 event.b_quarks_t[1].from_had_t = 1 # In Di leptonic events no b quarks come from hadronic top elif event.cat_gen == "dl": for b in event.b_quarks_t: b.from_had_t = 0 # In All hadronic events both b quarks come from hadronic top elif event.cat_gen == "fh": for b in event.b_quarks_t: b.from_had_t = 1 else: for b in event.b_quarks_t: b.from_had_t = -1 #Store for each jet, specified by it's index in the jet #vector, if it is matched to any gen-level quarks matched_pairs = {} def match_jets_to_quarks(jetcoll, quarkcoll, label, label_numeric): for ij, j in enumerate(jetcoll): for iq, q in enumerate(quarkcoll): # Set to 1 for bs from hadronic top # Set to 0 for bs from hadronic top # Set to -1 for other stuff if label == "tb": if q.from_had_t == 1: numeric_b_from_had_t = 1 elif q.from_had_t == 0: numeric_b_from_had_t = 0 else: numeric_b_from_had_t = -1 else: numeric_b_from_had_t = -1 #find DeltaR between jet and quark l1 = lvec(q) l2 = lvec(j) dr = l1.DeltaR(l2) if dr < 0.3: #Jet already had a match: take the one with smaller dR if not matched_pairs.has_key(ij): matched_pairs[ij] = [] matched_pairs[ij] += [(label, iq, dr, label_numeric, numeric_b_from_had_t)] #Find the best possible match for each individual jet #light-quarks from W match_jets_to_quarks(event.good_jets, event.l_quarks_gen, "wq", 0) #b-quarks from top match_jets_to_quarks(event.good_jets, event.b_quarks_gen_t, "tb", 1) #b-quarks from Higgs match_jets_to_quarks(event.good_jets, event.b_quarks_gen_h, "hb", 2) #gluons from top match_jets_to_quarks(event.good_jets, event.GenGluonFromTop, "tg", 3) #gluons from b match_jets_to_quarks(event.good_jets, event.GenGluonFromB, "bg", 4) #Number of reco jets matched to quarks from W, top, higgs event.nMatch_wq = 0 event.nMatch_tb = 0 event.nMatch_hb = 0 #As above, but also required to be tagged/untagged for b/light respectively. event.nMatch_wq_btag = 0 event.nMatch_tb_btag = 0 event.nMatch_hb_btag = 0 #Now check what each jet was matched to for ij, jet in enumerate(event.good_jets): jet.tth_match_label = None jet.tth_match_index = -1 jet.tth_match_dr = -1 jet.tth_match_label_numeric = -1 #Jet did not have a match (no jet index in matched_pairs) if not matched_pairs.has_key(ij): continue #continue jet loop #mlabel - string label of quark collection, e.g. "wq" #midx - index of quark in vector that the jet was matched to #mdr - delta R between jet and matched quark #mlabel_num - numeric label of quark collection, e.g. 0 #mlabel_num_bfromhadt - numeric label if the b is from hadronic top # -1 if not b or not from top # 0 if from leptonic top # 1 if from hadronic top matches = matched_pairs[ij] if len(matches) == 1: mlabel, midx, mdr, mlabel_num, mlabel_num_bfromhadt = matches[ 0] else: #select dR-ordered matches from W, t, b matches_hard = filter(lambda x: x[0] in ["wq", "tb", "hb"], matches) matches_hard = sorted(matches_hard, key=lambda x: x[2]) if len(matches_hard) >= 1: mlabel, midx, mdr, mlabel_num, mlabel_num_bfromhadt = matches_hard[ 0] else: matches_soft = filter(lambda x: x[0] in ["tg", "bg"], matches) matches_soft = sorted(matches_soft, key=lambda x: x[2]) mlabel, midx, mdr, mlabel_num, mlabel_num_bfromhadt = matches_soft[ 0] jet.tth_match_label = mlabel jet.tth_match_index = midx jet.tth_match_dr = mdr jet.tth_match_label_numeric = mlabel_num jet.tth_match_label_bfromhadt = mlabel_num_bfromhadt if mlabel == "wq": event.nMatch_wq += 1 #If this jet is considered to be un-tagged if jet.btagFlag == 0.0: event.nMatch_wq_btag += 1 elif mlabel == "tb": event.nMatch_tb += 1 #If this jet is considered to be b-tagged if jet.btagFlag == 1.0: event.nMatch_tb_btag += 1 elif mlabel == "hb": event.nMatch_hb += 1 if jet.btagFlag == 1.0: event.nMatch_hb_btag += 1 if "debug" in self.conf.general["verbosity"]: autolog( "nSel {0}_{1}_{2} nMatch {3}_{4}_{5} nMatch_btag {6}_{7}_{8}". format( event.nSelected_wq, event.nSelected_tb, event.nSelected_hb, event.nMatch_wq, event.nMatch_tb, event.nMatch_hb, event.nMatch_wq_btag, event.nMatch_tb_btag, event.nMatch_hb_btag, )) if "matching" in self.conf.general["verbosity"]: matches = { "wq": event.l_quarks_w, "tb": event.b_quarks_t, "hb": event.b_quarks_h } for ij, jet in enumerate(event.good_jets): if not matched_pairs.has_key(ij): continue mlabel, midx, mdr, mlabel_num = matched_pairs[ij] autolog("jet match", ij, mlabel, midx, mdr, jet.pt, matches[mlabel][midx].pt) #reco-level tth-matched system spx = 0.0 spy = 0.0 for jet in event.good_jets: if not (jet.tth_match_label is None): p4 = lvec(jet) spx += p4.Px() spy += p4.Py() for lep in event.good_leptons: p4 = lvec(lep) match = False for glep in event.lep_top: p4g = lvec(glep) if p4g.DeltaR(p4) < 0.3: match = True break if match: spx += p4.Px() spy += p4.Py() event.tth_px_reco = spx event.tth_py_reco = spy #Calculate tth recoil #rho = -met - tth_matched event.tth_rho_px_reco = -event.MET.px - event.tth_px_reco event.tth_rho_py_reco = -event.MET.py - event.tth_py_reco #print out gen-level quarks if "input" in self.conf.general["verbosity"]: print "gen Q" for q in event.l_quarks_gen: print q.pt, q.eta, q.phi, q.mass, q.pdgId print "gen B" for q in event.b_quarks_gen: print q.pt, q.eta, q.phi, q.mass, q.pdgId return event
def _process(self, event): event.passes_subjet = True if "debug" in self.conf.general["verbosity"]: autolog("SubjetAnalyzer started") if "subjet" in self.conf.general["verbosity"]: print 'Printing from SubjetAnalyzer! iEv = {0}'.format(event.iEv) # Is set to True only after the event passed all criteria setattr( event, 'PassedSubjetAnalyzer', False ) # Create two new lists for selected_btagged_jets and wquark_candidate_jets # Needs to be done here because the lists are needed in the mem config setattr( event, 'boosted_bjets', [] ) setattr( event, 'boosted_ljets', [] ) setattr( event, 'topCandidate', [] ) setattr( event, 'topCandidatesSync', [] ) setattr( event, 'othertopCandidate', [] ) setattr( event, 'higgsCandidate', [] ) setattr( event, 'higgsCandidateForSync', [] ) event.n_bjets = len( event.selected_btagged_jets_high ) event.n_ljets = len( list( event.wquark_candidate_jets ) ) ######################################## # Minimal event suitability: # - Needs to be single leptonic # - At least 1 httCandidate ######################################## # Check if the event is single leptonic or FH # for SYNC: REMOVE this cut #if not (event.is_sl or event.is_fh): #LC # return event # Get the top candidates # ====================================== # Keep track of number of httCandidates that passed the cut setattr( event, 'nhttCandidate', len( event.httCandidates ) ) setattr( event, 'nhttCandidate_aftercuts', 0 ) # Just run normal mem if there is no httCandidate present # Check if there is an httCandidate # if len( event.httCandidates ) == 0: # return event # All HTT candidates for sync all_tops = [] for candidate in event.httCandidates: # Veto tops unless all subjets pass jetID if not candidate.subjetIDPassed: continue # (optional eta cut) #if abs(candidate.eta) < 2.0: all_tops.append( copy.deepcopy(candidate) ) # TODO: Add eta cut also to analysis tops # Match the top to a fat jet # - Copies bbtag and tau_N, calculates n_subjettiness # - DOES NOT apply the n_subjettiness cut all_tops = self.Match_top_to_fatjet( event, all_tops, False ) for top in all_tops: top.fj_index = event.FatjetCA15ungroomed.index(top.matched_fatjet) # Sort by which ungroomed fj they are matched to all_tops = sorted(all_tops, key=lambda x: x.fj_index ) # Apply the cuts on the httCandidate tops = [] for candidate in event.httCandidates: if self.Apply_Cut_criteria( candidate ): tops.append( copy.deepcopy(candidate) ) # Match the top to a fat jet # - Copies bbtag and tau_N, calculates n_subjettiness # - Applies the n_subjettiness cut tops = self.Match_top_to_fatjet( event, tops, True ) other_tops = [] # Calculate delR with the lepton for all tops that survived the cut if event.is_sl: #LC for top in tops + all_tops: setattr( top, 'delR_lepton' , self.Get_DeltaR_two_objects( top, event.good_leptons[0] ) ) else: for top in tops + all_tops: setattr( top, 'delR_lepton' , -1 ) # Keep track of how many httCandidates passed event.nhttCandidate_aftercuts = len( tops ) #Find the best hadronic gen top match for each top candidate if self.cfg_comp.isMC: gentops = getattr(event, "genTopHad", []) if len(gentops)>0: for topcandidate in tops: lv1 = lvec(topcandidate) drs = [] for igentop, gentop in enumerate(gentops): lv2 = lvec(gentop) drs += [(lv1.DeltaR(lv2), gentop, igentop)] drs = sorted(drs, key=lambda x: x[0]) best = drs[0] topcandidate.genTopHad_dr = best[0] topcandidate.genTop = best[1] topcandidate.genTopHad_index = best[2] # Just run normal mem if there is no httCandidate surviving the cuts # Check if any candidates survived the cutoff criteria # if len(tops) == 0: # return event # If exactly 1 survived, simply continue with that candidate other_top_present = False top = None if len(tops) == 0: other_top_present = False elif len(tops) == 1: top = tops[0] other_top_present = False # If more than 1 candidate survived the cutoff criteria, choose the # one whose delR with the lepton was biggest else: if event.is_sl: #LC tops = sorted( tops, key=lambda x: -x.delR_lepton ) else: tops = sorted( tops, key=lambda x: x.pt) other_top_present = True top = tops[0] other_tops = tops[1:] if "subjet" in self.conf.general["verbosity"]: print "Number of top candidates ", len(tops) # Get a Higgs candidate # ====================================== #Types of fatjets to match to Higgs candidate fatjets_to_match = ["softdropz2b1", "softdrop", "softdropz2b1filt", "softdropfilt", "pruned", "subjetfiltered"] extra_higgs_vars = ["mass", "nallsubjets", "sj1pt", "sj1eta", "sj1phi", "sj1mass", "sj1btag", "sj2pt", "sj2eta", "sj2phi", "sj2mass", "sj2btag", "sj3pt", "sj3eta", "sj3phi", "sj3mass", "sj3btag", # only calc for subjetfiltered "sj12masspt", "sj12massb", "sj123masspt", # only calc for subjetfiltered "secondbtag", # only calc for subjetfiltered ] for fatjet_name in fatjets_to_match: self.Add_Higgs_Subjets_To_Fatjet(event, fatjet_name) higgs_present = False higgsCandidates = [] for fatjet in event.FatjetCA15ungroomed: # Turned off for now. TODO: Revisit Higgs/Top overlap removal # # Choose only fatjets that were not HTTv2 candidates for the higgs reco # # Check if the fatjet is not already matched to the chosen top candidate # if top and hasattr(fatjet, 'matched_top') and fatjet == top.matched_fatjet: # continue fatjet.n_subjettiness = -1 if fatjet.tau1 > 0: fatjet.n_subjettiness = fatjet.tau2 / fatjet.tau1 if top: fatjet.dr_top = self.Get_DeltaR_two_objects(fatjet, top) #set default extra variables for all fatjet types for fatjetkind in fatjets_to_match: for var in extra_higgs_vars: setattr(fatjet, var + "_" + fatjetkind, -9999) if self.cfg_comp.isMC: #match higgs candidate to generated higgs genhiggs = getattr(event, "GenHiggsBoson", []) if len(genhiggs)>0: lv1 = lvec(fatjet) lv2 = lvec(genhiggs[0]) fatjet.dr_genHiggs = lv1.DeltaR(lv2) #match higgs candidate to generated tops gentops = [x for x in getattr(event, "GenTop", []) if x.pt>self.GenTop_pt_cut] if len(gentops)>0: lv1 = lvec(fatjet) fatjet.dr_genTop = min([lv1.DeltaR(lvec(x)) for x in gentops]) higgsCandidates.append( fatjet ) higgs_present = True # Match higgs candidates to various fat jets for fatjetkind in fatjets_to_match: nmatch = self.Match_two_lists( higgsCandidates, 'higgs', getattr(event, "FatjetCA15" + fatjetkind), 'fatjet_' + fatjetkind, R_cut = self.R_cut_fatjets ) # Add properties of the matched fatjet to the higgs candidate for higgsCandidate in higgsCandidates: for fatjetkind in fatjets_to_match: matchjet = getattr(higgsCandidate, "matched_fatjet_" + fatjetkind, None) if matchjet != None: for var in extra_higgs_vars: if hasattr(matchjet,var): setattr(higgsCandidate, var + "_" + fatjetkind, getattr(matchjet,var)) # Sort higgs candidates by pt # We store all of them, so it does not really matter fow now higgsCandidates = sorted( higgsCandidates, key=lambda x: -x.pt ) ######################################## # Get the lists of particles: quarks, jets and subjets ######################################## # Get the subjets from the httCandidate # - Also sets transfer functions as attributes # - Returns subjets ordered by decreasing btag # - First subjet has btagFlag==1.0, the other two btagFlag==0.0 top_subjets = self.Get_Subjets( top ) if "subjet" in self.conf.general["verbosity"]: print "subjets" for subjet in top_subjets: print subjet if other_top_present: for top in other_tops: self.Get_Subjets( top ) # Set 'PDGID' to 1 for light, and to 5 for b for subjet in top_subjets: if subjet.btagFlag == 1.0: setattr( subjet, 'PDGID', 5 ) if subjet.btagFlag == 0.0: setattr( subjet, 'PDGID', 1 ) # Create two new lists for btagged_jets and wquark_candidate_jets in the # original events if event.is_sl: #LC reco_btagged_jets = copy.deepcopy( event.selected_btagged_jets_high ) reco_ltagged_jets = copy.deepcopy( list( event.wquark_candidate_jets ) ) else: #LC reco_ltagged_jets = event.buntagged_jets_bdisc reco_btagged_jets = event.btagged_jets_bdisc if len(tops) > 0: top_subjets = self.Get_Subjets( top ) if "subjet" in self.conf.general["verbosity"]: print "subjets" for subjet in top_subjets: print subjet if other_top_present: for top in other_tops: self.Get_Subjets( top ) # Set 'PDGID' to 1 for light, and to 5 for b # FIXME: do not use PDGID currently, as it ONLY works with the HEPTopTagger perm pruning strat #for subjet in top_subjets: # if subjet.btagFlag == 1.0: setattr( subjet, 'PDGID', 5 ) # if subjet.btagFlag == 0.0: setattr( subjet, 'PDGID', 1 ) # Create two new lists for btagged_jets and wquark_candidate_jets in the # original events reco_btagged_jets = copy.deepcopy( event.selected_btagged_jets_high ) reco_ltagged_jets = copy.deepcopy( list( event.wquark_candidate_jets ) ) for jet in reco_btagged_jets: setattr( jet, 'btag', getattr(jet,self.btagAlgo) ) setattr( jet, 'btagFlag', 1.0 ) #setattr( jet, 'PDGID', 0 ) for jet in reco_ltagged_jets: setattr( jet, 'btag', getattr(jet,self.btagAlgo) ) setattr( jet, 'btagFlag', 0.0 ) #setattr( jet, 'PDGID', 0 ) ######################################## # Matching ######################################## # Whenever a subjet has a 'match' (dR < dR_cut), the matched object should # excluded from the event # Match subjet to a bjet n_excluded_bjets = self.Match_two_lists( top_subjets, 'top_subjet', reco_btagged_jets, 'bjet' ) # Match subjet to a ljet n_excluded_ljets = self.Match_two_lists( top_subjets , 'top_subjet', reco_ltagged_jets, 'ljet' ) if "subjet" in self.conf.general["verbosity"]: print "subjet nMatchB={0} nMatchL={1}".format(n_excluded_bjets, n_excluded_ljets) #FIXME: Unify this for SL/DL/FH #from FH branch # # Stop adding after 4 b-jets # if event.is_sl:#LC # if len(boosted_bjets) == 4: break # event.PassedSubjetAnalyzer = True # # if event.is_fh: #LC: also add other light jets # for ljet in reco_ltagged_jets: # # Check if the l-jet is not excluded # if not hasattr( ljet, 'matched_top_subjet' ): # boosted_ljets.append( ljet ) # # # # # # If too many events are excluded, just run the default hypothesis # else: # if "subjet" in self.conf.general["verbosity"]: # print "[SubjetAnalyzer] subjet has too many overlaps, using reco" # boosted_bjets = reco_btagged_jets # boosted_ljets = reco_ltagged_jets # event.PassedSubjetAnalyzer = False #======= end from FH branch # In case of double matching, choose the match with lowest delR # (This is not expected to happen often) for subjet in top_subjets: if hasattr( subjet, 'matched_bjet' ) and \ hasattr( subjet, 'matched_ljet' ) : print '[SubjetAnalyzer] Double match detected' if subjet.matched_bjet_delR < subjet.matched_ljet_delR: del subjet.matched_ljet del subjet.matched_ljet_delR n_excluded_bjets -= 1 else: del subjet.matched_bjet del subjet.matched_bjet_delR n_excluded_ljets -= 1 ######################################## # Modifying the bjets and ljets lists ######################################## boosted_bjets = [] boosted_ljets = [] if n_excluded_bjets <= 1: if "subjet" in self.conf.general["verbosity"]: print "subjet replacing" # Add the subjets to the final output lists first for subjet in top_subjets: if subjet.btagFlag == 1.0: boosted_bjets.append( subjet ) if subjet.btagFlag == 0.0: boosted_ljets.append( subjet ) # Sort tl btagged jets by decreasing btag (to be sure, but should # already be done in previous analyzer) # Only resolved b-jets reco_btagged_jets = sorted( reco_btagged_jets, key=lambda x: -x.btag ) # Add up to 4 reco btagged jets to the output lists for bjet in reco_btagged_jets: # Check if the b-jet is not excluded if not hasattr( bjet, 'matched_top_subjet' ): boosted_bjets.append( bjet ) # Stop adding after 4 b-jets if len(boosted_bjets) == 4: break event.PassedSubjetAnalyzer = True # If too many events are excluded, just run the default hypothesis else: if "subjet" in self.conf.general["verbosity"]: print "[SubjetAnalyzer] subjet has too many overlaps, using reco" boosted_bjets = reco_btagged_jets boosted_ljets = reco_ltagged_jets event.PassedSubjetAnalyzer = False ######################################## # Write to event ######################################## # Store output lists in event event.higgsCandidate = higgsCandidates all_tops_to_add = [] # Add top matched to leading fatjet OR dummy for top in all_tops: if top.fj_index == 0: all_tops_to_add.append(top) break if len(all_tops_to_add) == 0: all_tops_to_add.append(DummyTop()) # Add top matched to sub-leading fatjet OR dummy for top in all_tops: if top.fj_index == 1: all_tops_to_add.append( top) break if len(all_tops_to_add) == 1: all_tops_to_add.append(DummyTop()) event.topCandidatesSync = all_tops_to_add if len(tops)>0: event.topCandidate = [ top ] event.othertopCandidate = other_tops event.boosted_bjets = boosted_bjets event.boosted_ljets = boosted_ljets event.n_boosted_bjets = len( boosted_bjets ) event.n_boosted_ljets = len( boosted_ljets ) event.n_excluded_bjets = n_excluded_bjets event.n_excluded_ljets = n_excluded_ljets #pdb.set_trace() if "subjet" in self.conf.general["verbosity"]: print '[SubjetAnalyzer] Exiting SubjetAnalyzer! event.PassedSubjetAnalyzer = {0}'.format( event.PassedSubjetAnalyzer ) ######################################## # Matching to Gen top ########################################### event.n_matched_TTgentop = -1 event.matched_TTgentop_pt = -1 event.n_matched_TTgenb = -1 event.n_matched_TTgenW = -1 if self.cfg_comp.isMC and len(tops)>0: self.Do_GenTop_Matching(event) return event ######################################## # Quark Matching ######################################## # This section is only useful for truth-level comparison, and can be turned # off if this is not needed. # Do_Quark_Matching( event ) sets number of matches with quarks as branches # in the event, but these branches do not have to be filled (they will be # automatically set to -1 in the final output root file). if self.cfg_comp.isMC: self.Do_Quark_Matching( event )