diff --git a/higgs_dna/selections/object_selections.py b/higgs_dna/selections/object_selections.py index 38008b467fe57c707a3644fd041fcd2672c64313..57d0a7d5b36591cfe841332407663643097a4fad 100644 --- a/higgs_dna/selections/object_selections.py +++ b/higgs_dna/selections/object_selections.py @@ -1,4 +1,5 @@ import awkward +import numpy as np def delta_r_mask( @@ -19,3 +20,17 @@ def delta_r_mask( """ mval = first.metric_table(second) return awkward.all(mval > threshold, axis=-1) + + +def delta_phi_mask( + Phi1: awkward.highlevel.Array, + Phi2: awkward.highlevel.Array, + threshold: float +) -> awkward.highlevel.Array: + # Select objects that are at least threshold away in Phi space + + # calculate delta_phi + dPhi = abs(Phi1 - Phi2) % (2 * np.pi) + dPhi = awkward.where(dPhi > np.pi, 2 * np.pi - dPhi, dPhi) + + return dPhi > threshold diff --git a/higgs_dna/tools/EcalBadCalibCrystal_events.py b/higgs_dna/tools/EcalBadCalibCrystal_events.py new file mode 100644 index 0000000000000000000000000000000000000000..739bc71ece30d578b60cae92340153e356b287c8 --- /dev/null +++ b/higgs_dna/tools/EcalBadCalibCrystal_events.py @@ -0,0 +1,34 @@ +import awkward as ak +from higgs_dna.selections.object_selections import delta_phi_mask + + +def remove_EcalBadCalibCrystal_events( + events: ak.highlevel.Array +) -> ak.highlevel.Array: + + """ + A peak appears in the pT spectrum of photons due to EcalBadCalibCrystal. The events affected by this has to be rejected. + Check here for more details and for the recipe to mitigate this: + https://indico.cern.ch/event/1397512/contributions/5873976/attachments/2828733/4942264/EcalBadCalibFilterRun3.pdf + """ + + # select the affected runs + run_mask = ((events.run >= 362433) & (events.run <= 367144)) + + # MET cut + MET_cut = (events.PuppiMET.pt > 100) + + # Jet cuts + jet_cuts = ( + (events.Jet.pt > 50) + & ((events.Jet.eta > -0.5) & (events.Jet.eta < -0.1)) + & ((events.Jet.phi > -2.1) & (events.Jet.phi < -1.8)) + & ((events.Jet.neEmEF > 0.9) | (events.Jet.chEmEF > 0.9)) + & (delta_phi_mask(events.PuppiMET.phi, events.Jet.phi, 2.9)) + ) + jet_cuts_any = ak.any(jet_cuts, axis=1) + + events_to_remove = run_mask & MET_cut & jet_cuts_any + events = events[~events_to_remove] + + return events diff --git a/higgs_dna/workflows/HHbbgg.py b/higgs_dna/workflows/HHbbgg.py index 41067658fe9747f44870b0ab2fe1d2ecff3850de..dc9eff80c3430fff59c9ce82e44af6046aeafbe9 100755 --- a/higgs_dna/workflows/HHbbgg.py +++ b/higgs_dna/workflows/HHbbgg.py @@ -1,6 +1,7 @@ from higgs_dna.workflows.base import HggBaseProcessor from higgs_dna.tools.SC_eta import add_photon_SC_eta from higgs_dna.tools.EELeak_region import veto_EEleak_flag +from higgs_dna.tools.EcalBadCalibCrystal_events import remove_EcalBadCalibCrystal_events from higgs_dna.selections.photon_selections import photon_preselection from higgs_dna.selections.lepton_selections import select_electrons, select_muons from higgs_dna.selections.jet_selections import select_jets, select_fatjets, jetvetomap @@ -154,6 +155,10 @@ class HHbbggProcessor(HggBaseProcessor): # apply filters and triggers events = self.apply_filters_and_triggers(events) + # remove events affected by EcalBadCalibCrystal + if self.data_kind == "data": + events = remove_EcalBadCalibCrystal_events(events) + # we need ScEta for corrections and systematics, which is not present in NanoAODv11 but can be calculated using PV events.Photon = add_photon_SC_eta(events.Photon, events.PV) @@ -383,6 +388,7 @@ class HHbbggProcessor(HggBaseProcessor): "PNetRegPtRawCorrNeutrino": Jets.PNetRegPtRawCorrNeutrino, "PNetRegPtRawRes": Jets.PNetRegPtRawRes, "btagRobustParTAK4B": Jets.btagRobustParTAK4B, + "jetId": Jets.jetId, } ) jets = awkward.with_name(jets, "PtEtaPhiMCandidate") diff --git a/higgs_dna/workflows/Zmmy.py b/higgs_dna/workflows/Zmmy.py index 261c6b20124ee6ecdf11237a6c269bd9e46d6b5c..e6008befc0e0f57f4bc752fff269bf63a77ad505 100644 --- a/higgs_dna/workflows/Zmmy.py +++ b/higgs_dna/workflows/Zmmy.py @@ -1,5 +1,6 @@ from higgs_dna.workflows.base import HggBaseProcessor from higgs_dna.tools.SC_eta import add_photon_SC_eta +from higgs_dna.tools.EcalBadCalibCrystal_events import remove_EcalBadCalibCrystal_events from higgs_dna.selections.lepton_selections_Zmmy import ( select_muons_zmmy, select_photons_zmmy, @@ -166,6 +167,10 @@ class ZmmyProcessor(HggBaseProcessor): events = events[trig_flag] # events = events[self.apply_triggers(events)] + # remove events affected by EcalBadCalibCrystal + if self.data_kind == "data": + events = remove_EcalBadCalibCrystal_events(events) + # we need ScEta for corrections and systematics, which is not present in NanoAODv11 but can be calculated using PV events.Photon = add_photon_SC_eta(events.Photon, events.PV) diff --git a/higgs_dna/workflows/base.py b/higgs_dna/workflows/base.py index dfb87ac5f72b7e2aeb4e503a3ef2bb29b94aa014..3fab1c36e0297aa13a6aebdaa8c19d2a74175203 100644 --- a/higgs_dna/workflows/base.py +++ b/higgs_dna/workflows/base.py @@ -5,6 +5,7 @@ from higgs_dna.tools.photonid_mva import calculate_photonid_mva, load_photonid_m from higgs_dna.tools.photonid_mva import calculate_photonid_mva_run3, load_photonid_mva_run3 from higgs_dna.tools.SC_eta import add_photon_SC_eta from higgs_dna.tools.EELeak_region import veto_EEleak_flag +from higgs_dna.tools.EcalBadCalibCrystal_events import remove_EcalBadCalibCrystal_events from higgs_dna.tools.gen_helpers import get_fiducial_flag, get_higgs_gen_attributes from higgs_dna.selections.photon_selections import photon_preselection from higgs_dna.selections.lepton_selections import select_electrons, select_muons @@ -304,6 +305,10 @@ class HggBaseProcessor(processor.ProcessorABC): # type: ignore # apply filters and triggers events = self.apply_filters_and_triggers(events) + # remove events affected by EcalBadCalibCrystal + if self.data_kind == "data": + events = remove_EcalBadCalibCrystal_events(events) + # we need ScEta for corrections and systematics, which is not present in NanoAODv11 but can be calculated using PV events.Photon = add_photon_SC_eta(events.Photon, events.PV) diff --git a/higgs_dna/workflows/dystudies.py b/higgs_dna/workflows/dystudies.py index 72135f167205586089e9ec80383d9c4e6e6469aa..a1d2667db84a9aaa1c83be88bdfc23edd20c4975 100644 --- a/higgs_dna/workflows/dystudies.py +++ b/higgs_dna/workflows/dystudies.py @@ -8,6 +8,7 @@ from higgs_dna.selections.lumi_selections import select_lumis from higgs_dna.utils.dumping_utils import diphoton_list_to_pandas, dump_pandas from higgs_dna.tools.SC_eta import add_photon_SC_eta from higgs_dna.tools.flow_corrections import calculate_flow_corrections +from higgs_dna.tools.EcalBadCalibCrystal_events import remove_EcalBadCalibCrystal_events from typing import Any, Dict, List, Optional import awkward as ak import logging @@ -126,6 +127,10 @@ class TagAndProbeProcessor(HggBaseProcessor): # apply filters and triggers events = self.apply_filters_and_triggers(events) + # remove events affected by EcalBadCalibCrystal + if self.data_kind == "data": + events = remove_EcalBadCalibCrystal_events(events) + # we need ScEta for corrections and systematics, which is not present in NanoAODv11 but can be calculated using PV events.Photon = add_photon_SC_eta(events.Photon, events.PV) diff --git a/higgs_dna/workflows/top.py b/higgs_dna/workflows/top.py index b78d5efcbdca331667a0a07674247fe34522083a..5593cf7f8b1091ded82ce4376f40bb216b273fc3 100644 --- a/higgs_dna/workflows/top.py +++ b/higgs_dna/workflows/top.py @@ -2,6 +2,7 @@ from higgs_dna.workflows.base import HggBaseProcessor from higgs_dna.tools.SC_eta import add_photon_SC_eta from higgs_dna.tools.EELeak_region import veto_EEleak_flag +from higgs_dna.tools.EcalBadCalibCrystal_events import remove_EcalBadCalibCrystal_events from higgs_dna.selections.photon_selections import photon_preselection from higgs_dna.selections.lepton_selections import select_electrons, select_muons from higgs_dna.selections.jet_selections import select_jets, jetvetomap @@ -134,6 +135,10 @@ class TopProcessor(HggBaseProcessor): # type: ignore # apply filters and triggers events = self.apply_filters_and_triggers(events) + # remove events affected by EcalBadCalibCrystal + if self.data_kind == "data": + events = remove_EcalBadCalibCrystal_events(events) + # we need ScEta for corrections and systematics, which is not present in NanoAODv11 but can be calculated using PV events.Photon = add_photon_SC_eta(events.Photon, events.PV)