class ElectronSFs: def __init__(self, year=2017): """Load histograms from files.""" assert year in [ 2016, 2017, 2018 ], "ElectronSFs: You must choose a year from: 2016, 2017 or 2018." self.year = year if year == 2016: self.sftool_trig_barrel = ScaleFactor( path + "Run2016/Ele115orEleIso27orPho175_SF_2016.root", 'SF_TH2F_Barrel', 'ele_trig_barrel') self.sftool_trig_endcap = ScaleFactor( path + "Run2016/Ele115orEleIso27orPho175_SF_2016.root", 'SF_TH2F_EndCap', 'ele_trig_endcap') self.sftool_reco = ScaleFactor( path + "Run2016/EGM2D_BtoH_GT20GeV_RecoSF_Legacy2016.root", "EGamma_SF2D", 'ele_reco') self.sftool_idiso = ScaleFactor( path + "Run2016/2016LegacyReReco_ElectronLoose_Fall17V2.root", "EGamma_SF2D", 'ele_idiso') elif year == 2017: self.sftool_trig_barrel = ScaleFactor( path + "Run2017/Ele115orEleIso35orPho200_SF_2017.root", 'SF_TH2F_Barrel', 'ele_trig_barrel') self.sftool_trig_endcap = ScaleFactor( path + "Run2017/Ele115orEleIso35orPho200_SF_2017.root", 'SF_TH2F_EndCap', 'ele_trig_endcap') self.sftool_reco = ScaleFactor( path + "Run2017/egammaEffi.txt_EGM2D_runBCDEF_passingRECO.root", "EGamma_SF2D", 'ele_reco') self.sftool_idiso = ScaleFactor( path + "Run2017/2017_ElectronLoose.root", "EGamma_SF2D", 'ele_idiso') elif year == 2018: self.sftool_trig_barrel = ScaleFactor( path + "Run2018/Ele115orEleIso32orPho200_SF_2018.root", 'SF_TH2F_Barrel', 'ele_trig_barrel') self.sftool_trig_endcap = ScaleFactor( path + "Run2018/Ele115orEleIso32orPho200_SF_2018.root", 'SF_TH2F_EndCap', 'ele_trig_endcap') self.sftool_reco = ScaleFactor( path + "Run2018/egammaEffi.txt_EGM2D_updatedAll.root", "EGamma_SF2D", 'ele_reco') self.sftool_idiso = ScaleFactor( path + "Run2018/2018_ElectronLoose.root", "EGamma_SF2D", 'ele_idiso') def getTriggerSF(self, pt, eta): """Get SF for single electron trigger.""" if eta > 1.4 and eta < 1.5: eta = 1.4 elif eta > 1.5 and eta < 1.6: eta = 1.6 elif eta < -1.4 and eta > -1.5: eta = -1.4 elif eta < -1.5 and eta > -1.6: eta = -1.6 if abs(eta) > 1.5: sf_trigger = self.sftool_trig_endcap.getSF(pt, eta) else: sf_trigger = self.sftool_trig_barrel.getSF(pt, eta) return sf_trigger def getTriggerSFerror(self, pt, eta): """Get SF error for single electron trigger.""" if eta > 1.4 and eta < 1.5: eta = 1.4 elif eta > 1.5 and eta < 1.6: eta = 1.6 elif eta < -1.4 and eta > -1.5: eta = -1.4 elif eta < -1.5 and eta > -1.6: eta = -1.6 if abs(eta) > 1.5: sf_trigger_error = self.sftool_trig_endcap.getSFerror(pt, eta) else: sf_trigger_error = self.sftool_trig_barrel.getSFerror(pt, eta) return sf_trigger_error def getIdIsoSF(self, pt, eta): """Get SF for electron identification + isolation.""" sf_reco = self.sftool_reco.getSF(pt, eta) if self.sftool_reco else 1. sf_idiso = self.sftool_idiso.getSF(pt, eta) return sf_reco * sf_idiso def getIdIsoSFerror(self, pt, eta): """Get SF error for electron identification + isolation.""" sf_reco = self.sftool_reco.getSF(pt, eta) if self.sftool_reco else 1. sf_idiso = self.sftool_idiso.getSF(pt, eta) sf_reco_error = self.sftool_reco.getSFerror(pt, eta) sf_idiso_error = self.sftool_idiso.getSFerror(pt, eta) sf_reco_idiso_error = np.sqrt((sf_reco_error * sf_idiso)**2 + (sf_idiso_error * sf_reco)**2) return sf_reco_idiso_error
class MuonSFs: def __init__(self, year=2017): """Load histograms from files.""" assert year in [ 2016, 2017, 2018 ], "MuonSFs: You must choose a year from: 2016, 2017 or 2018." self.year = year self.lumi_2016_bcdef = 20.2 self.lumi_2016_gh = 16.6 if year == 2016: self.sftool_trig = ScaleFactor( path + "Run2016/SingleMuonTrigger_2016.root", "Mu50_OR_TkMu50_PtEtaBins/abseta_pt_ratio", "mu_trig") self.sftool_id_bcdef = ScaleFactor( path + "Run2016/RunBCDEF_SF_ID.root", "NUM_HighPtID_DEN_genTracks_eta_pair_newTuneP_probe_pt", "mu_id") self.sftool_id_gh = ScaleFactor( path + "Run2016/RunGH_SF_ID.root", "NUM_HighPtID_DEN_genTracks_eta_pair_newTuneP_probe_pt", "mu_id") self.sftool_iso_id_bcdef = ScaleFactor( path + "Run2016/RunBCDEF_SF_ISO.root", "NUM_LooseRelTkIso_DEN_HighPtIDandIPCut_eta_pair_newTuneP_probe_pt", "mu_iso_id") self.sftool_iso_id_gh = ScaleFactor( path + "Run2016/RunGH_SF_ISO.root", "NUM_LooseRelTkIso_DEN_HighPtIDandIPCut_eta_pair_newTuneP_probe_pt", "mu_iso_id") elif year == 2017: self.sftool_trig = ScaleFactor( path + "Run2017/EfficienciesAndSF_RunBtoF_Nov17Nov2017.root", "Mu50_PtEtaBins/abseta_pt_ratio", 'mu_trig') self.sftool_id = ScaleFactor( path + "Run2017/RunBCDEF_SF_ID.root", "NUM_HighPtID_DEN_genTracks_pair_newTuneP_probe_pt_abseta", 'mu_id', ptvseta=False) self.sftool_trkid = ScaleFactor( path + "Run2017/RunBCDEF_SF_ID.root", "NUM_TrkHighPtID_DEN_genTracks_pair_newTuneP_probe_pt_abseta", 'mu_trkid', ptvseta=False) self.sftool_iso_id = ScaleFactor( path + "Run2017/RunBCDEF_SF_ISO.root", "NUM_LooseRelTkIso_DEN_HighPtIDandIPCut_pair_newTuneP_probe_pt_abseta", 'mu_iso_id', ptvseta=False) self.sftool_iso_trkid = ScaleFactor( path + "Run2017/RunBCDEF_SF_ISO.root", "NUM_LooseRelTkIso_DEN_TrkHighPtID_pair_newTuneP_probe_pt_abseta", 'mu_iso_trkid', ptvseta=False) elif year == 2018: self.sftool_trig = ScaleFactor( path + "Run2018/EfficienciesAndSF_2018Data_AfterMuonHLTUpdate.root", "Mu50_OR_OldMu100_OR_TkMu100_PtEtaBins/abseta_pt_ratio", 'mu_trig') self.sftool_id = ScaleFactor( path + "Run2018/RunABCD_SF_ID.root", "NUM_HighPtID_DEN_TrackerMuons_pair_newTuneP_probe_pt_abseta", 'mu_id', ptvseta=False) self.sftool_trkid = ScaleFactor( path + "Run2018/RunABCD_SF_ID.root", "NUM_TrkHighPtID_DEN_TrackerMuons_pair_newTuneP_probe_pt_abseta", 'mu_trkid', ptvseta=False) self.sftool_iso_id = ScaleFactor( path + "Run2018/RunABCD_SF_ISO.root", "NUM_LooseRelTkIso_DEN_HighPtIDandIPCut_pair_newTuneP_probe_pt_abseta", 'mu_iso_id', ptvseta=False) self.sftool_iso_trkid = ScaleFactor( path + "Run2018/RunABCD_SF_ISO.root", "NUM_LooseRelTkIso_DEN_TrkHighPtID_pair_newTuneP_probe_pt_abseta", 'mu_iso_trkid', ptvseta=False) def getTriggerSF(self, pt, eta): """Get SF for single muon trigger.""" return self.sftool_trig.getSF(pt, abs(eta)) def getTriggerSFerror(self, pt, eta): """Get SF for single muon trigger.""" return self.sftool_trig.getSFerror(pt, abs(eta)) def getIdSF(self, pt, eta, highptid): """Get SF for muon identification.""" if self.year == 2016: return (self.sftool_id_bcdef.getSF(pt, abs(eta)) * self.lumi_2016_bcdef + self.sftool_id_gh.getSF(pt, abs(eta)) * self.lumi_2016_gh ) / (self.lumi_2016_bcdef + self.lumi_2016_gh) else: if highptid == 1: return self.sftool_trkid.getSF(pt, abs(eta)) elif highptid == 2: return self.sftool_id.getSF(pt, abs(eta)) else: return 1. def getIdSFerror(self, pt, eta, highptid): """Get SF for muon identification.""" if self.year == 2016: idsferror = (self.sftool_id_bcdef.getSFerror(pt, abs(eta)) * self.lumi_2016_bcdef + self.sftool_id_gh.getSFerror(pt, abs(eta)) * self.lumi_2016_gh) / (self.lumi_2016_bcdef + self.lumi_2016_gh) if highptid == 1: return idsferror * 2 else: return idsferror else: if highptid == 1: return self.sftool_trkid.getSFerror(pt, abs(eta)) elif highptid == 2: return self.sftool_id.getSFerror(pt, abs(eta)) else: return 0. def getIsoSF(self, pt, eta, highptid): """Get SF for muon isolation.""" if self.year == 2016: return (self.sftool_iso_id_bcdef.getSF(pt, abs(eta)) * self.lumi_2016_bcdef + self.sftool_iso_id_gh.getSF(pt, abs(eta)) * self.lumi_2016_gh) / (self.lumi_2016_bcdef + self.lumi_2016_gh) else: if highptid == 1: return self.sftool_iso_trkid.getSF(pt, abs(eta)) elif highptid == 2: return self.sftool_iso_id.getSF(pt, abs(eta)) else: return 1. def getIsoSFerror(self, pt, eta, highptid): """Get SF for muon isolation.""" if self.year == 2016: isosferror = (self.sftool_iso_id_bcdef.getSFerror(pt, abs(eta)) * self.lumi_2016_bcdef + self.sftool_iso_id_gh.getSFerror(pt, abs(eta)) * self.lumi_2016_gh) / (self.lumi_2016_bcdef + self.lumi_2016_gh) if highptid == 1: return isosferror * 2 else: return isosferror else: if highptid == 1: return self.sftool_iso_trkid.getSFerror(pt, abs(eta)) elif highptid == 2: return self.sftool_iso_id.getSFerror(pt, abs(eta)) else: return 0.
class MuonSFs: def __init__(self, year=2017): """Load histograms from files.""" assert year in [ 2016, 2017, 2018 ], "MuonSFs: You must choose a year from: 2016, 2017 or 2018." self.year = year if year == 2016: self.sftool_trig = ScaleFactor( path + "Run2016/SingleMuonTrigger_2016.root", "IsoMu24_OR_IsoTkMu24_PtEtaBins/abseta_pt_ratio", "mu_trig") #Mu50_OR_TkMu50_PtEtaBins self.sftool_id = ScaleFactor( path + "Run2016/RunBCDEF_SF_ID.root", "NUM_MediumID_DEN_genTracks_eta_pt", "mu_id" ) #NUM_HighPtID_DEN_genTracks_eta_pair_newTuneP_probe_pt\ self.sftool_iso = ScaleFactor( path + "Run2016/RunBCDEF_SF_ISO.root", "NUM_LooseRelIso_DEN_MediumID_eta_pt", "mu_iso") self.sftool_trkid = ScaleFactor( path + "Run2016/trackHighPtID_effSF_80X.root", "sf_trackHighPt_80X_pteta", "mu_trkid") elif year == 2017: self.sftool_trig = ScaleFactor( path + "Run2017/EfficienciesAndSF_RunBtoF_Nov17Nov2017.root", "Mu50_PtEtaBins/abseta_pt_ratio", 'mu_trig') self.sftool_id = ScaleFactor( path + "Run2017/RunBCDEF_SF_ID.root", "NUM_HighPtID_DEN_genTracks_pair_newTuneP_probe_pt_abseta", 'mu_id', ptvseta=False) self.sftool_iso = ScaleFactor( path + "Run2017/RunBCDEF_SF_ISO.root", "NUM_LooseRelIso_DEN_MediumID_pt_abseta", 'mu_iso', ptvseta=False) self.sftool_trkid = ScaleFactor( path + "Run2017/RunBCDEF_SF_ID.root", "NUM_TrkHighPtID_DEN_genTracks_pair_newTuneP_probe_pt_abseta", 'mu_trkid', ptvseta=False) elif year == 2018: self.sftool_trig = ScaleFactor( path + "Run2018/EfficienciesAndSF_2018Data_AfterMuonHLTUpdate.root", "Mu50_OR_OldMu100_OR_TkMu100_PtEtaBins/abseta_pt_ratio", 'mu_trig') self.sftool_id = ScaleFactor( path + "Run2018/RunABCD_SF_ID.root", "NUM_HighPtID_DEN_TrackerMuons_pair_newTuneP_probe_pt_abseta", 'mu_id', ptvseta=False) self.sftool_iso = ScaleFactor( path + "Run2018/RunABCD_SF_ISO.root", "NUM_LooseRelIso_DEN_MediumID_pt_abseta", 'mu_id', ptvseta=False) self.sftool_trkid = ScaleFactor( path + "Run2018/RunABCD_SF_ID.root", "NUM_TrkHighPtID_DEN_TrackerMuons_pair_newTuneP_probe_pt_abseta", 'mu_trkid', ptvseta=False) def getTriggerSF(self, pt, eta): """Get SF for single muon trigger.""" return self.sftool_trig.getSF(pt, abs(eta)) def getTriggerSFerror(self, pt, eta): """Get SF for single muon trigger.""" return self.sftool_trig.getSFerror(pt, abs(eta)) def getIdSF(self, pt, eta, highptid): """Get SF for muon identification + isolation.""" if highptid == 1: return self.sftool_trkid.getSF(pt, abs(eta)) elif highptid == 2: return self.sftool_id.getSF(pt, abs(eta)) else: return 1. def getIdSFerror(self, pt, eta, highptid): """Get SF for muon identification + isolation.""" if highptid == 1: return self.sftool_trkid.getSFerror(pt, abs(eta)) elif highptid == 2: return self.sftool_id.getSFerror(pt, abs(eta)) else: return 0. def getIsoSF(self, pt, eta): """Get SF for muon isolation.""" return self.sftool_iso.getSF(pt, abs(eta)) def getIdSFerror(self, pt, eta): """Get SF for muon isolation.""" return self.sftool_iso.getSFerror(pt, abs(eta))
class ElectronSFs: def __init__(self, year=2017): """Load histograms from files.""" assert year in [ 2016, 2017, 2018 ], "ElectronSFs: You must choose a year from: 2016, 2017 or 2018." self.year = year if year == 2016: self.sftool_trig_data = ScaleFactor( path + "Run2016/Ele115_passingTight_2016.root", 'EGamma_EffData2D_ABSOLUTE', 'ele_trig_data') self.sftool_trig_mc = ScaleFactor( path + "Run2016/Ele115_passingTight_2016.root", 'EGamma_EffMC2D_ABSOLUTE', 'ele_trig_mc') self.sftool_trig = ScaleFactorCalc( path + "Run2016/Ele115_passingTight_2016.root", 'EGamma_EffData2D_ABSOLUTE', 'ele_trig_data', path + "Run2016/Ele115_passingTight_2016.root", 'EGamma_EffMC2D_ABSOLUTE', 'ele_trig_mc') self.sftool_reco = ScaleFactor( path + "Run2016/EGM2D_BtoH_GT20GeV_RecoSF_Legacy2016.root", "EGamma_SF2D", 'ele_reco') self.sftool_idiso = ScaleFactor( path + "Run2016/2016LegacyReReco_ElectronLoose_Fall17V2.root", "EGamma_SF2D", 'ele_idiso') elif year == 2017: self.sftool_trig_data = ScaleFactor( path + "Run2017/Ele115orEle35_SF_2017.root", 'ELE_DATA_ABSOLUTE', 'ele_trig_data', ptvseta=False) self.sftool_trig_mc = ScaleFactor( path + "Run2017/Ele115orEle35_SF_2017.root", 'ELE_MC_ABSOLUTE', 'ele_trig_mc', ptvseta=False) self.sftool_trig = ScaleFactorCalc( path + "Run2017/Ele115orEle35_SF_2017.root", 'ELE_DATA_ABSOLUTE', 'ele_trig_data', path + "Run2017/Ele115orEle35_SF_2017.root", 'ELE_MC_ABSOLUTE', 'ele_trig_mc', ptvseta=False) self.sftool_reco = ScaleFactor( path + "Run2017/egammaEffi.txt_EGM2D_runBCDEF_passingRECO.root", "EGamma_SF2D", 'ele_reco') self.sftool_idiso = ScaleFactor( path + "Run2017/2017_ElectronLoose.root", "EGamma_SF2D", 'ele_idiso') elif year == 2018: self.sftool_trig_data = ScaleFactor( path + "Run2018/Ele115orEle35_SF_2018.root", 'ELE_DATA_ABSOLUTE', 'ele_trig_data', ptvseta=False) self.sftool_trig_mc = ScaleFactor( path + "Run2018/Ele115orEle35_SF_2018.root", 'ELE_MC_ABSOLUTE', 'ele_trig_mc', ptvseta=False) self.sftool_trig = ScaleFactorCalc( path + "Run2018/Ele115orEle35_SF_2018.root", 'ELE_DATA_ABSOLUTE', 'ele_trig_data', path + "Run2018/Ele115orEle35_SF_2018.root", 'ELE_MC_ABSOLUTE', 'ele_trig_mc', ptvseta=False) self.sftool_reco = ScaleFactor( path + "Run2018/egammaEffi.txt_EGM2D_updatedAll.root", "EGamma_SF2D", 'ele_reco') self.sftool_idiso = ScaleFactor( path + "Run2018/2018_ElectronLoose.root", "EGamma_SF2D", 'ele_idiso') def getTriggerSF(self, pt, eta): """Get SF for single electron trigger.""" sf_trigger = self.sftool_trig.getSF(pt, eta) return sf_trigger def getTriggerSFerror(self, pt, eta): """Get SF error for single electron trigger.""" sf_trigger_error = self.sftool_trig.getSFerror(pt, eta) return sf_trigger_error def getIdIsoSF(self, pt, eta): """Get SF for electron identification + isolation.""" sf_reco = self.sftool_reco.getSF(pt, eta) if self.sftool_reco else 1. sf_idiso = self.sftool_idiso.getSF(pt, eta) return sf_reco * sf_idiso def getIdIsoSFerror(self, pt, eta): """Get SF error for electron identification + isolation.""" sf_reco = self.sftool_reco.getSF(pt, eta) if self.sftool_reco else 1. sf_idiso = self.sftool_idiso.getSF(pt, eta) sf_reco_error = self.sftool_reco.getSFerror(pt, eta) sf_idiso_error = self.sftool_idiso.getSFerror(pt, eta) sf_reco_idiso_error = np.sqrt((sf_reco_error * sf_idiso)**2 + (sf_idiso_error * sf_reco)**2) return sf_reco_idiso_error