def drmatch(event, jet): dr_b, dr_wq1, dr_wq2 = 999, 999, 999 if jet: top, _ = closest(jet, event.hadGenTops) if top: dr_b = deltaR(jet, top.genB) dr_wq1 = deltaR(jet, event.genparts[top.genW.dauIdx[0]]) dr_wq2 = deltaR(jet, event.genparts[top.genW.dauIdx[1]]) else: w, _ = closest(jet, event.hadGenWs) if w: dr_wq1 = deltaR(jet, event.genparts[w.dauIdx[0]]) dr_wq2 = deltaR(jet, event.genparts[w.dauIdx[1]]) return dr_b, max(dr_wq1, dr_wq2), min(dr_wq1, dr_wq2)
def getmindr(event, jet, genParticles, pickGenW=False): dr = 999 if jet: gp, _ = closest(jet, genParticles) if gp: if pickGenW: gp = gp.genW dr = deltaR(jet, gp) return dr
def _do_matching(self, partons, fatjets): rlt = {} jets_to_match = [j for j in fatjets] for p in partons: fj, dR = closest(p, jets_to_match) if dR < self._maxDeltaRJetParton: rlt[p] = fj jets_to_match.remove(fj) else: rlt[p] = _NullObject() return rlt
def fillFatJetInfo(self, event): self.out.fillBranch("n_fatjet", len(event.fatjets)) for idx in ([1, 2] if self._channel == 'qcd' else [1]): prefix = 'fj_%d_' % idx fj = event.fatjets[idx - 1] try: self.out.fillBranch(prefix + "DeepAK8MD_ZHbbvsQCD", fj.deepTagMD_ZHbbvsQCD) self.out.fillBranch(prefix + "DeepAK8MD_ZHccvsQCD", fj.deepTagMD_ZHccvsQCD) self.out.fillBranch(prefix + "DeepAK8MD_bbVsLight", fj.deepTagMD_bbvsLight) self.out.fillBranch( prefix + "DeepAK8MD_bbVsTop", (1 / (1 + (fj.deepTagMD_TvsQCD / fj.deepTagMD_HbbvsQCD) * (1 - fj.deepTagMD_HbbvsQCD) / (1 - fj.deepTagMD_TvsQCD)))) except RuntimeError: self.out.fillBranch(prefix + "DeepAK8MD_ZHbbvsQCD", -1) self.out.fillBranch(prefix + "DeepAK8MD_ZHccvsQCD", -1) self.out.fillBranch(prefix + "DeepAK8MD_bbVsLight", -1) self.out.fillBranch(prefix + "DeepAK8MD_bbVsTop", -1) try: self.out.fillBranch(prefix + "ParticleNetMD_Xbb", fj.ParticleNetMD_probXbb) self.out.fillBranch(prefix + "ParticleNetMD_Xcc", fj.ParticleNetMD_probXcc) self.out.fillBranch(prefix + "ParticleNetMD_Xqq", fj.ParticleNetMD_probXqq) self.out.fillBranch( prefix + "ParticleNetMD_QCD", convert_prob(jet, None, prefix='ParticleNetMD_prob')) self.out.fillBranch( prefix + "ParticleNetMD_XbbVsQCD", convert_prob(fj, ['Xbb'], prefix='ParticleNetMD_prob')) self.out.fillBranch( prefix + "ParticleNetMD_XccVsQCD", convert_prob(fj, ['Xcc'], prefix='ParticleNetMD_prob')) except RuntimeError: self.out.fillBranch(prefix + "ParticleNetMD_HbbVsQCD", -1) self.out.fillBranch(prefix + "ParticleNetMD_HccVsQCD", -1) self.out.fillBranch( prefix + "is_lep_overlap", closest(fj, event.preselLeptons)[1] < self._jetConeSize) self.out.fillBranch(prefix + "pt", fj.pt) self.out.fillBranch(prefix + "eta", fj.eta) self.out.fillBranch(prefix + "phi", fj.phi) self.out.fillBranch(prefix + "sdmass", fj.msoftdrop) self.out.fillBranch(prefix + "tau21", fj.tau2 / fj.tau1 if fj.tau1 > 0 else 99) self.out.fillBranch(prefix + "btagcsvv2", fj.btagCSVV2) try: self.out.fillBranch(prefix + "btagjp", fj.btagJP) except RuntimeError: self.out.fillBranch(prefix + "btagjp", -1) assert (len(fj.subjets) == 2) for idx_sj, sj in enumerate(fj.subjets): prefix_sj = prefix + 'sj%d_' % (idx_sj + 1) self.out.fillBranch(prefix_sj + "pt", sj.pt) self.out.fillBranch(prefix_sj + "eta", sj.eta) self.out.fillBranch(prefix_sj + "phi", sj.phi) self.out.fillBranch(prefix_sj + "btagcsvv2", sj.btagCSVV2) try: self.out.fillBranch(prefix_sj + "btagdeepcsv", sj.btagDeepB) except RuntimeError: self.out.fillBranch(prefix_sj + "btagdeepcsv", -1) try: self.out.fillBranch(prefix_sj + "btagjp", sj.btagJP) except RuntimeError: self.out.fillBranch(prefix_sj + "btagjp", -1) self.out.fillBranch(prefix_sj + "nsv", len(sj.sv_list)) sv = sj.sv_list[0] if len(sj.sv_list) else _NullObject() fill_sv = self._get_filler( sv) # wrapper, fill default value if sv=None fill_sv(prefix_sj + "sv1_pt", sv.pt) fill_sv(prefix_sj + "sv1_mass", sv.mass) fill_sv(prefix_sj + "sv1_masscor", corrected_svmass(sv) if sv else 0) fill_sv(prefix_sj + "sv1_ntracks", sv.ntracks) fill_sv(prefix_sj + "sv1_dxy", sv.dxy) fill_sv(prefix_sj + "sv1_dxysig", sv.dxySig) fill_sv(prefix_sj + "sv1_dlen", sv.dlen) fill_sv(prefix_sj + "sv1_dlensig", sv.dlenSig) fill_sv(prefix_sj + "sv1_chi2ndof", sv.chi2) fill_sv(prefix_sj + "sv1_pangle", sv.pAngle) sj1, sj2 = fj.subjets try: sv1, sv2 = sj1.sv_list[0], sj2.sv_list[0] sv = sv1 if sv1.dxySig > sv2.dxySig else sv2 self.out.fillBranch(prefix + "sj12_masscor_dxysig", corrected_svmass(sv) if sv else 0) except IndexError: # if len(sv_list) == 0 self.out.fillBranch(prefix + "sj12_masscor_dxysig", 0) # matching variables if self.isMC: self.out.fillBranch(prefix + "nbhadrons", fj.nBHadrons) self.out.fillBranch(prefix + "nchadrons", fj.nCHadrons) self.out.fillBranch(prefix + "sj1_nbhadrons", sj1.nBHadrons) self.out.fillBranch(prefix + "sj1_nchadrons", sj1.nCHadrons) self.out.fillBranch(prefix + "sj2_nbhadrons", sj2.nBHadrons) self.out.fillBranch(prefix + "sj2_nchadrons", sj2.nCHadrons)
def analyze(self, event): """ process event, return True (go to next module) or False (fail, go to next event) """ electrons = list(Collection(event, "Electron")) muons = list(Collection(event, "Muon")) jets = list(Collection(event, "Jet")) taus = list(Collection(event, "Tau")) flag = Object(event, "Flag") met = Object(event, "MET") # in case of systematic take the shifted values are default # For the central values, need to include jetMetTool all the time # Jet systematics if self.syst_var == "": syst_var = "nom" else: syst_var = self.syst_var ############################## ## corrections and MET ############################## try: var_jet_pts = getattr(event, "Jet_pt_{}".format(syst_var), None) if var_jet_pts: for i,jet in enumerate(jets): jet.pt = var_jet_pts[i] else: print 'WARNING: jet pts with variation {}' 'not available, using the nominal value'.format(syst_var) except: var_jet_pts = getattr(event, "Jet_pt_nom", None) for i,jet in enumerate(jets): jet.pt = var_jet_pts[i] try: var_met_pt = getattr(event, "MET_pt_{}".format(syst_var), None) var_met_phi = getattr(event, "MET_phi_{}".format(syst_var), None) if var_met_pt: met.pt = var_met_pt else: print 'WARNING: MET pt with variation ' '{} not available, using the nominal value'.format(syst_var) if var_met_phi: met.phi = var_met_phi else: print 'WARNING: MET phi with variation {}' 'not available, using the nominal value'.format(syst_var) except: var_met_pt = getattr(event, "MET_pt_nom", None) var_met_phi = getattr(event, "MET_phi_nom", None) if var_met_pt: met.pt = var_met_pt if var_met_phi: met.phi = var_met_phi met_p4 = ROOT.TLorentzVector() met_p4.SetPtEtaPhiM(met.pt,0.0,met.phi, 0.0) # Electrons Energy if "ElectronEn" in self.syst_var: (met_px, met_py) = ( met.pt*np.cos(met.phi), met.pt*np.sin(met.phi) ) if "Up" in self.syst_var: for i, elec in enumerate(electrons): met_px = met_px + (elec.energyErr)*np.cos(elec.phi)/math.cosh(elec.eta) met_py = met_py + (elec.energyErr)*np.sin(elec.phi)/math.cosh(elec.eta) elec.pt = elec.pt + elec.energyErr/math.cosh(elec.eta) else: for i, elec in enumerate(electrons): met_px = met_px - (elec.energyErr)*np.cos(elec.phi)/math.cosh(elec.eta) met_py = met_py - (elec.energyErr)*np.sin(elec.phi)/math.cosh(elec.eta) elec.pt = elec.pt - elec.energyErr/math.cosh(elec.eta) met.pt = math.sqrt(met_px**2 + met_py**2) met.phi = math.atan2(met_py, met_px) # Muons Energy if self.isMC: muons_pts = getattr(event, "Muon_corrected_pt") for i, muon in enumerate(muons): muon.pt = muons_pts[i] if "MuonEn" in self.syst_var: (met_px, met_py) = ( met.pt*np.cos(met.phi), met.pt*np.sin(met.phi) ) if "Up" in self.syst_var: muons_pts = getattr(event, "Muon_correctedUp_pt") for i, muon in enumerate(muons): met_px = met_px - (muons_pts[i] - muon.pt)*np.cos(muon.phi) met_py = met_py - (muons_pts[i] - muon.pt)*np.sin(muon.phi) muon.pt = muons_pts[i] else: muons_pts = getattr(event, "Muon_correctedDown_pt") for i, muon in enumerate(muons): met_px =met_px - (muons_pts[i] - muon.pt)*np.cos(muon.phi) met_py =met_py - (muons_pts[i] - muon.pt)*np.sin(muon.phi) muon.pt = muons_pts[i] met.pt = math.sqrt(met_px**2 + met_py**2) met.phi = math.atan2(met_py, met_px) pass_met_filter = self.met_filter(flag, True) # filling and contructing the event categorisation self.out.fillBranch("met_pt{}".format(self.syst_suffix), met.pt) self.out.fillBranch("met_phi{}".format(self.syst_suffix), met.phi) self.out.fillBranch("met_filter{}".format(self.syst_suffix), pass_met_filter) ############################## ## process leptons ############################## muons.sort(key=lambda muon: muon.pt, reverse=True) electrons.sort(key=lambda el: el.pt, reverse=True) # Choose tight-quality e/mu for event categorization good_muons = [] for idx,mu in enumerate(muons): isoLep = mu.pfRelIso04_all pass_ips = abs(mu.dxy) < 0.02 and abs(mu.dz) < 0.1 pass_fid = abs(mu.eta) < 2.4 and mu.pt >= (25 if idx==0 else 20) pass_ids = mu.tightId and isoLep <= 0.15 if pass_fid and pass_ids and pass_ips: good_muons.append(mu) good_electrons = [] for idy,el in enumerate(electrons): id_CB = el.cutBased # changing to MVA based ID : if el.pt >= (25 if idy==0 else 20) and abs(el.eta) <= 2.5 and self.electron_id(el, "90"): good_electrons.append(el) # let sort the muons in pt good_muons.sort(key=lambda x: x.pt, reverse=True) good_electrons.sort(key=lambda x: x.pt, reverse=True) # Find any remaining e/mu that pass looser selection extra_leptons = [] for mu in muons: isoLep = mu.pfRelIso04_all pass_ids = mu.softId and isoLep <= 0.25 pass_fid = abs(mu.eta) < 2.4 and mu.pt >= 7 if tk.closest(mu, good_muons)[1] < 0.01: continue if pass_fid and pass_ids: extra_leptons.append(mu) for el in electrons: pass_fid = abs(el.eta) < 2.5 and el.pt >= 7 if tk.closest(el, good_electrons)[1] < 0.01: continue if pass_fid and self.electron_id(el, "WPL"): extra_leptons.append(el) good_leptons = good_electrons + good_muons good_leptons.sort(key=lambda x: x.pt, reverse=True) extra_leptons.sort(key=lambda x: x.pt, reverse=True) ngood_leptons = len(good_leptons) nextra_leptons = len(extra_leptons) _leading_lep_flavor = 0 if len(good_muons) and len(good_electrons): if good_muons[0].pt > good_electrons[0].pt: _leading_lep_flavor = 1 _leading_lep_pt = good_leptons[0].pt if ngood_leptons else 0.0 _leading_lep_eta = good_leptons[0].eta if ngood_leptons else -99. _leading_lep_phi = good_leptons[0].phi if ngood_leptons else -99. _trailing_lep_pt = good_leptons[1].pt if ngood_leptons >= 2 else 0.0 _trailing_lep_eta = good_leptons[1].eta if ngood_leptons >= 2 else -99. _trailing_lep_phi = good_leptons[1].phi if ngood_leptons >= 2 else -99. self.out.fillBranch("ngood_leptons{}".format(self.syst_suffix), ngood_leptons) self.out.fillBranch("nextra_leptons{}".format(self.syst_suffix), nextra_leptons) self.out.fillBranch("leading_lep_flavor{}".format(self.syst_suffix), _leading_lep_flavor) self.out.fillBranch("leading_lep_pt{}".format(self.syst_suffix), _leading_lep_pt) self.out.fillBranch("leading_lep_eta{}".format(self.syst_suffix), _leading_lep_eta) self.out.fillBranch("leading_lep_phi{}".format(self.syst_suffix), _leading_lep_phi) self.out.fillBranch("trailing_lep_pt{}".format(self.syst_suffix), _trailing_lep_pt) self.out.fillBranch("trailing_lep_eta{}".format(self.syst_suffix), _trailing_lep_eta) self.out.fillBranch("trailing_lep_phi{}".format(self.syst_suffix), _trailing_lep_phi) if False: print "number of leptons [all, good, extra]: ", ngood_leptons, " : ", nextra_leptons print " CBId electrons : ", [e.cutBased for e in good_electrons] print " WP90 electrons : ", [e.mvaFall17Iso_WP90 for e in good_electrons] print " muons : ", [e.tightId for e in good_muons] print " lepton pts : ", [e.pt for e in good_leptons] # Leptons efficiency/Trigger/Isolation Scale factors # These are applied only of the first 2 leading leptons if self.isMC: w_muon_SF = w_electron_SF = 1.0 w_muon_SFUp = w_electron_SFUp = 1.0 w_muon_SFDown = w_electron_SFDown = 1.0 if ngood_leptons >= 2: if abs(good_leptons[0].pdgId) == 11: w_electron_SF *= good_leptons[0].SF w_electron_SFUp *= (good_leptons[0].SF + good_leptons[0].SFErr) w_electron_SFDown *= (good_leptons[0].SF - good_leptons[0].SFErr) if abs(good_leptons[0].pdgId) == 11: w_electron_SF *= good_leptons[1].SF w_electron_SFUp *= (good_leptons[1].SF + good_leptons[1].SFErr) w_electron_SFDown *= (good_leptons[1].SF - good_leptons[1].SFErr) if abs(good_leptons[0].pdgId) == 13: w_muon_SF *= good_leptons[0].SF w_muon_SFUp *= (good_leptons[0].SF + good_leptons[0].SFErr) w_muon_SFDown *= (good_leptons[0].SF - good_leptons[0].SFErr) if abs(good_leptons[1].pdgId) == 13: w_muon_SF *= good_leptons[1].SF w_muon_SFUp *= (good_leptons[1].SF + good_leptons[1].SFErr) w_muon_SFDown *= (good_leptons[1].SF - good_leptons[1].SFErr) self.out.fillBranch("w_muon_SF" , w_muon_SF ) self.out.fillBranch("w_muon_SFUp" , w_muon_SFUp ) self.out.fillBranch("w_muon_SFDown" , w_muon_SFDown ) self.out.fillBranch("w_electron_SF" , w_electron_SF ) self.out.fillBranch("w_electron_SFUp" , w_electron_SFUp ) self.out.fillBranch("w_electron_SFDown", w_electron_SFDown) # process taus had_taus = [] for tau in taus: if tk.closest(tau, good_leptons)[1] < 0.4: continue # only hadronic tau decay if tau.decayMode != 5: continue if tau.pt > 18 and abs(tau.eta) <= 2.3: had_taus.append(tau) _nhad_taus = len(had_taus) self.out.fillBranch("nhad_taus{}".format(self.syst_suffix), _nhad_taus) self.out.fillBranch("lead_tau_pt{}".format(self.syst_suffix), had_taus[0].pt if _nhad_taus else 0) ############################## ## process jet ############################## z_candidate = [] zcand_p4 = ROOT.TLorentzVector() emulated_met = ROOT.TLorentzVector() all_lepton_p4 = ROOT.TLorentzVector() rem_lepton_p4 = ROOT.TLorentzVector() good_jets = [] good_bjets = [] for jet in jets: if jet.pt < 30.0 or abs(jet.eta) > 4.7: continue if not jet.jetId: continue if tk.closest(jet, good_leptons)[1] < 0.4: continue good_jets.append(jet) # Count b-tag with medium WP DeepJet # ref : https://twiki.cern.ch/twiki/bin/view/CMS/BtagRecommendation if abs(jet.eta) <= 2.4 and jet.btagDeepFlavB > self.btag_id("loose"): good_bjets.append(jet) _ngood_jets = len(good_jets) _ngood_bjets = len(good_bjets) good_jets.sort(key=lambda jet: jet.pt, reverse=True) good_bjets.sort(key=lambda jet: jet.pt, reverse=True) _lead_jet_pt = good_jets[0].pt if _ngood_jets >= 1 else 0. _lead_jet_eta = good_jets[0].eta if _ngood_jets >= 1 else -99. _lead_jet_phi = good_jets[0].phi if _ngood_jets >= 1 else -99. _lead_jet_mass = good_jets[0].mass if _ngood_jets >= 1 else -99. _trail_jet_pt = good_jets[1].pt if _ngood_jets >= 2 else 0. _trail_jet_eta = good_jets[1].eta if _ngood_jets >= 2 else -99. _trail_jet_phi = good_jets[1].phi if _ngood_jets >= 2 else -99. _trail_jet_mass = good_jets[1].mass if _ngood_jets >= 2 else -99. _third_jet_pt = good_jets[2].pt if _ngood_jets >= 3 else 0. _third_jet_eta = good_jets[2].eta if _ngood_jets >= 3 else -99. _third_jet_phi = good_jets[2].phi if _ngood_jets >= 3 else -99. _third_jet_mass = good_jets[2].mass if _ngood_jets >= 3 else -99. _H_T = sum([jet.pt for jet in good_jets]) _dphi_j_met = tk.deltaPhi(good_jets[0], met.phi) if _ngood_jets >= 1 else -99. _lead_bjet_pt = good_bjets[0].pt if _ngood_bjets else 0. self.out.fillBranch("ngood_jets{}".format(self.syst_suffix), _ngood_jets) self.out.fillBranch("ngood_bjets{}".format(self.syst_suffix), _ngood_bjets) self.out.fillBranch("lead_jet_pt{}".format(self.syst_suffix), _lead_jet_pt) self.out.fillBranch("lead_jet_eta{}".format(self.syst_suffix), _lead_jet_eta) self.out.fillBranch("lead_jet_phi{}".format(self.syst_suffix), _lead_jet_phi) self.out.fillBranch("lead_jet_mass{}".format(self.syst_suffix), _lead_jet_mass) self.out.fillBranch("trail_jet_pt{}".format(self.syst_suffix), _trail_jet_pt) self.out.fillBranch("trail_jet_eta{}".format(self.syst_suffix), _trail_jet_eta) self.out.fillBranch("trail_jet_phi{}".format(self.syst_suffix), _trail_jet_phi) self.out.fillBranch("trail_jet_mass{}".format(self.syst_suffix), _trail_jet_mass) self.out.fillBranch("third_jet_pt{}".format(self.syst_suffix), _third_jet_pt) self.out.fillBranch("third_jet_eta{}".format(self.syst_suffix), _third_jet_eta) self.out.fillBranch("third_jet_phi{}".format(self.syst_suffix), _third_jet_phi) self.out.fillBranch("third_jet_mass{}".format(self.syst_suffix), _third_jet_mass) self.out.fillBranch("H_T{}".format(self.syst_suffix), _H_T) self.out.fillBranch("delta_phi_j_met{}".format(self.syst_suffix), _dphi_j_met) self.out.fillBranch("lead_bjet_pt{}".format(self.syst_suffix), _lead_bjet_pt) ############################## ## construct Z and category ############################## lep_category = 0 if ngood_leptons < 2: lep_category = -1 if ngood_leptons == 2 and nextra_leptons==0: # constructing the signal region if (good_leptons[0].pdgId * good_leptons[1].pdgId) == -11*11: lep_category = 1 # EE category if (good_leptons[0].pdgId * good_leptons[1].pdgId) == -11*13: lep_category = 2 # EM category if (good_leptons[0].pdgId * good_leptons[1].pdgId) == -13*13: lep_category = 3 # MM category z_candidate = [good_leptons[0], good_leptons[1]] zcand_p4 = good_leptons[0].p4() + good_leptons[1].p4() all_lepton_p4 = zcand_p4 elif ngood_leptons == 3 and nextra_leptons==0: # constructing the 3 leptons CR for pair in itertools.combinations(good_leptons, 2): if pair[0].pdgId == -pair[1].pdgId: zcand_ = pair[0].p4() + pair[1].p4() if abs(zcand_.M()-self.zmass) < abs(zcand_p4.M()-self.zmass): zcand_p4 = zcand_ z_candidate = list(pair) lep3_idx_ = 3 - good_leptons.index(pair[0]) - good_leptons.index(pair[1]) emulated_met = good_leptons[lep3_idx_].p4() + met_p4 all_lepton_p4 = zcand_ + good_leptons[lep3_idx_].p4() rem_lepton_p4 = good_leptons[lep3_idx_].p4() if abs(pair[0].pdgId) == 11: lep_category = 4 # EEL category if abs(pair[0].pdgId) == 13: lep_category = 5 # MML category elif ngood_leptons>=2 and (ngood_leptons + nextra_leptons) == 4: # constructing the 4 leptons CR for pair in itertools.combinations(good_leptons, 2): # checking if OSSF pair rem_pair = [x for x in good_leptons + extra_leptons if x not in pair] if (pair[0].pdgId == -pair[1].pdgId) and (rem_pair[0].pdgId == -rem_pair[1].pdgId): zcand_0 = pair[0].p4() + pair[1].p4() zcand_1 = rem_pair[0].p4() + rem_pair[1].p4() if abs(zcand_0.M()-self.zmass) < abs(zcand_p4.M()-self.zmass): zcand_p4 = zcand_0 z_candidate = pair emulated_met = zcand_1 + met_p4 all_lepton_p4 = zcand_p4 + zcand_1 rem_lepton_p4 = zcand_1 if abs(pair[0].pdgId) == 11: lep_category = 6 # EELL category if abs(pair[0].pdgId) == 13: lep_category = 7 # MMLL category else: # too many bad leptons, with no obvious meaning ? if ngood_leptons==1 and (ngood_leptons + nextra_leptons)>=1: lep_category = -2 elif ngood_leptons>=2 and (ngood_leptons + nextra_leptons)>=2: lep_category = -3 else: lep_category = -4 # filling MonoZ type of variables self.out.fillBranch("lep_category{}".format(self.syst_suffix), lep_category) self.out.fillBranch("Z_pt{}".format(self.syst_suffix), zcand_p4.Pt()) self.out.fillBranch("Z_eta{}".format(self.syst_suffix), zcand_p4.Eta()) self.out.fillBranch("Z_phi{}".format(self.syst_suffix), zcand_p4.Phi()) self.out.fillBranch("Z_mass{}".format(self.syst_suffix), zcand_p4.M()) self.out.fillBranch("Z_mt{}".format(self.syst_suffix), zcand_p4.Mt()) ############################## ## high level info ############################## _delta_zphi = tk.deltaPhi(z_candidate[0].phi, z_candidate[1].phi) if lep_category > 0 else -99 _delta_zdR = tk.deltaR(z_candidate[0].eta, z_candidate[0].phi, z_candidate[1].eta, z_candidate[1].phi,) if lep_category > 0 else -99 _delta_zeta = abs(z_candidate[0].eta - z_candidate[1].eta) if lep_category > 0 else -99 _delta_phi_zmet = tk.deltaPhi(zcand_p4.Phi(), met.phi) _vec_delta_balance = (met_p4 - zcand_p4).Pt()/zcand_p4.Pt() if zcand_p4.Pt() != 0 else -1 _sca_delta_balance = met.pt/zcand_p4.Pt() if zcand_p4.Pt() != 0 else -1 # hadronic recoil had_recoil_p4 = ROOT.TLorentzVector() had_recoil_p4 += met_p4 for lep in good_leptons + extra_leptons: had_recoil_p4 += lep.p4() had_recoil_p4 = -had_recoil_p4 _delta_met_rec = tk.deltaPhi(met.phi, had_recoil_p4.Phi()) if lep_category > 0 else -99 _MT = np.sqrt(2 * zcand_p4.Pt() * var_met_pt * (1 - np.cos(_delta_phi_zmet))) # defined as from https://arxiv.org/pdf/1808.09054.pdf _Ell = np.sqrt(zcand_p4.Mag2() + zcand_p4.M2()) _altMT = np.sqrt(np.power(_Ell + met_p4.Pt(),2) + (met_p4 + zcand_p4).Mag2()) # checking the transverse mass _rem_p4 = ROOT.TLorentzVector() _rem_p4.SetPtEtaPhiM(rem_lepton_p4.Pt(), 0, rem_lepton_p4.Phi(), 0) self.out.fillBranch("delta_phi_ll{}".format(self.syst_suffix), _delta_zphi) self.out.fillBranch("delta_eta_ll{}".format(self.syst_suffix), _delta_zeta) self.out.fillBranch("delta_R_ll{}".format(self.syst_suffix), _delta_zdR) self.out.fillBranch("delta_phi_ZMet{}".format(self.syst_suffix), _delta_phi_zmet) self.out.fillBranch("vec_balance{}".format(self.syst_suffix), _vec_delta_balance) self.out.fillBranch("sca_balance{}".format(self.syst_suffix), _sca_delta_balance) self.out.fillBranch("hadronic_recoil{}".format(self.syst_suffix), had_recoil_p4.Pt()) self.out.fillBranch("delta_met_rec{}".format(self.syst_suffix), _delta_met_rec) self.out.fillBranch("emulatedMET{}".format(self.syst_suffix), emulated_met.Pt()) self.out.fillBranch("emulatedMET_phi{}".format(self.syst_suffix), emulated_met.Phi()) self.out.fillBranch("mass_alllep{}".format(self.syst_suffix), all_lepton_p4.M()) self.out.fillBranch("pt_alllep{}".format(self.syst_suffix), all_lepton_p4.Pt()) self.out.fillBranch("remll_mass{}".format(self.syst_suffix), rem_lepton_p4.M()) self.out.fillBranch("MT{}".format(self.syst_suffix), _MT) self.out.fillBranch("altMT{}".format(self.syst_suffix), _altMT) self.out.fillBranch("trans_mass{}".format(self.syst_suffix), (_rem_p4 + met_p4).M()) # Let remove the negative categories with no obvious meaning meaning # This will reduce the size of most of the bacground and data if (lep_category > 0 and zcand_p4.Pt()>60 and zcand_p4.M() > 55 and zcand_p4.M() < 127): return True else: return False
def prepareEvent(self, event): logging.debug('processing event %d' % event.event) ## met selection if event.met.pt < 50.0: return False ## muon selection muSubJets = [] for j in Collection(event, "CustomAK4CHS"): if j.pt > 30 and abs(j.eta) < 2.4: muSubJets.append(j) event._allMuons = Collection(event, "Muon") event.muons = [] for muon in event._allMuons: if muon.pt > 55 and abs(muon.eta) < 2.4 and muon.tightId and abs( muon.dxy) < 0.2 and abs(muon.dz) < 0.5: j, muon.drjet = closest(muon, muSubJets) muon.ptrel = muon.p4().Perp(j.p4().Vect()) if j else 0 # if muon.pfRelIso04_all < 0.15: if muon.drjet > 0.4 or muon.ptrel > 25: event.muons.append(muon) if len(event.muons) != 1: return False # #leptonic W pt cut event.mu = event.muons[0] event.leptonicW = event.mu.p4() + event.met.p4() if event.leptonicW.Pt() < 250.0: return False ## b-tag AK4 jet selection event.ak4jets = [] for j in event._allJets: if not (j.pt > 25.0 and abs(j.eta) < 2.4 and (j.jetId & 2)): continue if j.btagCSVV2 > 0.8484 and\ abs(deltaPhi(j, event.muons[0])) < 2.0: event.ak4jets.append(j) if len(event.ak4jets) < 1: return False # # selection on AK8 jets event.ak8jets = [] for fj in event._allAK8jets: if not (fj.pt > 200 and abs(fj.eta) < 2.4 and (fj.jetId & 2)): continue if abs(deltaPhi(fj, event.muons[0])) > 2.0: event.ak8jets.append(fj) if len(event.ak8jets) < 1: return False # # selection on CA15 jets event.ca15jets = [] for fj in event._allCA15jets: if not (fj.pt > 200 and abs(fj.eta) < 2.4 and (fj.jetId & 2)): continue if abs(deltaPhi(fj, event.muons[0])) > 2.0: event.ca15jets.append(fj) if len(event.ca15jets) < 1: return False ## require the leading ak8 & ca15 jets overlap if deltaR(event.ak8jets[0], event.ca15jets[0]) > 0.8: return False # # selection on HOTVR jets event.hotvrjets = [] for fj in event._allHOTVRjets: if not (fj.pt > 200 and abs(fj.eta) < 2.4): continue if abs(deltaPhi(fj, event.muons[0])) > 2.0: event.hotvrjets.append(fj) ## return True if passes selection return True
def _fill_matching(self, parton, daughters, fatjetCollection, fjname): fj, dR = closest(parton, fatjetCollection) self.out.fillBranch("dR_gen_%s" % fjname, dR) return _NullObject() if dR > self._maxDeltaRJetParton else fj
def analyze(self, event): """ process event, return True (go to next module) or False (fail, go to next event) """ # skip useless events if event.lep_category <= 0: return False # Get collection from event tree electrons = list(Collection(event, "Electron")) muons = list(Collection(event, "Muon")) jets = list(Collection(event, "Jet")) # in case of systematic take the shifted values are default # For the central values, need to include jetMetTool all the time # Jet systematics if self.syst_var == "": syst_var = "nom" else: syst_var = self.syst_var # checking something try: var_jet_pts = getattr(event, "Jet_pt_{}".format(syst_var), None) if var_jet_pts: for i, jet in enumerate(jets): jet.pt = var_jet_pts[i] else: print 'WARNING: jet pts with variation {}' 'not available, using the nominal value'.format(syst_var) except: var_jet_pts = getattr(event, "Jet_pt_nom", None) for i, jet in enumerate(jets): jet.pt = var_jet_pts[i] # Get variables from event tree Z_pt = event.Z_pt Z_eta = event.Z_eta Z_phi = event.Z_phi Z_mass = event.Z_mass Z_p4 = ROOT.TLorentzVector() Z_p4.SetPtEtaPhiM(Z_pt, Z_eta, Z_phi, Z_mass) Z_p4_bst = ROOT.TLorentzVector(Z_p4) met_pt = event.met_pt met_phi = event.met_phi met_p4 = ROOT.TLorentzVector() met_p4.SetPtEtaPhiM(met_pt, 0., met_phi, 0.) met_p4_bst = ROOT.TLorentzVector(met_p4) emulatedMET_pt_bst = event.emulatedMET emulatedMET_phi = event.emulatedMET_phi emulatedMET_p4 = ROOT.TLorentzVector() emulatedMET_p4.SetPtEtaPhiM(emulatedMET_pt_bst, 0., emulatedMET_phi, 0.) emulatedMET_p4_bst = ROOT.TLorentzVector(emulatedMET_p4) # process leptons good_leptons = [] good_muons = [] good_electrons = [] # Choose tight-quality e/mu for event categorization for idx, mu in enumerate(muons): isoLep = mu.pfRelIso04_all pass_ips = abs(mu.dxy) < 0.02 and abs(mu.dz) < 0.1 pass_fid = abs(mu.eta) < 2.4 and mu.pt >= (25 if idx == 0 else 20) pass_ids = mu.tightId and isoLep <= 0.15 if pass_fid and pass_ids and pass_ips: good_muons.append(mu) for idy, el in enumerate(electrons): if el.pt >= (25 if idy == 0 else 20) and abs( el.eta) <= 2.5 and self.electron_id(el, "90"): good_electrons.append(el) # Find any remaining e/mu that pass looser selection extra_leptons = [] for mu in muons: isoLep = mu.pfRelIso04_all pass_ids = mu.softId and isoLep <= 0.25 pass_fid = abs(mu.eta) < 2.4 and mu.pt >= 10 if tk.closest(mu, good_muons)[1] < 0.01: continue if pass_fid and pass_ids: extra_leptons.append(mu) for el in electrons: pass_fid = abs(el.eta) < 2.5 and el.pt >= 10 if tk.closest(el, good_electrons)[1] < 0.01: continue if pass_fid and self.electron_id(el, "WPL"): extra_leptons.append(el) # sort the leptons in pt good_muons.sort(key=lambda x: x.pt, reverse=True) good_electrons.sort(key=lambda x: x.pt, reverse=True) good_leptons = good_electrons + good_muons good_leptons.sort(key=lambda x: x.pt, reverse=True) extra_leptons.sort(key=lambda x: x.pt, reverse=True) ngood_leptons = len(good_leptons) nextra_leptons = len(extra_leptons) if ngood_leptons != event.ngood_leptons or nextra_leptons != event.nextra_leptons: print( 'n good (extra) leptons: {} ({}) in VBSProducer, {} ({}) in MonoZProducer.' .format(ngood_leptons, nextra_leptons, event.ngood_leptons, event.nextra_leptons)) lead_lep_p4 = good_leptons[0].p4( ) if ngood_leptons else ROOT.TLorentzVector(0., 0., 0., 0.) lead_lep_p4_bst = ROOT.TLorentzVector(lead_lep_p4) lead_lep_pt = good_leptons[0].pt if ngood_leptons else 0. trail_lep_p4 = good_leptons[1].p4( ) if ngood_leptons >= 2 else ROOT.TLorentzVector(0., 0., 0., 0.) trail_lep_p4_bst = ROOT.TLorentzVector(trail_lep_p4) trail_lep_pt = good_leptons[1].pt if ngood_leptons >= 2 else 0. # process jet good_jets = [] good_jets_p4 = ROOT.TLorentzVector(0., 0., 0., 0.) et_jets20 = 0. et_jets30 = 0. for jet in jets: if not jet.jetId: continue if tk.closest(jet, good_leptons)[1] < 0.4: continue if jet.pt <= 20 or abs(jet.eta) > 4.7: continue et_jets20 += jet.p4().Et() if jet.pt < 30.: continue et_jets30 += jet.p4().Et() good_jets.append(jet) good_jets_p4 += jet.p4() # sort the jets by pt good_jets.sort(key=lambda jet: jet.pt, reverse=True) ngood_jets = len(good_jets) if ngood_jets != event.ngood_jets: print 'ngood_jets: {} in VBSProducer, {} in MonoZProducer'.format( ngood_jets, event.ngood_jets) lead_jet_p4 = good_jets[0].p4() if ngood_jets else ROOT.TLorentzVector( 0., 0., 0., 0.) lead_jet_pt = good_jets[0].pt if ngood_jets else 0. lead_jet_phi = good_jets[0].phi if ngood_jets else 0. lead_jet_eta = good_jets[0].eta if ngood_jets else -99. trail_jet_p4 = good_jets[1].p4( ) if ngood_jets > 1 else ROOT.TLorentzVector(0., 0., 0., 0.) trail_jet_pt = good_jets[1].pt if ngood_jets > 1 else 0. trail_jet_phi = good_jets[1].phi if ngood_jets > 1 else 0. trail_jet_eta = good_jets[1].eta if ngood_jets > 1 else -99. # boosting 4 vectors boost_vet = good_jets_p4.BoostVector() lead_lep_p4_bst.Boost(boost_vet) trail_lep_p4_bst.Boost(boost_vet) Z_p4_bst.Boost(boost_vet) met_p4_bst.Boost(boost_vet) emulatedMET_p4_bst.Boost(boost_vet) # variables in bossted frame delta_eta_ll_bst = abs(lead_lep_p4_bst.Eta() - trail_lep_p4_bst.Eta()) delta_phi_ll_bst = tk.deltaPhi(lead_lep_p4_bst.Phi(), trail_lep_p4_bst.Phi()) delta_phi_ZMet_bst = tk.deltaPhi(Z_p4_bst.Phi(), met_p4_bst.Phi()) # more variables x_denom20 = (et_jets20 + met_pt + Z_pt) x_denom30 = (et_jets30 + met_pt + Z_pt) x_Z = Z_pt / x_denom30 if x_denom30 > 0. else -99. x_jet20 = et_jets20 / x_denom20 if x_denom20 > 0. else -99. x_jet30 = et_jets30 / x_denom30 if x_denom30 > 0. else -99. x_MET = met_pt / x_denom30 if x_denom30 > 0. else -99. H_T = sum([jet.pt for jet in good_jets]) HT_F = (lead_jet_pt + trail_jet_pt) / H_T if H_T > 0. else 0. Jet_etas_multiplied = lead_jet_eta * trail_jet_eta # more variables if ngood_jets >= 2: S_T_jets = (lead_jet_p4 + trail_jet_p4).Pt() / (lead_jet_pt + trail_jet_pt) S_T_hard = (lead_jet_p4 + trail_jet_p4 + Z_p4).Pt() / (lead_jet_pt + trail_jet_pt + Z_pt) S_T_all = (lead_jet_p4 + trail_jet_p4 + Z_p4 + met_p4).Pt() / ( lead_jet_pt + trail_jet_pt + Z_pt + met_pt) Jet_pt_Ratio = trail_jet_pt / lead_jet_pt R_pt = lead_lep_pt * trail_lep_pt / (lead_jet_pt * trail_jet_pt) dijet_abs_dEta = abs(lead_jet_eta - trail_jet_eta) dijet_Mjj = (lead_jet_p4 + trail_jet_p4).M() dijet_Zep = Z_eta - 0.5 * (lead_jet_eta + trail_jet_eta) dijet_centrality = np.exp(-4 * (dijet_Zep / dijet_abs_dEta)** 2) if dijet_abs_dEta > 0 else -99. # study jets between leading and trailing jets eta_range = sorted([lead_jet_eta, trail_jet_eta]) pT_mid_Jets = [ jet.pt for jet in good_jets[2:] if eta_range[0] < jet.eta < eta_range[1] ] CJV_Pt = pT_mid_Jets[0] if len(pT_mid_Jets) else 0. CJV_Pt_Sum = sum(pT_mid_Jets) if len(pT_mid_Jets) else 0. else: S_T_jets = -99. S_T_hard = -99. S_T_all = -99. Jet_pt_Ratio = -99. R_pt = -99. dijet_abs_dEta = -99. dijet_Mjj = -99. dijet_Zep = -99. dijet_centrality = -99. CJV_Pt = 0. CJV_Pt_Sum = 0. # more variables dPT_OZ = (lead_jet_pt + trail_jet_pt) / Z_pt if Z_pt > 0. else -99. etaThirdJet = good_jets[2].eta if ngood_jets >= 3 else -99. deltaPhiClosestJetMet = 99. deltaPhiFarthestJetMet = -99. for jet in good_jets: if deltaPhiClosestJetMet > abs(tk.deltaPhi(jet.phi, met_phi)): deltaPhiClosestJetMet = abs(tk.deltaPhi(jet.phi, met_phi)) if deltaPhiFarthestJetMet < abs(tk.deltaPhi(jet.phi, met_phi)): deltaPhiFarthestJetMet = abs(tk.deltaPhi(jet.phi, met_phi)) self.out.fillBranch("lead_jet_eta{}".format(self.syst_suffix), lead_jet_eta) self.out.fillBranch("lead_jet_phi{}".format(self.syst_suffix), lead_jet_phi) self.out.fillBranch("trail_jet_pt{}".format(self.syst_suffix), trail_jet_pt) self.out.fillBranch("trail_jet_eta{}".format(self.syst_suffix), trail_jet_eta) self.out.fillBranch("trail_jet_phi{}".format(self.syst_suffix), trail_jet_phi) self.out.fillBranch("dijet_abs_dEta{}".format(self.syst_suffix), dijet_abs_dEta) self.out.fillBranch("dijet_Mjj{}".format(self.syst_suffix), dijet_Mjj) self.out.fillBranch("dijet_Zep{}".format(self.syst_suffix), dijet_Zep) self.out.fillBranch("dijet_centrality{}".format(self.syst_suffix), dijet_centrality) self.out.fillBranch("S_T_hard{}".format(self.syst_suffix), S_T_hard) self.out.fillBranch("S_T_jets{}".format(self.syst_suffix), S_T_jets) self.out.fillBranch("S_T_all{}".format(self.syst_suffix), S_T_all) self.out.fillBranch("x_Z{}".format(self.syst_suffix), x_Z) self.out.fillBranch("x_jet20{}".format(self.syst_suffix), x_jet20) self.out.fillBranch("x_jet30{}".format(self.syst_suffix), x_jet30) self.out.fillBranch("x_MET{}".format(self.syst_suffix), x_MET) self.out.fillBranch("H_T{}".format(self.syst_suffix), H_T) self.out.fillBranch("HT_F{}".format(self.syst_suffix), HT_F) self.out.fillBranch("Jet_pt_Ratio{}".format(self.syst_suffix), Jet_pt_Ratio) self.out.fillBranch("R_pt{}".format(self.syst_suffix), R_pt) self.out.fillBranch("Jet_etas_multiplied{}".format(self.syst_suffix), Jet_etas_multiplied) self.out.fillBranch("dPT_OZ{}".format(self.syst_suffix), dPT_OZ) self.out.fillBranch("CJV_Pt{}".format(self.syst_suffix), CJV_Pt) self.out.fillBranch("CJV_Pt_Sum{}".format(self.syst_suffix), CJV_Pt_Sum) self.out.fillBranch("deltaPhiClosestJetMet{}".format(self.syst_suffix), deltaPhiClosestJetMet) self.out.fillBranch( "deltaPhiFarthestJetMet{}".format(self.syst_suffix), deltaPhiFarthestJetMet) self.out.fillBranch("etaThirdJet{}".format(self.syst_suffix), etaThirdJet) self.out.fillBranch("Z_pt_bst{}".format(self.syst_suffix), Z_p4_bst.Pt()) self.out.fillBranch("Z_phi_bst{}".format(self.syst_suffix), Z_p4_bst.Phi()) self.out.fillBranch("met_pt_bst{}".format(self.syst_suffix), met_p4_bst.Pt()) self.out.fillBranch("met_phi_bst{}".format(self.syst_suffix), met_p4_bst.Phi()) self.out.fillBranch("emulatedMET_pt_bst{}".format(self.syst_suffix), emulatedMET_p4_bst.Pt()) self.out.fillBranch("emulatedMET_phi_bst{}".format(self.syst_suffix), emulatedMET_p4_bst.Phi()) self.out.fillBranch("delta_phi_ll_bst{}".format(self.syst_suffix), delta_phi_ll_bst) self.out.fillBranch("delta_eta_ll_bst{}".format(self.syst_suffix), delta_eta_ll_bst) self.out.fillBranch("delta_phi_ZMet_bst{}".format(self.syst_suffix), delta_phi_ZMet_bst) return True
def fillFatJetInfo(self, event): self.out.fillBranch("n_fatjet", len(event.fatjets)) for idx in ([1, 2] if self._channel == 'qcd' else [1]): prefix = 'fj_%d_' % idx fj = event.fatjets[idx - 1] if self.isMC: h, dr_h = closest(fj, event.hadGenHs) z, dr_z = closest(fj, event.hadGenZs) self.out.fillBranch(prefix + "dr_H", dr_h) self.out.fillBranch(prefix + "H_dau_pdgid", abs(h.daughters[0].pdgId) if h else 0) self.out.fillBranch(prefix + "dr_Z", dr_z) self.out.fillBranch(prefix + "Z_dau_pdgid", abs(z.daughters[0].pdgId) if z else 0) try: self.out.fillBranch(prefix + "DeepAK8MD_ZHbbvsQCD", fj.deepTagMD_ZHbbvsQCD) self.out.fillBranch(prefix + "DeepAK8MD_ZHccvsQCD", fj.deepTagMD_ZHccvsQCD) self.out.fillBranch(prefix + "DeepAK8MD_bbVsLight", fj.deepTagMD_bbvsLight) self.out.fillBranch( prefix + "DeepAK8MD_bbVsTop", (1 / (1 + (fj.deepTagMD_TvsQCD / fj.deepTagMD_HbbvsQCD) * (1 - fj.deepTagMD_HbbvsQCD) / (1 - fj.deepTagMD_TvsQCD)))) except RuntimeError: self.out.fillBranch(prefix + "DeepAK8MD_ZHbbvsQCD", -1) self.out.fillBranch(prefix + "DeepAK8MD_ZHccvsQCD", -1) self.out.fillBranch(prefix + "DeepAK8MD_bbVsLight", -1) self.out.fillBranch(prefix + "DeepAK8MD_bbVsTop", -1) try: self.out.fillBranch(prefix + "ParticleNetMD_Xbb", fj.ParticleNetMD_probXbb) self.out.fillBranch(prefix + "ParticleNetMD_Xcc", fj.ParticleNetMD_probXcc) self.out.fillBranch(prefix + "ParticleNetMD_Xqq", fj.ParticleNetMD_probXqq) if self.isParticleNetV01: self.out.fillBranch(prefix + "ParticleNetMD_QCD", fj.ParticleNetMD_probQCD) self.out.fillBranch( prefix + "ParticleNetMD_XbbVsQCD", convert_prob(fj, ['Xbb'], ['QCD'], prefix='ParticleNetMD_prob')) self.out.fillBranch( prefix + "ParticleNetMD_XccVsQCD", convert_prob(fj, ['Xcc'], ['QCD'], prefix='ParticleNetMD_prob')) else: self.out.fillBranch( prefix + "ParticleNetMD_QCD", convert_prob(fj, None, prefix='ParticleNetMD_prob')) self.out.fillBranch( prefix + "ParticleNetMD_XbbVsQCD", convert_prob(fj, ['Xbb'], prefix='ParticleNetMD_prob')) self.out.fillBranch( prefix + "ParticleNetMD_XccVsQCD", convert_prob(fj, ['Xcc'], prefix='ParticleNetMD_prob')) except RuntimeError: self.out.fillBranch(prefix + "ParticleNetMD_Xbb", -1) self.out.fillBranch(prefix + "ParticleNetMD_Xcc", -1) self.out.fillBranch(prefix + "ParticleNetMD_Xqq", -1) self.out.fillBranch(prefix + "ParticleNetMD_QCD", -1) self.out.fillBranch(prefix + "ParticleNetMD_HbbVsQCD", -1) self.out.fillBranch(prefix + "ParticleNetMD_HccVsQCD", -1) self.out.fillBranch( prefix + "is_lep_overlap", closest(fj, event.looseLeptons)[1] < self._jetConeSize) self.out.fillBranch(prefix + "pt", fj.pt) self.out.fillBranch(prefix + "eta", fj.eta) self.out.fillBranch(prefix + "phi", fj.phi) self.out.fillBranch(prefix + "energy", fj.p4().E()) self.out.fillBranch(prefix + "rawmass", fj.mass) self.out.fillBranch(prefix + "sdmass", fj.msoftdrop) self.out.fillBranch(prefix + "tau21", fj.tau2 / fj.tau1 if fj.tau1 > 0 else 99) self.out.fillBranch(prefix + "btagcsvv2", fj.btagCSVV2) try: self.out.fillBranch(prefix + "btagjp", fj.btagJP) except RuntimeError: self.out.fillBranch(prefix + "btagjp", -1) self._matchSVToFatjet(event, fj) nsv_ptgt25_ = 0 nsv_ptgt50_ = 0 ntracks_ = 0 ntracks_sv12_ = 0 for isv, sv in enumerate(fj.sv_list): ntracks_ += sv.ntracks if isv < 2: ntracks_sv12_ += sv.ntracks if sv.pt > 25.: nsv_ptgt25_ += 1 if sv.pt > 50.: nsv_ptgt50_ += 1 self.out.fillBranch(prefix + "nsv", len(fj.sv_list)) self.out.fillBranch(prefix + "nsv_ptgt25", nsv_ptgt25_) self.out.fillBranch(prefix + "nsv_ptgt50", nsv_ptgt50_) self.out.fillBranch(prefix + "ntracks", ntracks_) self.out.fillBranch(prefix + "ntracks_sv12", ntracks_sv12_) assert (len(fj.subjets) == 2) self.out.fillBranch(prefix + "deltaR_sj12", deltaR(*fj.subjets[:2])) for idx_sj, sj in enumerate(fj.subjets): prefix_sj = prefix + 'sj%d_' % (idx_sj + 1) self.out.fillBranch(prefix_sj + "pt", sj.pt) self.out.fillBranch(prefix_sj + "eta", sj.eta) self.out.fillBranch(prefix_sj + "phi", sj.phi) self.out.fillBranch(prefix_sj + "energy", sj.p4().E()) self.out.fillBranch(prefix_sj + "rawmass", sj.mass) self.out.fillBranch(prefix_sj + "btagcsvv2", sj.btagCSVV2) try: self.out.fillBranch(prefix_sj + "btagdeepcsv", sj.btagDeepB) except RuntimeError: self.out.fillBranch(prefix_sj + "btagdeepcsv", -1) try: self.out.fillBranch(prefix_sj + "btagjp", sj.btagJP) except RuntimeError: self.out.fillBranch(prefix_sj + "btagjp", -1) self.out.fillBranch(prefix_sj + "ntracks", sum([sv.ntracks for sv in sj.sv_list])) self.out.fillBranch(prefix_sj + "nsv", len(sj.sv_list)) sv = sj.sv_list[0] if len(sj.sv_list) else _NullObject() fill_sv = self._get_filler( sv) # wrapper, fill default value if sv=None fill_sv(prefix_sj + "sv1_pt", sv.pt) fill_sv(prefix_sj + "sv1_mass", sv.mass) fill_sv(prefix_sj + "sv1_masscor", corrected_svmass(sv) if sv else 0) fill_sv(prefix_sj + "sv1_ntracks", sv.ntracks) fill_sv(prefix_sj + "sv1_dxy", sv.dxy) fill_sv(prefix_sj + "sv1_dxysig", sv.dxySig) fill_sv(prefix_sj + "sv1_dlen", sv.dlen) fill_sv(prefix_sj + "sv1_dlensig", sv.dlenSig) fill_sv(prefix_sj + "sv1_chi2ndof", sv.chi2) fill_sv(prefix_sj + "sv1_pangle", sv.pAngle) sj1, sj2 = fj.subjets try: sv1, sv2 = sj1.sv_list[0], sj2.sv_list[0] sv = sv1 if sv1.dxySig > sv2.dxySig else sv2 self.out.fillBranch(prefix + "sj12_masscor_dxysig", corrected_svmass(sv) if sv else 0) except IndexError: # if len(sv_list) == 0 self.out.fillBranch(prefix + "sj12_masscor_dxysig", 0) # sfBDT sfbdt_inputs = { k: self.out._branches[k.replace('fj_2_', prefix)].buff[0] for k in self._sfbdt_vars } self.out.fillBranch( prefix + "sfBDT", self.xgb.eval(sfbdt_inputs, model_idx=(event.event % 10))) # matching variables if self.isMC: self.out.fillBranch(prefix + "nbhadrons", fj.nBHadrons) self.out.fillBranch(prefix + "nchadrons", fj.nCHadrons) self.out.fillBranch(prefix + "sj1_nbhadrons", sj1.nBHadrons) self.out.fillBranch(prefix + "sj1_nchadrons", sj1.nCHadrons) self.out.fillBranch(prefix + "sj2_nbhadrons", sj2.nBHadrons) self.out.fillBranch(prefix + "sj2_nchadrons", sj2.nCHadrons) try: self.out.fillBranch(prefix + "partonflavour", fj.partonFlavour) self.out.fillBranch(prefix + "sj1_partonflavour", sj1.partonFlavour) self.out.fillBranch(prefix + "sj2_partonflavour", sj2.partonFlavour) except: self.out.fillBranch(prefix + "partonflavour", -1) self.out.fillBranch(prefix + "sj1_partonflavour", -1) self.out.fillBranch(prefix + "sj2_partonflavour", -1)