Skip to content

Commit

Permalink
allow ID efficiencies in Nano
Browse files Browse the repository at this point in the history
  • Loading branch information
ikrommyd committed Jun 10, 2024
1 parent 248495a commit b1b5269
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 86 deletions.
115 changes: 59 additions & 56 deletions src/egamma_tnp/nanoaod_efficiency.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,9 @@ class ElectronTagNProbeFromNanoAOD(BaseTagNProbe):
def __init__(
self,
fileset,
for_trigger,
egm_nano=False,
filter,
*,
filter="None",
egm_nano=False,
is_photon_filter=False,
trigger_pt=None,
tags_pt_cut=35,
Expand All @@ -35,21 +34,18 @@ def __init__(
use_sc_phi=False,
avoid_ecal_transition_tags=True,
avoid_ecal_transition_probes=False,
hlt_filter=None,
require_event_to_pass_hlt_filter=True,
):
"""Electron Tag and Probe efficiency from NanoAOD and EGamma NanoAOD.
Can only perform trigger efficiencies at the moment.
Parameters
----------
fileset: dict
The fileset to calculate the trigger efficiencies for.
for_trigger: bool
Whether the filter is a trigger or not.
egm_nano: bool, optional
Whether the input fileset is EGamma NanoAOD or NanoAOD. The default is False.
filter: str
The name of the filter to calculate the efficiencies for.
egm_nano: bool, optional
Whether the input fileset is EGamma NanoAOD or NanoAOD. The default is False.
is_photon_filter: bool, optional
Whether the filter to calculate the efficiencies for is a photon filter. The default is False.
trigger_pt: int or float, optional
Expand Down Expand Up @@ -94,18 +90,12 @@ def __init__(
Whether to avoid the ECAL transition region for the tags with an eta cut. The default is True.
avoid_ecal_transition_probes : bool, optional
Whether to avoid the ECAL transition region for the probes with an eta cut. The default is False.
hlt_filter : str, optional
The HLT filter to also require an event to have passed to consider a probe belonging to that event as passing.
If None, no such requirement is applied. The default is None.
require_event_to_pass_hlt_filter : bool, optional
Also require the event to have passed the filter HLT filter under study to consider a probe belonging to that event as passing.
The default is True.
"""
if for_trigger is False:
raise NotImplementedError("Only trigger efficiencies are supported at the moment.")
if use_sc_phi and not egm_nano:
raise NotImplementedError("Supercluster Phi is only available for EGamma NanoAOD.")
if for_trigger and filterbit is None:
raise ValueError("TrigObj filerbit must be provided for trigger efficiencies.")
if filter == "None" and trigger_pt is None and for_trigger:
raise ValueError("An HLT filter name or a trigger Pt threshold must be provided for trigger efficiencies.")
if trigger_pt is None:
from egamma_tnp.utils.misc import find_pt_threshold

Expand All @@ -132,11 +122,16 @@ def __init__(
schemaclass=NanoAODSchema,
default_vars=["el_pt", "el_eta", "el_phi"],
)
self.for_trigger = for_trigger
self.egm_nano = egm_nano
self.is_photon_filter = is_photon_filter
self.filterbit = filterbit
self.hlt_filter = hlt_filter
self.require_event_to_pass_hlt_filter = require_event_to_pass_hlt_filter

if filter.startswith("HLT_"):
if filterbit is None:
raise ValueError("TrigObj filerbit must be provided for trigger efficiencies.")
if self.trigger_pt == 0:
raise ValueError("A trigger Pt threshold must be provided for trigger efficiencies.")

def __repr__(self):
n_of_files = 0
Expand Down Expand Up @@ -205,7 +200,8 @@ def find_probes(self, events, cut_and_count, mass_range, vars):
filterbit=self.filterbit,
cut_and_count=cut_and_count,
mass_range=mass_range,
hlt_filter=self.hlt_filter,
filter=self.filter,
require_event_to_pass_hlt_filter=self.require_event_to_pass_hlt_filter,
is_photon_filter=self.is_photon_filter,
)

Expand Down Expand Up @@ -259,7 +255,8 @@ def _process_zcands(
filterbit,
cut_and_count,
mass_range,
hlt_filter,
filter,
require_event_to_pass_hlt_filter,
is_photon_filter,
):
trigobjs = good_events.TrigObj
Expand Down Expand Up @@ -294,14 +291,19 @@ def _process_zcands(
trigobj_pdgid = 22
else:
trigobj_pdgid = 11
trig_matched_probe = ElectronTagNProbeFromNanoAOD._trigger_match(zcands.probe, trigobjs, trigobj_pdgid, trigger_pt, filterbit)

if filter.startswith("HLT_"):
is_passing_probe = ElectronTagNProbeFromNanoAOD._trigger_match(zcands.probe, trigobjs, trigobj_pdgid, trigger_pt, filterbit)
else:
is_passing_probe = eval(f"zcands.probe.{filter}")
good_events = good_events[events_with_tags]
if hlt_filter is None:
passing_pairs = zcands[trig_matched_probe]
failing_pairs = zcands[~trig_matched_probe]
if filter.startswith("HLT_") and require_event_to_pass_hlt_filter:
hlt_filter = filter.rsplit("_", 1)[0].split("HLT_")[1] if filter.split("HLT_")[1] not in good_events.HLT.fields else filter.split("HLT_")[1]
passing_pairs = zcands[is_passing_probe & getattr(good_events.HLT, hlt_filter)]
failing_pairs = zcands[~(is_passing_probe & getattr(good_events.HLT, hlt_filter))]
else:
passing_pairs = zcands[trig_matched_probe & getattr(good_events.HLT, hlt_filter)]
failing_pairs = zcands[~(trig_matched_probe & getattr(good_events.HLT, hlt_filter))]
passing_pairs = zcands[is_passing_probe]
failing_pairs = zcands[~is_passing_probe]
has_passing_probe = dak.num(passing_pairs) >= 1
has_failing_probe = dak.num(failing_pairs) >= 1
passing_pairs = passing_pairs[has_passing_probe]
Expand All @@ -322,10 +324,9 @@ class PhotonTagNProbeFromNanoAOD(BaseTagNProbe):
def __init__(
self,
fileset,
for_trigger,
egm_nano=False,
filter,
*,
filter="None",
egm_nano=False,
is_electron_filter=False,
start_from_diphotons=True,
trigger_pt=None,
Expand All @@ -344,21 +345,18 @@ def __init__(
use_sc_phi=False,
avoid_ecal_transition_tags=True,
avoid_ecal_transition_probes=False,
hlt_filter=None,
require_event_to_pass_hlt_filter=True,
):
"""Photon Tag and Probe efficiency from NanoAOD and EGamma NanoAOD.
Can only perform trigger efficiencies at the moment.
Parameters
----------
fileset: dict
The fileset to calculate the trigger efficiencies for.
for_trigger: bool
Whether the filter is a trigger or not.
egm_nano: bool, optional
Whether the input fileset is EGamma NanoAOD or NanoAOD. The default is False.
filter: str
The name of the filter to calculate the efficiencies for.
egm_nano: bool, optional
Whether the input fileset is EGamma NanoAOD or NanoAOD. The default is False.
is_electron_filter: bool, optional
Whether the filter to calculate the efficiencies for is an electron filter. The default is False.
start_from_diphotons: bool, optional
Expand Down Expand Up @@ -406,18 +404,12 @@ def __init__(
Whether to avoid the ECAL transition region for the tags with an eta cut. The default is True.
avoid_ecal_transition_probes : bool, optional
Whether to avoid the ECAL transition region for the probes with an eta cut. The default is False.
hlt_filter : str, optional
The HLT filter to also require an event to have passed to consider a probe belonging to that event as passing.
If None, no such requirement is applied. The default is None.
require_event_to_pass_hlt_filter : bool, optional
Also require the event to have passed the filter HLT filter under study to consider a probe belonging to that event as passing.
The default is True.
"""
if for_trigger is False:
raise NotImplementedError("Only trigger efficiencies are supported at the moment.")
if use_sc_phi and not egm_nano:
raise NotImplementedError("Supercluster Phi is not yet available in NanoAOD.")
if for_trigger and filterbit is None:
raise ValueError("TrigObj filerbit must be provided for trigger efficiencies.")
if filter == "None" and trigger_pt is None and for_trigger:
raise ValueError("An HLT filter name or a trigger Pt threshold must be provided for trigger efficiencies.")
if trigger_pt is None:
from egamma_tnp.utils.misc import find_pt_threshold

Expand All @@ -444,12 +436,17 @@ def __init__(
schemaclass=NanoAODSchema,
default_vars=["ph_pt", "ph_eta", "ph_phi"],
)
self.for_trigger = for_trigger
self.egm_nano = egm_nano
self.is_electron_filter = is_electron_filter
self.start_from_diphotons = start_from_diphotons
self.filterbit = filterbit
self.hlt_filter = hlt_filter
self.require_event_to_pass_hlt_filter = require_event_to_pass_hlt_filter

if filter.startswith("HLT_"):
if filterbit is None:
raise ValueError("TrigObj filerbit must be provided for trigger efficiencies.")
if self.trigger_pt == 0:
raise ValueError("A trigger Pt threshold must be provided for trigger efficiencies.")

def __repr__(self):
n_of_files = 0
Expand Down Expand Up @@ -534,7 +531,8 @@ def find_probes(self, events, cut_and_count, mass_range, vars):
filterbit=self.filterbit,
cut_and_count=cut_and_count,
mass_range=mass_range,
hlt_filter=self.hlt_filter,
filter=self.filter,
require_event_to_pass_hlt_filter=self.require_event_to_pass_hlt_filter,
is_electron_filter=self.is_electron_filter,
start_from_diphotons=self.start_from_diphotons,
)
Expand Down Expand Up @@ -588,7 +586,8 @@ def _process_zcands(
filterbit,
cut_and_count,
mass_range,
hlt_filter,
filter,
require_event_to_pass_hlt_filter,
is_electron_filter,
start_from_diphotons,
):
Expand Down Expand Up @@ -631,14 +630,18 @@ def _process_zcands(
trigobj_pdgid = 11
else:
trigobj_pdgid = 22
trig_matched_probe = PhotonTagNProbeFromNanoAOD._trigger_match(zcands.probe, trigobjs, trigobj_pdgid, trigger_pt, filterbit)
if filter.startswith("HLT_"):
is_passing_probe = PhotonTagNProbeFromNanoAOD._trigger_match(zcands.probe, trigobjs, trigobj_pdgid, trigger_pt, filterbit)
else:
is_passing_probe = eval(f"zcands.probe.{filter}")
good_events = good_events[events_with_tags]
if hlt_filter is None:
passing_pairs = zcands[trig_matched_probe]
failing_pairs = zcands[~trig_matched_probe]
if filter.startswith("HLT_") and require_event_to_pass_hlt_filter:
hlt_filter = filter.rsplit("_", 1)[0].split("HLT_")[1] if filter.split("HLT_")[1] not in good_events.HLT.fields else filter.split("HLT_")[1]
passing_pairs = zcands[is_passing_probe & getattr(good_events.HLT, hlt_filter)]
failing_pairs = zcands[~(is_passing_probe & getattr(good_events.HLT, hlt_filter))]
else:
passing_pairs = zcands[trig_matched_probe & getattr(good_events.HLT, hlt_filter)]
failing_pairs = zcands[~(trig_matched_probe & getattr(good_events.HLT, hlt_filter))]
passing_pairs = zcands[is_passing_probe]
failing_pairs = zcands[~is_passing_probe]
has_passing_probe = dak.num(passing_pairs) >= 1
has_failing_probe = dak.num(failing_pairs) >= 1
passing_pairs = passing_pairs[has_passing_probe]
Expand Down
30 changes: 12 additions & 18 deletions src/egamma_tnp/triggers.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,7 @@ def __new__(
else:
instance = ElectronTagNProbeFromNanoAOD(
fileset=fileset,
filter=f"passHltEle{trigger_pt}WPTightGsf",
for_trigger=True,
filter=f"HLT_Ele{trigger_pt}_WPTight_Gsf_v16",
trigger_pt=trigger_pt,
tags_pt_cut=tags_pt_cut,
probes_pt_cut=probes_pt_cut,
Expand All @@ -88,7 +87,7 @@ def __new__(
use_sc_phi=use_sc_phi,
avoid_ecal_transition_tags=avoid_ecal_transition_tags,
avoid_ecal_transition_probes=avoid_ecal_transition_probes,
hlt_filter=f"Ele{trigger_pt}_WPTight_Gsf",
require_event_to_pass_hlt_filter=True,
)

return instance
Expand Down Expand Up @@ -171,8 +170,7 @@ def __new__(
filterbit = 11
instance = ElectronTagNProbeFromNanoAOD(
fileset=fileset,
filter=f"passHltEle{trigger_pt}CaloIdVTGsfTrkIdTGsf",
for_trigger=True,
filter=f"HLT_Ele{trigger_pt}_CaloIdVT_GsfTrkIdT",
trigger_pt=trigger_pt,
tags_pt_cut=tags_pt_cut,
probes_pt_cut=probes_pt_cut,
Expand All @@ -186,7 +184,7 @@ def __new__(
use_sc_phi=use_sc_phi,
avoid_ecal_transition_tags=avoid_ecal_transition_tags,
avoid_ecal_transition_probes=avoid_ecal_transition_probes,
hlt_filter=f"Ele{trigger_pt}_CaloIdVT_GsfTrkIdT",
require_event_to_pass_hlt_filter=True,
)

return instance
Expand Down Expand Up @@ -265,8 +263,7 @@ def __new__(
else:
instance = ElectronTagNProbeFromNanoAOD(
fileset=fileset,
filter=f"passHltEle{trigger_pt1}Ele{trigger_pt2}CaloIdLTrackIdLIsoVLLeg1L1match",
for_trigger=True,
filter=f"HLT_Ele{trigger_pt1}_Ele{trigger_pt2}_CaloIdL_TrackIdL_IsoVL_Leg1",
trigger_pt=trigger_pt1,
tags_pt_cut=tags_pt_cut,
probes_pt_cut=probes_pt_cut,
Expand All @@ -280,7 +277,7 @@ def __new__(
use_sc_phi=use_sc_phi,
avoid_ecal_transition_tags=avoid_ecal_transition_tags,
avoid_ecal_transition_probes=avoid_ecal_transition_probes,
hlt_filter=f"Ele{trigger_pt1}_Ele{trigger_pt2}_CaloIdL_TrackIdL_IsoVL",
require_event_to_pass_hlt_filter=True,
)

return instance
Expand Down Expand Up @@ -366,8 +363,7 @@ def __new__(
)
instance = ElectronTagNProbeFromNanoAOD(
fileset=fileset,
filter=f"passHltEle{trigger_pt1}Ele{trigger_pt2}CaloIdLTrackIdLIsoVLLeg2",
for_trigger=True,
filter=f"HLT_Ele{trigger_pt1}_Ele{trigger_pt2}_CaloIdL_TrackIdL_IsoVL_Leg2",
trigger_pt=trigger_pt2,
tags_pt_cut=tags_pt_cut,
probes_pt_cut=probes_pt_cut,
Expand All @@ -381,7 +377,7 @@ def __new__(
use_sc_phi=use_sc_phi,
avoid_ecal_transition_tags=avoid_ecal_transition_tags,
avoid_ecal_transition_probes=avoid_ecal_transition_probes,
hlt_filter=f"Ele{trigger_pt1}_Ele{trigger_pt2}_CaloIdL_TrackIdL_IsoVL",
require_event_to_pass_hlt_filter=True,
)

return instance
Expand Down Expand Up @@ -462,8 +458,7 @@ def __new__(
raise ValueError("Measuring the efficiency of the HLT_DoubleElePt_CaloIdL_MW trigger is only supported for NanoAODv13 and above.")
instance = ElectronTagNProbeFromNanoAOD(
fileset=fileset,
filter=f"passHltDoubleEle{trigger_pt}CaloIdLMWSeedLegL1match",
for_trigger=True,
filter=f"HLT_DoubleEle{trigger_pt}_CaloIdL_MW_SeededLeg",
trigger_pt=trigger_pt,
tags_pt_cut=tags_pt_cut,
probes_pt_cut=probes_pt_cut,
Expand All @@ -477,7 +472,7 @@ def __new__(
use_sc_phi=use_sc_phi,
avoid_ecal_transition_tags=avoid_ecal_transition_tags,
avoid_ecal_transition_probes=avoid_ecal_transition_probes,
hlt_filter=f"DoubleEle{trigger_pt}_CaloIdL_MW",
require_event_to_pass_hlt_filter=True,
)

return instance
Expand Down Expand Up @@ -558,8 +553,7 @@ def __new__(
raise ValueError("Measuring the efficiency of the HLT_DoubleElePt_CaloIdL_MW trigger is only supported for NanoAODv13 and above.")
instance = ElectronTagNProbeFromNanoAOD(
fileset=fileset,
filter=f"passHltDoubleEle{trigger_pt}CaloIdLMWUnsLeg",
for_trigger=True,
filter=f"HLT_DoubleEle{trigger_pt}_CaloIdL_MW_UnseededLeg",
trigger_pt=trigger_pt,
tags_pt_cut=tags_pt_cut,
probes_pt_cut=probes_pt_cut,
Expand All @@ -573,7 +567,7 @@ def __new__(
use_sc_phi=use_sc_phi,
avoid_ecal_transition_tags=avoid_ecal_transition_tags,
avoid_ecal_transition_probes=avoid_ecal_transition_probes,
hlt_filter=f"DoubleEle{trigger_pt}_CaloIdL_MW",
require_event_to_pass_hlt_filter=True,
)

return instance
9 changes: 3 additions & 6 deletions tests/test_histogramming_nanoaod.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@ def assert_histograms_equal(h1, h2, flow):
def test_histogramming_default_vars(tag_n_probe_class):
tag_n_probe = tag_n_probe_class(
fileset,
True,
filter="Ele30",
filter="HLT_Ele30_WPTight_Gsf",
filterbit=1,
tags_pt_cut=30,
use_sc_eta=True,
Expand Down Expand Up @@ -97,8 +96,7 @@ def test_histogramming_custom_vars(tag_n_probe_class):

tag_n_probe = tag_n_probe_class(
fileset,
True,
filter="Ele30",
filter="HLT_Ele30_WPTight_Gsf",
filterbit=1,
tags_pt_cut=30,
use_sc_eta=True,
Expand Down Expand Up @@ -138,8 +136,7 @@ def test_histogramming_non_probe_vars(tag_n_probe_class):

tag_n_probe = tag_n_probe_class(
fileset,
True,
filter="Ele30",
filter="HLT_Ele30_WPTight_Gsf",
filterbit=1,
tags_pt_cut=30,
use_sc_eta=True,
Expand Down
Loading

0 comments on commit b1b5269

Please sign in to comment.