diff --git a/analysis/topeft_run2/analysis_processor.py b/analysis/topeft_run2/analysis_processor.py index 72ad2b057..9d2f94327 100644 --- a/analysis/topeft_run2/analysis_processor.py +++ b/analysis/topeft_run2/analysis_processor.py @@ -229,10 +229,18 @@ def process(self, events): if is_run3: - leptonSelection = te_os.run3leptonselection() + elePresId = ele.mvaNoIso_WP90 + ele_pres_id_tag = "wp90noiso" + eleFOId = ele.mvaNoIso_WP80 + eleMVATTH = ele.mvaTTH + muMVATTH = mu.mvaTTH jetsRho = events.Rho["fixedGridRhoFastjetAll"] elif is_run2: - leptonSelection = te_os.run2leptonselection() + elePresId = ele.mvaFall17V2noIso_WPL + ele_pres_id_tag = "wpLnoiso" + eleFOId = ele.mvaFall17V2noIso_WP90 + eleMVATTH = ele.mvaTTHUL + muMVATTH = mu.mvaTTHUL jetsRho = events.fixedGridRhoFastjetAll # An array of lenght events that is just 1 for each event @@ -240,8 +248,8 @@ def process(self, events): events.nom = ak.ones_like(events.MET.pt) ele["idEmu"] = te_os.ttH_idEmu_cuts_E3(ele.hoe, ele.eta, ele.deltaEtaSC, ele.eInvMinusPInv, ele.sieie) - ele["conept"] = leptonSelection.coneptElec(ele) - mu["conept"] = leptonSelection.coneptMuon(mu) + ele["conept"] = te_os.coneptElec(ele.pt, eleMVATTH, ele.jetRelIso) + mu["conept"] = te_os.coneptMuon(mu.pt, muMVATTH, mu.jetRelIso, mu.mediumId) ele["btagDeepFlavB"] = ak.fill_none(ele.matched_jet.btagDeepFlavB, -99) mu["btagDeepFlavB"] = ak.fill_none(mu.matched_jet.btagDeepFlavB, -99) if not isData: @@ -278,18 +286,18 @@ def process(self, events): ################### Electron selection #################### - ele["isPres"] = leptonSelection.isPresElec(ele) - ele["isLooseE"] = leptonSelection.isLooseElec(ele) - ele["isFO"] = leptonSelection.isFOElec(ele, year) - ele["isTightLep"] = leptonSelection.tightSelElec(ele) + ele["isPres"] = te_os.isPresElec(ele.pt, ele.eta, ele.dxy, ele.dz, ele.miniPFRelIso_all, ele.sip3d, elePresId) + ele["isLooseE"] = te_os.isLooseElec(ele.miniPFRelIso_all,ele.sip3d,ele.lostHits) + ele["isFO"] = te_os.isFOElec(ele.pt, ele.conept, ele.btagDeepFlavB, ele.idEmu, ele.convVeto, ele.lostHits, eleMVATTH, ele.jetRelIso, eleFOId, year) + ele["isTightLep"] = te_os.tightSelElec(ele.isFO, eleMVATTH) ################### Muon selection #################### mu["pt"] = ApplyRochesterCorrections(year, mu, isData) # Run3 ready - mu["isPres"] = leptonSelection.isPresMuon(mu) - mu["isLooseM"] = leptonSelection.isLooseMuon(mu) - mu["isFO"] = leptonSelection.isFOMuon(mu, year) - mu["isTightLep"]= leptonSelection.tightSelMuon(mu) + mu["isPres"] = te_os.isPresMuon(mu.dxy, mu.dz, mu.sip3d, mu.eta, mu.pt, mu.miniPFRelIso_all) + mu["isLooseM"] = te_os.isLooseMuon(mu.miniPFRelIso_all,mu.sip3d,mu.looseId) + mu["isFO"] = te_os.isFOMuon(mu.pt, mu.conept, mu.btagDeepFlavB, muMVATTH, mu.jetRelIso, year) + mu["isTightLep"]= te_os.tightSelMuon(mu.isFO, mu.mediumId, muMVATTH) ################### Loose selection #################### @@ -314,7 +322,7 @@ def process(self, events): e_fo = ele[ele.isPres & ele.isLooseE & ele.isFO] # Attach the lepton SFs to the electron and muons collections - AttachElectronSF(e_fo, year=year, looseWP="wpLnoiso" if is_run3 else "none") #Run3 ready + AttachElectronSF(e_fo, year=year, looseWP=ele_pres_id_tag) #Run3 ready AttachMuonSF(m_fo,year=year) #Run3 ready # Attach per lepton fake rates diff --git a/topeft/modules/corrections.py b/topeft/modules/corrections.py index 38fb611f8..475d0444b 100644 --- a/topeft/modules/corrections.py +++ b/topeft/modules/corrections.py @@ -1168,7 +1168,33 @@ def AttachElectronSF(electrons, year, looseWP=None): reco_up = ak.unflatten(reco_up_flat, ak.num(pt)) reco_do = ak.unflatten(reco_do_flat, ak.num(pt)) - if not is_run3: # run 3 dont need loose for the id because we dont have ID working point (to be checked!!) + if is_run3: + loose_sf_flat = None + loose_up_flat = None + loose_do_flat = None + pt_mask = ak.flatten((pt >= 10)) + egm_args = [eta_flat, pt_bin_flat] + if "2023" in year: + egm_args.append(phi_flat) + loose_sf_flat = ak.where( + ~pt_mask, + 1, + ceval[egm_tag].evaluate(egm_year, "sf", looseWP, *egm_args) + ) + loose_up_flat = ak.where( + ~pt_mask, + 1, + ceval[egm_tag].evaluate(egm_year, "sfup", looseWP, *egm_args) + ) + loose_do_flat = ak.where( + ~pt_mask, + 1, + ceval[egm_tag].evaluate(egm_year, "sfdown", looseWP, *egm_args) + ) + loose_sf = ak.unflatten(loose_sf_flat, ak.num(pt)) + loose_up = ak.unflatten(loose_up_flat, ak.num(pt)) + loose_do = ak.unflatten(loose_do_flat, ak.num(pt)) + else: loose_sf = SFevaluator['ElecLooseSF_{year}'.format(year=year)](np.abs(eta),pt) loose_err = SFevaluator['ElecLooseSF_{year}_er'.format(year=year)](np.abs(eta),pt) loose_up = loose_sf + loose_err diff --git a/topeft/modules/object_selection.py b/topeft/modules/object_selection.py index 13bebc85d..a04a6336d 100644 --- a/topeft/modules/object_selection.py +++ b/topeft/modules/object_selection.py @@ -72,147 +72,100 @@ def smoothBFlav(jetpt,ptmin,ptmax,year,scale_loose=1.0): x = np.minimum(np.maximum(0, jetpt - ptmin)/(ptmax-ptmin), 1.0) return x*wploose*scale_loose + (1-x)*wpmedium -def smoothSip3D(jetpt, sipmin, sipmax, ptmin, ptmax): - x = np.minimum(np.maximum(0, jetpt - ptmin)/(ptmax-ptmin), 1.0) - return x*sipmax+(1-x)*sipmin +def coneptElec(pt, mvaTTHUL, jetRelIso): + conePt = (0.90 * pt * (1 + jetRelIso)) + return ak.where((mvaTTHUL>get_tc_param("mva_TTH_e_cut")),pt,conePt) + +def coneptMuon(pt, mvaTTHUL, jetRelIso, mediumId): + conePt = (0.90 * pt * (1 + jetRelIso)) + return ak.where(((mvaTTHUL>get_tc_param("mva_TTH_m_cut"))&(mediumId>0)),pt,conePt) + +def isPresElec(pt, eta, dxy, dz, miniIso, sip3D, eleId): + pt_mask = (pt > get_te_param("pres_e_pt_cut")) + eta_mask = (abs(eta) < get_te_param("eta_e_cut")) + dxy_mask = (abs(dxy) < get_te_param("dxy_cut")) + dz_mask = (abs(dz) < get_te_param("dz_cut")) + iso_mask = (miniIso < get_te_param("iso_cut")) + sip3d_mask = (sip3D < get_te_param("sip3d_cut")) + return (pt_mask & eta_mask & dxy_mask & dz_mask & iso_mask & sip3d_mask & eleId) + +def isPresMuon(dxy, dz, sip3D, eta, pt, miniRelIso): + pt_mask = (pt > get_te_param("pres_m_pt_cut")) + eta_mask = (abs(eta) < get_te_param("eta_m_cut")) + dxy_mask = (abs(dxy) < get_te_param("dxy_cut")) + dz_mask = (abs(dz) < get_te_param("dz_cut")) + iso_mask = (miniRelIso < get_te_param("iso_cut")) + sip3d_mask = (sip3D < get_te_param("sip3d_cut")) + return (pt_mask & eta_mask & dxy_mask & dz_mask & iso_mask & sip3d_mask) + +def isLooseElec(miniPFRelIso_all,sip3d,lostHits): + return (miniPFRelIso_allget_te_param("mva_TTH_e_cut")),ele.pt,conePt) - - def coneptMuon(self, muo): - conePt = (0.90 * muo.pt * (1 + muo.jetRelIso)) - return ak.where(((muo.mvaTTHUL>get_te_param("mva_TTH_m_cut"))&(muo.mediumId>0)),muo.pt,conePt) - - def isPresElec(self, ele): - pt_mask = (ele.pt > get_te_param("pres_e_pt_cut")) - eta_mask = (abs(ele.eta) < get_te_param("eta_e_cut")) - dxy_mask = (abs(ele.dxy) < get_te_param("dxy_cut")) - dz_mask = (abs(ele.dz) < get_te_param("dz_cut")) - iso_mask = (ele.miniPFRelIso_all < get_te_param("iso_cut")) - sip3d_mask = (ele.sip3d < get_te_param("sip3d_cut")) - return (pt_mask & eta_mask & dxy_mask & dz_mask & iso_mask & sip3d_mask & ele.mvaFall17V2noIso_WPL) - - def isPresMuon(self, muon): - pt_mask = (muon.pt > get_te_param("pres_m_pt_cut")) - eta_mask = (abs(muon.eta) < get_te_param("eta_m_cut")) - dxy_mask = (abs(muon.dxy) < get_te_param("dxy_cut")) - dz_mask = (abs(muon.dz) < get_te_param("dz_cut")) - iso_mask = (muon.miniPFRelIso_all < get_te_param("iso_cut")) - sip3d_mask = (muon.sip3d < get_te_param("sip3d_cut")) - return (pt_mask & eta_mask & dxy_mask & dz_mask & iso_mask & sip3d_mask) - - def isLooseElec(self, ele): - return (ele.miniPFRelIso_allget_te_param("fo_pt_cut")) - qualityReq = (ele.idEmu & ele.convVeto & (ele.lostHits==0)) - mvaReq = ((ele.mvaTTHUL>get_te_param("mva_TTH_e_cut")) | ((ele.mvaFall17V2noIso_WP90) & (ele.jetBTagDeepFlavget_te_param("fo_pt_cut")) - mvaReq = ((muo.mvaTTHUL>get_te_param("mva_TTH_m_cut")) | ((muo.jetBTagDeepFlav get_te_param("mva_TTH_e_cut")) - - def tightSelMuon(self, muo): - return (muo.isFO) & (muo.mediumId>0) & (muo.mvaTTHUL > get_te_param("mva_TTH_m_cut")) - -class run3leptonselection: - - def __init__(self): - pass - - def coneptElec(self, ele): - conePt = (0.90 * ele.pt * (1 + ele.jetRelIso)) - return ak.where((ele.mvaTTH_Run3>get_te_param("mva_TTH_e_cut_run3")),ele.pt,conePt) - - def coneptMuon(self, muo): - conePt = (0.90 * muo.pt * (1 + muo.jetRelIso)) - return ak.where(((muo.mvaTTH_Run3>get_te_param("mva_TTH_m_cut_run3"))&(muo.mediumId>0)),muo.pt,conePt) - - def isPresElec(self, ele): - pt_mask = (ele.pt > get_te_param("pres_e_pt_cut")) - eta_mask = (abs(ele.eta) < get_te_param("eta_e_cut")) - dxy_mask = (abs(ele.dxy) < get_te_param("dxy_cut")) - dz_mask = (abs(ele.dz) < get_te_param("dz_cut")) - iso_mask = (ele.miniPFRelIso_all < get_te_param("iso_cut")) - sip3d_mask = (ele.sip3d < get_te_param("sip3d_cut")) - ecal_crack_mask = (((abs(ele.etaSC) < 1.4442) | (abs(ele.etaSC) > 1.566))) - return (pt_mask & eta_mask & dxy_mask & dz_mask & iso_mask & sip3d_mask & ecal_crack_mask) - - def isPresMuon(self, muon): - pt_mask = (muon.pt > get_te_param("pres_m_pt_cut")) - eta_mask = (abs(muon.eta) < get_te_param("eta_m_cut")) - dxy_mask = (abs(muon.dxy) < get_te_param("dxy_cut")) - dz_mask = (abs(muon.dz) < get_te_param("dz_cut")) - iso_mask = (muon.miniPFRelIso_all < get_te_param("iso_cut")) - sip3d_mask = (muon.sip3d < get_te_param("sip3d_cut")) - return (pt_mask & eta_mask & dxy_mask & dz_mask & iso_mask & sip3d_mask) - - def isLooseElec(self, ele): - return (ele.miniPFRelIso_allget_te_param("fo_pt_cut")) - qualityReq = (ele.idEmu & ele.convVeto & (ele.lostHits==0)) - mvaReq = ((ele.mvaTTH_Run3>get_te_param("mva_TTH_e_cut_run3")) | ((ele.mvaIso > get_te_param("fo_e_mvaiso_cut_run3")) & (ele.jetRelIso < get_te_param("fo_e_jetRelIso_cut")))) - - def isFOMuon(self, muo, year): - bTagCut=get_medium_btag_foryear(year) - btagReq = (muo.jetBTagDeepFlavget_te_param("fo_pt_cut")) - mvaReq = ((muo.mvaTTH_Run3>get_te_param("mva_TTH_m_cut_run3")) | ((muo.jetBTagDeepFlav get_te_param("mva_TTH_e_cut_run3")) - - def tightSelMuon(self, muo): - return (muo.isFO) & (muo.mediumId>0) & (muo.mvaTTH_Run3 > get_te_param("mva_TTH_m_cut_run3")) + btabReq = (jetBTagDeepFlavget_te_param("fo_pt_cut")) + qualityReq = (ttH_idEmu_cuts_E3 & convVeto & (lostHits==0)) + mvaReq = ((mvaTTHUL>get_tc_param("mva_TTH_e_cut")) | ((mvaFall17V2noIso_WP90) & (jetBTagDeepFlavget_te_param("fo_pt_cut")) + mvaReq = ((mvaTTHUL>get_tc_param("mva_TTH_m_cut")) | ((jetBTagDeepFlav get_tc_param("mva_TTH_e_cut")) + +def tightSelMuon(clean_and_FO_selection_TTH, mediumId, mvaTTHUL): + return (clean_and_FO_selection_TTH) & (mediumId>0) & (mvaTTHUL > get_tc_param("mva_TTH_m_cut")) def isClean(obj_A, obj_B, drmin=0.4): objB_near, objB_DR = obj_A.nearest(obj_B, return_metric=True) diff --git a/topeft/params/params.json b/topeft/params/params.json index 18819a357..4c27a230a 100644 --- a/topeft/params/params.json +++ b/topeft/params/params.json @@ -8,18 +8,11 @@ "pres_e_pt_cut" : 7.0, "pres_m_pt_cut" : 5.0, - "mva_TTH_e_cut" : 0.90, - "mva_TTH_m_cut" : 0.85, - "mva_TTH_e_cut_run3" : 0.90, - "mva_TTH_m_cut_run3" : 0.64, - "iso_cut" : 0.4, "fo_m_jetRelIso_cut" : 0.5, "fo_e_jetRelIso_cut" : 1.0, - "fo_e_mvaiso_cut_run3" : 0.6, - "jet_id_cut" : 0, "dxy_cut" : 0.05,