ATLAS Offline Software
Loading...
Searching...
No Matches
PhotonBDTCalculator.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
6#include "xAODEgamma/Photon.h"
8#include <limits>
9#include <cmath>
10
11namespace {
12 // Internal helper function
13 inline StatusCode getShowerShape(const xAOD::Photon& ph,
15 float& out)
16 {
17 if (!ph.showerShapeValue(out, t)) { return StatusCode::FAILURE; }
18 return StatusCode::SUCCESS;
19 }
20
21 inline StatusCode getClusterKinematics(const xAOD::Photon& ph, float& eta, float& ptGeV)
22 {
23 const xAOD::CaloCluster* cluster = ph.caloCluster();
24 if (!cluster) { return StatusCode::FAILURE; }
25 eta = cluster->eta();
26 ptGeV = cluster->pt() * 1e-3f;
27 return StatusCode::SUCCESS;
28 }
29
30} // end anonymous namespace
31
32namespace PhotonIDBDT {
33
35 : asg::AsgTool(name)
36{}
37
39
41 // Base tools for BDT evaluation
42 ATH_CHECK(m_toolConv.retrieve());
43 ATH_CHECK(m_toolUnconv.retrieve());
44
45 return StatusCode::SUCCESS;
46}
47
48// Helpers to compute input variables for converted photons
49StatusCode PhotonBDTCalculator::fillVariablesConv(const xAOD::Photon& ph, std::vector<float>& vars) const {
50 vars.clear();
51 vars.reserve(m_reserveVarsConv.value());
52 // Get photon kinematics from cluster
53 float eta = 0.f, ptGeV = 0.f;
54 ATH_CHECK(getClusterKinematics(ph, eta, ptGeV));
55
56 const float ptGeV_capped = std::min(ptGeV, 700.f); // Cap pt at 700 GeV
57 // Get shower shape variables
58 float reta = 0.f, rphi = 0.f, weta2 = 0.f, fracs1 = 0.f, weta1 = 0.f, wtots1 = 0.f, rhad = 0.f, rhad1 = 0.f, eratio = 0.f, deltaE = 0.f;
59 ATH_CHECK(getShowerShape(ph, xAOD::EgammaParameters::Reta, reta));
60 ATH_CHECK(getShowerShape(ph, xAOD::EgammaParameters::Rphi, rphi));
61 ATH_CHECK(getShowerShape(ph, xAOD::EgammaParameters::weta2, weta2));
62 ATH_CHECK(getShowerShape(ph, xAOD::EgammaParameters::fracs1, fracs1));
63 ATH_CHECK(getShowerShape(ph, xAOD::EgammaParameters::weta1, weta1));
64 ATH_CHECK(getShowerShape(ph, xAOD::EgammaParameters::wtots1, wtots1));
65 ATH_CHECK(getShowerShape(ph, xAOD::EgammaParameters::Rhad, rhad));
66 ATH_CHECK(getShowerShape(ph, xAOD::EgammaParameters::Rhad1, rhad1));
67 ATH_CHECK(getShowerShape(ph, xAOD::EgammaParameters::Eratio, eratio));
68 ATH_CHECK(getShowerShape(ph, xAOD::EgammaParameters::DeltaE, deltaE));
69
70 // LAr cell energies are quantised to integer MeV (LArRawChannel stores an int),
71 // so deltaE lives on a 1 MeV lattice. Normalizing flows produce a smooth
72 // distribution and cannot reproduce it, which gives the BDT artificial
73 // separation power. Round the BDT input back onto the lattice to match the
74 // training preprocessing. This is specific to this training.
75 // NB: this runs *after* the fudge/NF correction (see EGPhotonBDTToolWrapper),
76 // so it also quantises that correction.
77 deltaE = std::round(deltaE);
78
79 // Fill variables in the order expected by the BDT tool
80 vars.push_back(ptGeV_capped);
81 vars.push_back(eta);
82 vars.push_back(reta);
83 vars.push_back(rphi);
84 vars.push_back(weta2);
85 vars.push_back(fracs1);
86 vars.push_back(weta1);
87 vars.push_back(wtots1);
88 vars.push_back(rhad);
89 vars.push_back(rhad1);
90 vars.push_back(eratio);
91 vars.push_back(deltaE);
92 // The end!
93 return StatusCode::SUCCESS;
94}
95
96StatusCode PhotonBDTCalculator::fillVariablesUnconv(const xAOD::Photon& ph, std::vector<float>& vars) const {
97 vars.clear();
98 vars.reserve(m_reserveVarsUnconv.value());
99 // Get photon kinematics from cluster
100 float eta = 0.f, ptGeV = 0.f;
101 ATH_CHECK(getClusterKinematics(ph, eta, ptGeV));
102
103 const float ptGeV_capped = std::min(ptGeV, 700.f); // Cap pt at 700 GeV
104 // Get shower shape variables
105 float reta = 0.f, rphi = 0.f, weta2 = 0.f, fracs1 = 0.f, weta1 = 0.f, wtots1 = 0.f, rhad = 0.f, rhad1 = 0.f, eratio = 0.f, deltaE = 0.f;
106 ATH_CHECK(getShowerShape(ph, xAOD::EgammaParameters::Reta, reta));
107 ATH_CHECK(getShowerShape(ph, xAOD::EgammaParameters::Rphi, rphi));
108 ATH_CHECK(getShowerShape(ph, xAOD::EgammaParameters::weta2, weta2));
109 ATH_CHECK(getShowerShape(ph, xAOD::EgammaParameters::fracs1, fracs1));
110 ATH_CHECK(getShowerShape(ph, xAOD::EgammaParameters::weta1, weta1));
111 ATH_CHECK(getShowerShape(ph, xAOD::EgammaParameters::wtots1, wtots1));
112 ATH_CHECK(getShowerShape(ph, xAOD::EgammaParameters::Rhad, rhad));
113 ATH_CHECK(getShowerShape(ph, xAOD::EgammaParameters::Rhad1, rhad1));
114 ATH_CHECK(getShowerShape(ph, xAOD::EgammaParameters::Eratio, eratio));
115 ATH_CHECK(getShowerShape(ph, xAOD::EgammaParameters::DeltaE, deltaE));
116
117 // LAr cell energies are quantised to integer MeV (LArRawChannel stores an int),
118 // so deltaE lives on a 1 MeV lattice. Normalizing flows produce a smooth
119 // distribution and cannot reproduce it, which gives the BDT artificial
120 // separation power. Round the BDT input back onto the lattice to match the
121 // training preprocessing. This is specific to this training.
122 // NB: this runs *after* the fudge/NF correction (see EGPhotonBDTToolWrapper),
123 // so it also quantises that correction.
124 deltaE = std::round(deltaE);
125
126 // Fill variables in the order expected by the BDT tool
127 vars.push_back(ptGeV_capped);
128 vars.push_back(eta);
129 vars.push_back(reta);
130 vars.push_back(rphi);
131 vars.push_back(weta2);
132 vars.push_back(fracs1);
133 vars.push_back(weta1);
134 vars.push_back(wtots1);
135 vars.push_back(rhad);
136 vars.push_back(rhad1);
137 vars.push_back(eratio);
138 vars.push_back(deltaE);
139 // The end!
140 return StatusCode::SUCCESS;
141}
142
146
147StatusCode PhotonBDTCalculator::decorate(const xAOD::Photon& ph) const {
148 const SG::AuxElement::Decorator<float> decScore(m_decorationName);
149 float score = 0.f;
150 ATH_CHECK(getScore(ph, score));
151 decScore(ph) = score;
152 return StatusCode::SUCCESS;
153}
154
155StatusCode PhotonBDTCalculator::getScore(const xAOD::Photon& ph, float& score) const {
156 const SG::AuxElement::Accessor<float> accScore(m_decorationName);
157 if (!m_forceRecompute && accScore.isAvailable(ph)) {
158 score = accScore(ph);
159 return StatusCode::SUCCESS;
160 }
161 std::vector<float> vars;
162 if (isConverted(ph)) {
163 ATH_CHECK(fillVariablesConv(ph, vars));
164 ATH_CHECK(m_toolConv->computeScore(vars, score));
165 } else {
167 ATH_CHECK(m_toolUnconv->computeScore(vars, score));
168 }
169 return StatusCode::SUCCESS;
170}
171
173{
174 if (!photon) {
175 throw std::invalid_argument("PhotonBDTCalculator::evaluate called with nullptr photon");
176 }
177
178 float score = 0.f;
179 const StatusCode sc = getScore(*photon, score);
180 if (sc.isFailure()) {
181 // Fails loudly if it cannot be computed
182 throw std::runtime_error("PhotonBDTCalculator::evaluate failed to compute BDT score");
183 }
184 return static_cast<double>(score);
185}
186
187} // namespace PhotonIDBDT
Scalar eta() const
pseudorapidity method
#define ATH_CHECK
Evaluate an expression and check for errors.
static Double_t sc
StatusCode getScore(const xAOD::Photon &ph, float &score) const
Return the score (computes if needed if m_forceRecompute is true).
Gaudi::Property< bool > m_excludeTRT
StatusCode fillVariablesConv(const xAOD::Photon &ph, std::vector< float > &vars) const
virtual double evaluate(const xAOD::Photon *photon) const override
virtual ~PhotonBDTCalculator() override
Gaudi::Property< bool > m_forceRecompute
bool isConverted(const xAOD::Photon &ph) const
Gaudi::Property< unsigned > m_reserveVarsConv
StatusCode fillVariablesUnconv(const xAOD::Photon &ph, std::vector< float > &vars) const
virtual StatusCode initialize() override
Dummy implementation of the initialisation function.
Gaudi::Property< std::string > m_decorationName
ToolHandle< PhotonSingleBDTCalculator > m_toolConv
ToolHandle< PhotonSingleBDTCalculator > m_toolUnconv
StatusCode decorate(const xAOD::Photon &ph) const
Compute and decorate the photon with the BDT score.
Gaudi::Property< unsigned > m_reserveVarsUnconv
PhotonBDTCalculator(const std::string &name)
AsgTool(const std::string &name)
Constructor specifying the tool instance's name.
Definition AsgTool.cxx:58
virtual double pt() const
The transverse momentum ( ) of the particle (negative for negative-energy clusters).
virtual double eta() const
The pseudorapidity ( ) of the particle.
bool showerShapeValue(float &value, const EgammaParameters::ShowerShapeType information) const
Accessor for ShowerShape values.
const xAOD::CaloCluster * caloCluster(size_t index=0) const
Pointer to the xAOD::CaloCluster/s that define the electron candidate.
::StatusCode StatusCode
StatusCode definition for legacy code.
bool isConvertedPhoton(const xAOD::Egamma *eg, bool excludeTRT=false)
is the object a converted photon
@ wtots1
shower width is determined in a window detaxdphi = 0,0625 ×~0,2, corresponding typically to 20 strips...
@ Eratio
(emaxs1-e2tsts1)/(emaxs1+e2tsts1)
@ DeltaE
e2tsts1-emins1
@ fracs1
shower shape in the shower core : [E(+/-3)-E(+/-1)]/E(+/-1), where E(+/-n) is the energy in ± n strip...
@ weta2
the lateral width is calculated with a window of 3x5 cells using the energy weighted sum over all cel...
@ weta1
shower width using +/-3 strips around the one with the maximal energy deposit: w3 strips = sqrt{sum(E...
Definition EgammaEnums.h:98
CaloCluster_v1 CaloCluster
Define the latest version of the calorimeter cluster class.
Photon_v1 Photon
Definition of the current "egamma version".