ATLAS Offline Software
Loading...
Searching...
No Matches
ForwardElectronToolsTestAlg.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3 Test algorithm: prints variables exactly as extracted in AsgForwardElectronSelectorTool::getInputs()
4*/
5
10#include "CaloGeoHelpers/CaloSampling.h"
11#include <cmath>
12
14 const std::string& name, ISvcLocator* pSvcLocator)
15 : AnaReentrantAlgorithm(name, pSvcLocator)
16{}
17
19{
20 ATH_CHECK(m_electronKey.initialize());
21 ATH_CHECK(m_truthKey.initialize());
22 ATH_CHECK(m_calibTool.retrieve());
23 ATH_CHECK(m_looseTool.retrieve());
24 ATH_CHECK(m_mediumTool.retrieve());
25 ATH_CHECK(m_tightTool.retrieve());
26 ATH_MSG_INFO("ForwardElectronToolsTestAlg initialised");
27 return StatusCode::SUCCESS;
28}
29
30static double deltaR(double eta1, double phi1, double eta2, double phi2) {
31 double deta = eta1 - eta2;
32 double dphi = phi1 - phi2;
33 while (dphi > M_PI) dphi -= 2*M_PI;
34 while (dphi < -M_PI) dphi += 2*M_PI;
35 return std::sqrt(deta*deta + dphi*dphi);
36}
37
38StatusCode ForwardElectronToolsTestAlg::execute(const EventContext& ctx) const
39{
40 ++m_nEvents;
41
43 if (!electrons.isValid()) return StatusCode::SUCCESS;
44
46
47 // Skip events with no forward electrons
48
49 std::vector<const xAOD::Electron*> fwd_electrons;
50 for (const xAOD::Electron* el : *electrons) {
51 const xAOD::CaloCluster* cl = el->caloCluster();
52 if (cl && std::abs(cl->eta()) > 2.5 && std::abs(cl->eta()) <= 4.0)
53 {
54 fwd_electrons.push_back(el);
55 }
56 }
57 if (fwd_electrons.size() == 0) return StatusCode::SUCCESS;
58
59 for (const xAOD::Electron* el : fwd_electrons) {
60 const xAOD::CaloCluster* cluster = el->caloCluster();
61 const xAOD::TrackParticle* track = el->trackParticle();
62 if (!track) continue;
63
65
66 // --- Tool outputs ---
67 const double calibPt = m_calibTool->calibrate(ctx, el);
68 const double score = m_mediumTool->calculate(ctx, el);
69 const bool isLoose = static_cast<bool>(m_looseTool->accept(ctx, el));
70 const bool isMedium = static_cast<bool>(m_mediumTool->accept(ctx, el));
71 const bool isTight = static_cast<bool>(m_tightTool->accept(ctx, el));
72 if (isLoose) ++m_nLoose;
73 if (isMedium) ++m_nMedium;
74 if (isTight) ++m_nTight;
75
76 // --- Truth match ---
77 double truthPt = -1.;
78 double bestDR = 0.3;
79 if (truthParticles.isValid()) {
80 for (const xAOD::TruthParticle* tp : *truthParticles) {
81 if (!tp || std::abs(tp->pdgId()) != 11 || tp->status() != 1) continue;
82 double dr = deltaR(cluster->eta(), cluster->phi(), tp->eta(), tp->phi());
83 if (dr < bestDR) { bestDR = dr; truthPt = tp->pt() / 1000.; }
84 }
85 }
86
87 // =====================================================================
88 // Extract variables exactly as in AsgForwardElectronSelectorTool::getInputs()
89 // =====================================================================
90
91 // x1, x2 = calo eta and phi
92 double calo_eta = cluster->eta();
93 double calo_phi = cluster->phi();
94
95 // x3, x4 = track eta and phi
96 double track_eta = track->eta();
97 double track_phi = track->phi();
98
99 // x5 = HGTD time
100 double hgtd_time = track->time();
101
102 // x6, x7 = ITk hit counts
103 double pixels = el->trackParticleSummaryIntValue(xAOD::numberOfPixelHits);
104 double strips = el->trackParticleSummaryIntValue(xAOD::numberOfSCTHits);
105
106 // x8 to x14 = 7 calorimeter shower-shape moments
107 auto getMom = [&](xAOD::CaloCluster::MomentType type) -> double {
108 double val = 0.;
109 cluster->retrieveMoment(type, val);
110 return val;
111 };
112 double ENG_FRAC_MAX = getMom(xAOD::CaloCluster::ENG_FRAC_MAX);
113 double LONGITUDINAL = getMom(xAOD::CaloCluster::LONGITUDINAL);
114 double SECOND_LAMBDA = getMom(xAOD::CaloCluster::SECOND_LAMBDA);
115 double LATERAL = getMom(xAOD::CaloCluster::LATERAL);
116 double SECOND_R = getMom(xAOD::CaloCluster::SECOND_R);
117 double CENTER_LAMBDA = getMom(xAOD::CaloCluster::CENTER_LAMBDA);
118 double SECOND_ENG_DENS = getMom(xAOD::CaloCluster::SECOND_ENG_DENS);
119
120 // x15 to x18 = track-calo matching
121 auto getMatch = [&](xAOD::EgammaParameters::TrackCaloMatchType type) -> float {
122 float val = 0.f;
123 el->trackCaloMatchValue(val, type);
124 return val;
125 };
126 double delta_eta2 = getMatch(xAOD::EgammaParameters::deltaEta2);
127 double delta_phi2 = getMatch(xAOD::EgammaParameters::deltaPhi2);
128 double delta_phi_rescaled2 = getMatch(xAOD::EgammaParameters::deltaPhiRescaled2);
129 double delta_phi_last = getMatch(xAOD::EgammaParameters::deltaPhiFromLastMeasurement);
130
131 // x19-x25 - energy fractions (exactly as in getInputs())
132 const double caloE = cluster->e();
133 const double inv_E = (caloE != 0.) ? 1. / caloE : 0.;
134 using CS = CaloSampling::CaloSample;
135
136 double frac_EM_1 = cluster->energyBE(1) * inv_E;
137 double frac_EM_2 = cluster->energyBE(2) * inv_E;
138 double frac_EM_3 = cluster->energyBE(3) * inv_E;
139 double frac_HAD_0 = cluster->eSample(static_cast<CS>(CaloSampling::HEC0)) * inv_E;
140 double frac_HAD_1 = (cluster->eSample(static_cast<CS>(CaloSampling::HEC1)) +
141 cluster->eSample(static_cast<CS>(CaloSampling::FCAL0))) * inv_E;
142 double frac_HAD_2 = (cluster->eSample(static_cast<CS>(CaloSampling::HEC2)) +
143 cluster->eSample(static_cast<CS>(CaloSampling::FCAL1))) * inv_E;
144 double frac_HAD_3 = (cluster->eSample(static_cast<CS>(CaloSampling::HEC3)) +
145 cluster->eSample(static_cast<CS>(CaloSampling::FCAL2))) * inv_E;
146
147 double calo_pt = el->pt();
148
149 // =====================================================================
150 // Print in parseable format
151 // =====================================================================
152 if (msgLvl(MSG::DEBUG))
153 {
154 ATH_MSG_DEBUG("FWDEL_START");
155 ATH_MSG_DEBUG(" raw_pT=" << calo_pt/1000.
156 << " calib_pT=" << calibPt/1000.
157 << " truth_pT=" << truthPt
158 << " score_cpp=" << score
159 << " L=" << isLoose << " M=" << isMedium << " T=" << isTight);
160 ATH_MSG_DEBUG(" calo_eta=" << calo_eta
161 << " calo_phi=" << calo_phi
162 << " track_eta=" << track_eta
163 << " track_phi=" << track_phi
164 << " time=" << hgtd_time
165 << " pixels=" << pixels
166 << " strips=" << strips);
167 ATH_MSG_DEBUG(" ENG_FRAC_MAX=" << ENG_FRAC_MAX
168 << " LONGITUDINAL=" << LONGITUDINAL
169 << " SECOND_LAMBDA=" << SECOND_LAMBDA
170 << " LATERAL=" << LATERAL
171 << " SECOND_R=" << SECOND_R
172 << " CENTER_LAMBDA=" << CENTER_LAMBDA
173 << " SECOND_ENG_DENS=" << SECOND_ENG_DENS);
174 ATH_MSG_DEBUG(" delta_eta2=" << delta_eta2
175 << " delta_phi2=" << delta_phi2
176 << " delta_phi_rescaled2=" << delta_phi_rescaled2
177 << " delta_phi_last=" << delta_phi_last);
178 ATH_MSG_DEBUG(" calo_frac_EM_1=" << frac_EM_1
179 << " calo_frac_EM_2=" << frac_EM_2
180 << " calo_frac_EM_3=" << frac_EM_3
181 << " calo_frac_HAD_0=" << frac_HAD_0
182 << " calo_frac_HAD_1=" << frac_HAD_1
183 << " calo_frac_HAD_2=" << frac_HAD_2
184 << " calo_frac_HAD_3=" << frac_HAD_3);
185 ATH_MSG_DEBUG(" calo_pt=" << calo_pt);
186 ATH_MSG_DEBUG("FWDEL_END");
187 }
188 }
189 return StatusCode::SUCCESS;
190}
191
193{
194 const double n = m_nElectrons > 0 ? static_cast<double>(m_nElectrons) : 1.;
195 ATH_MSG_INFO("========================================");
196 ATH_MSG_INFO("Events processed : " << m_nEvents);
197 ATH_MSG_INFO("Forward electrons : " << m_nElectrons);
198 ATH_MSG_INFO("Pass Loose (90%) : " << m_nLoose << " (" << 100.*m_nLoose/n << "%)");
199 ATH_MSG_INFO("Pass Medium (80%) : " << m_nMedium << " (" << 100.*m_nMedium/n << "%)");
200 ATH_MSG_INFO("Pass Tight (70%) : " << m_nTight << " (" << 100.*m_nTight/n << "%)");
201 ATH_MSG_INFO("========================================");
202 return StatusCode::SUCCESS;
203}
204
#define M_PI
Scalar deltaR(const MatrixBase< Derived > &vec) const
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_INFO(x)
#define ATH_MSG_DEBUG(x)
Handle class for reading from StoreGate.
static double deltaR(double eta1, double phi1, double eta2, double phi2)
bool msgLvl(const MSG::Level lvl) const
AnaReentrantAlgorithm(const std::string &name, ISvcLocator *pSvcLocator)
constructor with parameters
SG::ReadHandleKey< xAOD::ElectronContainer > m_electronKey
ToolHandle< IAsgElectronLikelihoodTool > m_tightTool
virtual StatusCode finalize() override
ForwardElectronToolsTestAlg(const std::string &name, ISvcLocator *pSvcLocator)
virtual StatusCode execute(const EventContext &ctx) const override
ToolHandle< IAsgElectronLikelihoodTool > m_looseTool
ToolHandle< AsgForwardElectronCalibrationTool > m_calibTool
SG::ReadHandleKey< xAOD::TruthParticleContainer > m_truthKey
virtual StatusCode initialize() override
ToolHandle< IAsgElectronLikelihoodTool > m_mediumTool
virtual bool isValid() override final
Can the handle be successfully dereferenced?
bool retrieveMoment(MomentType type, double &value) const
Retrieve individual moment.
virtual double eta() const
The pseudorapidity ( ) of the particle.
virtual double e() const
The total energy of the particle.
float eSample(const CaloSample sampling) const
float energyBE(const unsigned layer) const
Get the energy in one layer of the EM Calo.
virtual double phi() const
The azimuthal angle ( ) of the particle.
MomentType
Enums to identify different moments.
@ SECOND_ENG_DENS
Second Moment in E/V.
@ SECOND_LAMBDA
Second Moment in .
@ LATERAL
Normalized lateral moment.
@ LONGITUDINAL
Normalized longitudinal moment.
@ ENG_FRAC_MAX
Energy fraction of hottest cell.
@ SECOND_R
Second Moment in .
@ CENTER_LAMBDA
Shower depth at Cluster Centroid.
@ deltaPhiFromLastMeasurement
difference between the cluster phi (sampling 2) and the eta of the track extrapolated from the last m...
@ deltaEta2
difference between the cluster eta (second sampling) and the eta of the track extrapolated to the sec...
@ deltaPhiRescaled2
difference between the cluster phi (second sampling) and the phi of the track extrapolated to the sec...
@ deltaPhi2
difference between the cluster phi (second sampling) and the phi of the track extrapolated to the sec...
CaloCluster_v1 CaloCluster
Define the latest version of the calorimeter cluster class.
TrackParticle_v1 TrackParticle
Reference the current persistent version:
TruthParticle_v1 TruthParticle
Typedef to implementation.
@ numberOfSCTHits
number of hits in SCT [unit8_t].
@ numberOfPixelHits
these are the pixel hits, including the b-layer [unit8_t].
Electron_v1 Electron
Definition of the current "egamma version".