diff --git a/Preselection/data/HH_ggTauTau_default.json b/Preselection/data/HH_ggTauTau_default.json index 3ffaead..7b0be62 100644 --- a/Preselection/data/HH_ggTauTau_default.json +++ b/Preselection/data/HH_ggTauTau_default.json @@ -14,5 +14,36 @@ "muon1_pt", "muon1_eta", "muon2_pt", "muon2_eta", "tau1_pt", "tau1_eta", "tau2_pt", "tau2_eta", "tau1_id_vs_e", "tau1_id_vs_m", "tau1_id_vs_j", "tau2_id_vs_e", "tau2_id_vs_m", "tau2_id_vs_j", "n_tau", "n_electrons", "n_muons" - ] + ], + "selection_options" : { + "photons" : { + "idmva_cut" : -0.7 + }, + "electrons" : { + "pt" : 10.0, + "eta" : 2.4, + "ip_xy" : 0.045, + "ip_z" : 0.2, + "dR_pho" : 0.2 + }, + "muons" : { + "pt" : 10.0, + "eta" : 2.4, + "ip_xy" : 0.045, + "ip_z" : 0.2, + "rel_iso" : 0.3, + "dR_pho" : 0.2 + }, + "taus" : { + "pt" : 20.0, + "eta" : 2.3, + "dz" : 0.2, + "DeepTau_vs_e" : 2, + "DeepTau_vs_mu" : 1, + "DeepTau_vs_jet" : 8, + "dR_pho" : 0.2, + "dR_lep" : 0.2 + }, + "n_leptons_and_taus" : 1 + } } diff --git a/Preselection/helpers/loop_helper.py b/Preselection/helpers/loop_helper.py index d5c6d03..154ae9b 100644 --- a/Preselection/helpers/loop_helper.py +++ b/Preselection/helpers/loop_helper.py @@ -7,6 +7,7 @@ import awkward import multiprocessing import time +import copy import selections.photon_selections as photon_selections import selections.analysis_selections as analysis_selections @@ -217,19 +218,22 @@ def write_summary(self): def select_events(self, events, metadata): # Dipho preselection - events = photon_selections.diphoton_preselection(events, metadata["resonant"], self.debug) - events.Photon = events.Photon[photon_selections.select_photons(events, self.debug)] + options = copy.deepcopy(self.selection_options) + for key, value in metadata.items(): # add sample-specific options to selection options + options[key] = value + events = photon_selections.diphoton_preselection(events, options, self.debug) + events.Photon = events.Photon[photon_selections.select_photons(events, options, self.debug)] if self.selections == "HHggTauTau_InclusivePresel": - events = analysis_selections.ggTauTau_inclusive_preselection(events, self.debug) - events.Electron = events.Electron[lepton_selections.select_electrons(events, events.Photon, self.debug)] - events.Muon = events.Muon[lepton_selections.select_muons(events, events.Photon, self.debug)] - events.Tau = events.Tau[tau_selections.select_taus(events, events.Photon, events.Muon, events.Electron, self.debug)] + events = analysis_selections.ggTauTau_inclusive_preselection(events, options, self.debug) + events.Electron = events.Electron[lepton_selections.select_electrons(events, events.Photon, options, self.debug)] + events.Muon = events.Muon[lepton_selections.select_muons(events, events.Photon, options, self.debug)] + events.Tau = events.Tau[tau_selections.select_taus(events, events.Photon, events.Muon, events.Electron, options, self.debug)] elif self.selections == "ttH_LeptonicPresel": - events = analysis_selections.tth_leptonic_preselection(events, self.debug) - events.Electron = events.Electron[lepton_selections.select_electrons(events, events.Photon, self.debug)] - events.Muon = events.Muon[lepton_selections.select_muons(events, events.Photon, self.debug)] + events = analysis_selections.tth_leptonic_preselection(events, options, self.debug) + events.Electron = events.Electron[lepton_selections.select_electrons(events, events.Photon, options, self.debug)] + events.Muon = events.Muon[lepton_selections.select_muons(events, events.Photon, options, self.debug)] return events diff --git a/Preselection/selections/analysis_selections.py b/Preselection/selections/analysis_selections.py index 25b31f9..6944378 100644 --- a/Preselection/selections/analysis_selections.py +++ b/Preselection/selections/analysis_selections.py @@ -8,13 +8,13 @@ import selections.tau_selections as tau_selections import selections.photon_selections as photon_selections -def ggTauTau_inclusive_preselection(events, debug): +def ggTauTau_inclusive_preselection(events, options, debug): cut_diagnostics = utils.CutDiagnostics(events = events, debug = debug, cut_set = "[analysis_selections.py : ggTauTau_inclusive_preselection]") # Get number of electrons, muons, taus - electron_selection = lepton_selections.select_electrons(events, events.Photon, debug) - muon_selection = lepton_selections.select_muons(events, events.Photon, debug) - tau_selection = tau_selections.select_taus(events, events.Photon, events.Muon[muon_selection], events.Electron[electron_selection], debug) + electron_selection = lepton_selections.select_electrons(events, events.Photon, options, debug) + muon_selection = lepton_selections.select_muons(events, events.Photon, options, debug) + tau_selection = tau_selections.select_taus(events, events.Photon, events.Muon[muon_selection], events.Electron[electron_selection], options, debug) n_electrons = awkward.num(events.Electron[electron_selection]) n_muons = awkward.num(events.Muon[muon_selection]) @@ -22,14 +22,14 @@ def ggTauTau_inclusive_preselection(events, debug): # Require >= 1 lep/tau n_leptons_and_taus = n_electrons + n_muons + n_taus - lep_tau_cut = n_leptons_and_taus >= 1 + lep_tau_cut = n_leptons_and_taus >= options["n_leptons_and_taus"] # Require OS leptons/taus for events with 2 leptons/taus sum_charge = awkward.sum(events.Electron[electron_selection].charge, axis=1) + awkward.sum(events.Muon[muon_selection].charge, axis=1) + awkward.sum(events.Tau[tau_selection].charge, axis=1) charge_cut = sum_charge == 0 - n_lep_cut = n_leptons_and_taus == 2 + two_leptons = n_leptons_and_taus == 2 not_two_leptons = n_leptons_and_taus != 2 - os_cut = (n_lep_cut & charge_cut) | not_two_leptons # only require 2 OS leptons if there are ==2 leptons in the event + os_cut = (two_leptons & charge_cut) | not_two_leptons # only require 2 OS leptons if there are ==2 leptons in the event all_cuts = lep_tau_cut & os_cut cut_diagnostics.add_cuts([lep_tau_cut, os_cut, all_cuts], ["N_leptons + N_taus >= 1", "OS dileptons", "all"]) @@ -38,7 +38,7 @@ def ggTauTau_inclusive_preselection(events, debug): return events -def tth_leptonic_preselection(events, debug): +def tth_leptonic_preselection(events, options, debug): cut_diagnostics = utils.CutDiagnostics(events = events, debug = debug, cut_set = "[analysis_selections.py : tth_leptonic_preselection]") # Get number of electrons, muons diff --git a/Preselection/selections/lepton_selections.py b/Preselection/selections/lepton_selections.py index ea8b885..6459e66 100644 --- a/Preselection/selections/lepton_selections.py +++ b/Preselection/selections/lepton_selections.py @@ -7,15 +7,17 @@ DR_LEP_PHO = 0.2 -def select_electrons(events, photons, debug): +def select_electrons(events, photons, options, debug): cut_diagnostics = utils.ObjectCutDiagnostics(objects = events.Electron, cut_set = "[lepton_selections.py : select_electrons]", debug = debug) - pt_cut = events.Electron.pt > 10 - eta_cut = abs(events.Electron.eta) < 2.5 - ip_xy_cut = abs(events.Electron.dxy) < 0.045 - ip_z_cut = abs(events.Electron.dz) < 0.2 + pt_cut = events.Electron.pt > options["electrons"]["pt"] + eta_cut = abs(events.Electron.eta) < options["electrons"]["eta"] + ip_xy_cut = abs(events.Electron.dxy) < options["electrons"]["ip_xy"] + ip_z_cut = abs(events.Electron.dz) < options["electrons"]["ip_z"] id_cut = (events.Electron.mvaFall17V2Iso_WP90 == True | ((events.Electron.mvaFall17V2noIso_WP90 == True) & (events.Electron.pfRelIso03_all < 0.3))) - dR_cut = object_selections.select_deltaR(events, events.Electron, photons, DR_LEP_PHO, debug) + # TODO: make ID cut configurable + # also: ID cut has pretty low efficiency on signal, loosen? + dR_cut = object_selections.select_deltaR(events, events.Electron, photons, options["electrons"]["dR_pho"], debug) electron_cut = pt_cut & eta_cut & ip_xy_cut & ip_z_cut & id_cut & dR_cut @@ -23,15 +25,15 @@ def select_electrons(events, photons, debug): return electron_cut -def select_muons(events, photons, debug): +def select_muons(events, photons, options, debug): cut_diagnostics = utils.ObjectCutDiagnostics(objects = events.Muon, cut_set = "[lepton_selections.py : select_muons]", debug = debug) - pt_cut = events.Muon.pt > 10 - eta_cut = abs(events.Muon.eta) < 2.4 - ip_xy_cut = abs(events.Muon.dxy) < 0.045 - ip_z_cut = abs(events.Muon.dz) < 0.2 - iso_cut = events.Muon.pfRelIso03_all < 0.3 - dR_cut = object_selections.select_deltaR(events, events.Muon, photons, DR_LEP_PHO, debug) + pt_cut = events.Muon.pt > options["muons"]["pt"] + eta_cut = abs(events.Muon.eta) < options["muons"]["eta"] + ip_xy_cut = abs(events.Muon.dxy) < options["muons"]["ip_xy"] + ip_z_cut = abs(events.Muon.dz) < options["muons"]["ip_z"] + iso_cut = events.Muon.pfRelIso03_all < options["muons"]["rel_iso"] + dR_cut = object_selections.select_deltaR(events, events.Muon, photons, options["muons"]["dR_pho"], debug) muon_cut = pt_cut & eta_cut & ip_xy_cut & ip_z_cut & iso_cut & dR_cut diff --git a/Preselection/selections/photon_selections.py b/Preselection/selections/photon_selections.py index 75d3527..9702910 100644 --- a/Preselection/selections/photon_selections.py +++ b/Preselection/selections/photon_selections.py @@ -18,13 +18,14 @@ 2. Trim objects with object-level selections afterwards """ -def diphoton_preselection(events, resonant, debug): +def diphoton_preselection(events, options, debug): # Initialize cut diagnostics tool for debugging cut_diagnostics = utils.CutDiagnostics(events = events, debug = debug, cut_set = "[photon_selections.py : diphoton_preselection]") - photons = events.Photon[select_photons(events, debug)] + photons = events.Photon[select_photons(events, options, debug)] ### mgg cut ### + resonant = options["resonant"] if resonant: mgg_mask = numpy.array(events.ggMass > 100) & numpy.array(events.ggMass < 180) else: @@ -41,7 +42,7 @@ def diphoton_preselection(events, resonant, debug): pt_mgg_cut = lead_pt_mgg_cut & sublead_pt_mgg_cut ### pho ID MVA cuts ### - pho_idmva_requirement = photons.mvaID > -0.7 + pho_idmva_requirement = photons.mvaID > options["photons"]["idmva_cut"] pho_idmva_cut = awkward.num(photons[pho_idmva_requirement]) >= 2 # both photons must pass id mva requirement ### electron veto cut ### @@ -58,13 +59,13 @@ def diphoton_preselection(events, resonant, debug): return events -def select_photons(events, debug): +def select_photons(events, options, debug): cut_diagnostics = utils.ObjectCutDiagnostics(objects = events.Photon, cut_set = "[photon_selections.py : select_photons]", debug = debug) pt_cut = events.Photon.pt > 25 eta_cut = abs(events.Photon.eta) < 2.5 pt_mgg_cut = (events.Photon.pt / events.ggMass) >= 0.25 - idmva_cut = events.Photon.mvaID > -0.7 + idmva_cut = events.Photon.mvaID > options["photons"]["idmva_cut"] eveto_cut = events.Photon.electronVeto == 1 photon_cut = pt_cut & eta_cut & pt_mgg_cut & idmva_cut & eveto_cut diff --git a/Preselection/selections/tau_selections.py b/Preselection/selections/tau_selections.py index bd6be40..088e1ab 100644 --- a/Preselection/selections/tau_selections.py +++ b/Preselection/selections/tau_selections.py @@ -8,21 +8,21 @@ DR_TAU_PHO = 0.2 DR_TAU_LEP = 0.2 -def select_taus(events, photons, muons, electrons, debug): +def select_taus(events, photons, muons, electrons, options, debug): cut_diagnostics = utils.ObjectCutDiagnostics(objects = events.Tau, cut_set = "[tau_selections.py : select_taus]", debug = debug) - pt_cut = events.Tau.pt > 20 - eta_cut = abs(events.Tau.eta) < 2.3 + pt_cut = events.Tau.pt > options["taus"]["pt"] + eta_cut = abs(events.Tau.eta) < options["taus"]["eta"] decay_mode_cut = events.Tau.idDecayModeNewDMs == True - dz_cut = abs(events.Tau.dz) < 0.2 + dz_cut = abs(events.Tau.dz) < options["taus"]["dz"] - id_electron_cut = events.Tau.idDeepTau2017v2p1VSe >= 2 - id_muon_cut = events.Tau.idDeepTau2017v2p1VSmu >= 1 - id_jet_cut = events.Tau.idDeepTau2017v2p1VSjet >= 8 + id_electron_cut = events.Tau.idDeepTau2017v2p1VSe >= options["taus"]["DeepTau_vs_e"] + id_muon_cut = events.Tau.idDeepTau2017v2p1VSmu >= options["taus"]["DeepTau_vs_mu"] + id_jet_cut = events.Tau.idDeepTau2017v2p1VSjet >= options["taus"]["DeepTau_vs_jet"] - dR_pho_cut = object_selections.select_deltaR(events, events.Tau, photons, DR_TAU_PHO, debug) - dR_muon_cut = object_selections.select_deltaR(events, events.Tau, muons, DR_TAU_LEP, debug) - dR_ele_cut = object_selections.select_deltaR(events, events.Tau, electrons, DR_TAU_LEP, debug) + dR_pho_cut = object_selections.select_deltaR(events, events.Tau, photons, options["taus"]["dR_pho"], debug) + dR_muon_cut = object_selections.select_deltaR(events, events.Tau, muons, options["taus"]["dR_lep"], debug) + dR_ele_cut = object_selections.select_deltaR(events, events.Tau, electrons, options["taus"]["dR_lep"], debug) tau_cut = pt_cut & eta_cut & decay_mode_cut & dz_cut & id_electron_cut & id_muon_cut & id_jet_cut & dR_pho_cut & dR_muon_cut & dR_ele_cut