ATLAS Offline Software
Loading...
Searching...
No Matches
egammaTransformerCalibTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4#ifndef XAOD_ANALYSIS
7#include "Identifier/Identifier.h"
8
10
11#include "xAODEgamma/Egamma.h"
12#include "xAODEgamma/Photon.h"
13#include "xAODEgamma/Electron.h"
16
19
20#include "TFile.h"
21#include "TMath.h"
22#include "TObjString.h"
23#include "TTree.h"
24#include "TClass.h"
25
26#include <cmath>
27#include <format>
28
29#include "GaudiKernel/SystemOfUnits.h"
30using Gaudi::Units::GeV;
31
33 asg::AsgTool(name)
34{
35}
36
37// Need to declare this out-of-line since the full type of m_funcs
38// isn't available in the header.
42
43
45{
47 ATH_MSG_FATAL("Particle type not set: you have to set property ParticleType to a valid value");
48 return StatusCode::FAILURE;
49 }
50 ATH_MSG_DEBUG("Initializing with particle " << m_particleType);
51
52 if (m_isMC) {
53 ATH_MSG_DEBUG("Input is MC");
54 } else {
55 ATH_MSG_DEBUG("Input is data");
56 }
57
58 if (!m_egammaCellRecoveryTool.empty()) {
59 ATH_MSG_DEBUG("Retrieving cell recovery tool");
61 } else {
62 ATH_MSG_DEBUG("Disabling cell recovery tool");
64 }
65
67 ATH_MSG_DEBUG("Using layer-corrected energies as input to Transformer");
68 //
69 m_layerRecalibTool = std::make_unique<egammaLayerRecalibTool>(m_layerCalibTune, m_useSaccCorrection);
71 m_layerRecalibTool->disable_LayerclEdecoration();
72 // by default it will not apply timing cut fix, we apply the timing cut fix here by default
73 } else {
74 ATH_MSG_DEBUG("Not using layer tool, Using raw layer energies as input to Transformer");
75 }
76
77 // get the Transformer models and initialize functions
78 ATH_MSG_DEBUG("get Transformer ONNX models in folder: " << m_folder);
79 switch (m_particleType) {
81 {
85 }
86 break;
88 {
92 }
93 break;
95 {
99 }
100 break;
101
102 default:
103 ATH_MSG_FATAL("Particle type not set properly: " << m_particleType);
104 return StatusCode::FAILURE;
105 }
106
107 return StatusCode::SUCCESS;
108}
109
110
111StatusCode egammaTransformerCalibTool::setupTransformerModel(const std::string& fileName)
112{
113 ATH_MSG_DEBUG("initialize() initialize salt model...");
114
115 m_saltModel = std::make_unique<FlavorTagInference::SaltModel>(fileName);
116
117 // return StatusCode::SUCCESS;
118
119 // set up decorators using a dummy query of the onnx model
121
122 ATH_MSG_DEBUG("initialize() initialize cluster-level features...");
123 std::vector<float> cluster_feat(m_num_cluster_features, 0.);
124 std::vector<int64_t> cluster_feat_dim = {1, static_cast<int64_t>(cluster_feat.size())};
125 FlavorTagInference::Inputs elec_info(cluster_feat, cluster_feat_dim);
126 gnn_input.insert({"cluster_features", elec_info}); // need to use the "jet_features" keyword as we are borrowing flavour tagging code
127
128 ATH_MSG_DEBUG("initialize() initialize cell-level features...");
129 std::vector<float> cell_feat(m_num_cell_features, 0.);
130 std::vector<int64_t> cell_feat_dim = {1, m_num_cell_features};
131 FlavorTagInference::Inputs track_info(cell_feat, cell_feat_dim);
132 gnn_input.insert({"cell_features", track_info});
133
134 ATH_MSG_DEBUG("initialize() initialize dummy evaluation...");
135 auto [out_f, out_vc, out_vf] = m_saltModel->runInference(gnn_input); // the dummy evaluation
136
137 ATH_MSG_DEBUG("initialize() finished dummy evaluation...");
138 ATH_MSG_DEBUG("initialize() Output Float(s):");
139 for (auto &singlefloat : out_f)
140 {
141 ATH_MSG_DEBUG("initialize() " << singlefloat.first << " = " << singlefloat.second);
142 }
143 ATH_MSG_DEBUG("initialize() Output vector char(s):");
144 for (auto &vecchar : out_vc)
145 {
146 ATH_MSG_DEBUG("initialize() " << vecchar.first << " = ");
147 for (auto &cc : vecchar.second)
148 {
149 ATH_MSG_DEBUG("initialize() " << cc);
150 }
151 }
152
153 ATH_MSG_DEBUG("initialize() Output vector float(s):");
154 for (auto &vecfloat : out_vf)
155 {
156 ATH_MSG_DEBUG("initialize() " << vecfloat.first << " = ");
157 for (auto &ff : vecfloat.second)
158 {
159 ATH_MSG_DEBUG("initialize() " << ff);
160 }
161 }
162
163 if (!out_f.empty() || !out_vc.empty() || out_vf.size() != 1 ||
164 out_vf.begin()->second.empty()) {
165 ATH_MSG_FATAL("Transformer model must provide exactly one non-empty vector-float output");
166 return StatusCode::FAILURE;
167 }
168 m_outputName = out_vf.begin()->first;
169 ATH_MSG_DEBUG("Using Transformer output " << m_outputName);
170
171 return StatusCode::SUCCESS;
172}
173
175 const xAOD::Egamma* eg,
176 const egammaMVACalib::GlobalEventInfo& gei) const
177{
178 // 0. Safety Checks
179 if (!m_saltModel || !eg) {
180 if (m_clusterEif0) {
181 ATH_MSG_WARNING("Model not loaded or Egamma pointer is null, returning cluster energy");
182 return clus.e();
183 } else {
184 ATH_MSG_FATAL("Model not loaded or Egamma pointer is null, and useClusterIf0 is false, cannot proceed");
185 return 0.0f;
186 }
187 }
188
189 // --- 1. Cell Recovery (Timing Cut Fix) ---
191 bool recoverySucceeded = true;
193 egammaCellUtils::MaxECell maxECell(&clus);
194 if (maxECell.sc == StatusCode::FAILURE) {
195 ATH_MSG_WARNING("Issues in finding maximum energy cell.");
196 recoverySucceeded = false;
197 } else {
198 recoveryInfo.etamax = maxECell.etaCell;
199 recoveryInfo.phimax = maxECell.phiCell;
200 if (m_egammaCellRecoveryTool->execute(clus, recoveryInfo).isFailure()) {
201 ATH_MSG_WARNING("Cell Recovery Tool failed. Proceeding without recovered cells.");
202 recoverySucceeded = false;
203 }
204 }
205 }
206 ATH_MSG_DEBUG("Eadded " << recoveryInfo.eCells[0] << " " << recoveryInfo.eCells[1]);
207 ATH_MSG_DEBUG("naddedCells = " << recoveryInfo.addedCells.size() << " " << recoveryInfo.nCells[0] << " " << recoveryInfo.nCells[1]);
208
209 // --- 2. Apply Layer Calibration if needed ---
211 auto array_layer_scales = std::array<double, 4>{1.0, 1.0, 1.0, 1.0}; // default scales
212
213 if (m_layerRecalibTool && !m_isMC && !isForward) {
214 ATH_MSG_DEBUG("Applying layer recalibration for GNN on data.");
215
216 const xAOD::EventInfo* eventInfo = gei.eventInfo;
217 if (!eventInfo) {
218 ATH_MSG_ERROR("EventInfo is required to apply data layer corrections; using configured fallback");
219 return m_clusterEif0 ? clus.e() : 0.0f;
220 }
221 array_layer_scales = m_layerRecalibTool->getLayerCorrections(*eg, *eventInfo);
222 }
223 ATH_MSG_DEBUG("Layer scale "
224 << array_layer_scales[0] << " " << array_layer_scales[1] << " "
225 << array_layer_scales[2] << " " << array_layer_scales[3]);
226
227 if ( m_useExtraLayerScales ) {
228 ATH_MSG_DEBUG("Applying extra layer scales for systematic studies, normally this is for MC events.");
229 if ( !m_isMC ) {
230 ATH_MSG_WARNING("You are applying extra layer scales but the input is not MC! Are you sure this is intended?");
231 }
232 // extract scales from global event info
233 for (std::size_t i = 0; i < 4; ++i)
234 array_layer_scales[i] *= gei.scaleEs[i];
235 }
236
237 // --- 3. Calculate Scale Factors ---
238
239 // Raw energies + Recovered Energy (Timing Fix)
240 // double raw_Es0 = clus.energyBE(0); // LG: not sure if this is still needed but keeping it here for consistency
241 double raw_Es1 = clus.energyBE(1);
242 double raw_Es2 = clus.energyBE(2) + (recoverySucceeded && m_useFixForMissingCells ? recoveryInfo.eCells[0] : 0.0);
243 double raw_Es3 = clus.energyBE(3) + (recoverySucceeded && m_useFixForMissingCells ? recoveryInfo.eCells[1] : 0.0);
244 ATH_MSG_DEBUG("raw Es " << raw_Es1 << " " << raw_Es2 << " " << raw_Es3);
245
246 // --- 4. Cell Gathering ---
247 std::vector<float> cells_E, cells_eta, cells_phi, cells_x, cells_y, cells_z;
248 std::vector<int> cells_layer;
249 std::vector<Identifier> included_cells; // Track cells to avoid duplicates
250
251 // Layer sums
252 double sum_cell_E_L0 = 0.0, sum_cell_E_L1 = 0.0, sum_cell_E_L2 = 0.0, sum_cell_E_L3 = 0.0, sum_cell_E_Gap = 0.0;
253
254 // A. Iterate over Standard Cluster Cells
255 const CaloClusterCellLink* cellLinks = clus.getCellLinks();
256 if (cellLinks) {
257 for (const CaloCell* cell : *cellLinks) {
258 if (!cell || !cell->caloDDE()) {
259 ATH_MSG_WARNING("Skipping calorimeter cell without detector element");
260 continue;
261 }
262
263 int sampling = cell->caloDDE()->getSampling();
264 double scale_factor = 1.0;
265 int layer_idx = -1;
266
267 switch (sampling) {
268 case CaloCell_ID::PreSamplerB: case CaloCell_ID::PreSamplerE:
269 scale_factor = array_layer_scales[0]; layer_idx = 0; break;
270 case CaloCell_ID::EMB1: case CaloCell_ID::EME1:
271 scale_factor = array_layer_scales[1]; layer_idx = 1; break;
272 case CaloCell_ID::EMB2: case CaloCell_ID::EME2:
273 scale_factor = array_layer_scales[2]; layer_idx = 2;
274 // Track cells that might already have been returned by the recovery tool.
275 if (std::abs(cell->time()) > m_timeCut) {
276 included_cells.push_back(cell->ID());
277 }
278 break;
279 case CaloCell_ID::EMB3: case CaloCell_ID::EME3:
280 scale_factor = array_layer_scales[3]; layer_idx = 3;
281 if (std::abs(cell->time()) > m_timeCut) {
282 included_cells.push_back(cell->ID());
283 }
284 break;
285 case CaloCell_ID::TileGap3:
286 scale_factor = 1.0; layer_idx = 4; break;
287 default: continue;
288 }
289
290 double final_E = cell->e() * scale_factor;
291
292 cells_E.push_back(final_E);
293 cells_eta.push_back(cell->eta());
294 cells_phi.push_back(cell->phi());
295 cells_x.push_back(cell->x());
296 cells_y.push_back(cell->y());
297 cells_z.push_back(cell->z());
298 cells_layer.push_back(layer_idx);
299
300 // Accumulate Sums
301 switch(layer_idx) {
302 case 0: sum_cell_E_L0 += final_E; break;
303 case 1: sum_cell_E_L1 += final_E; break;
304 case 2: sum_cell_E_L2 += final_E; break;
305 case 3: sum_cell_E_L3 += final_E; break;
306 case 4: sum_cell_E_Gap += final_E; break;
307 }
308 }
309 }
310
311 // B. Iterate over Recovered Cells (from Tool) - Skip Duplicates
312 // Added cells are only expected in layers 2 and 3, so the dedup list only tracks those layers.
313 if (recoverySucceeded) {
314 for (const CaloCell* cell : recoveryInfo.addedCells) {
315 if (!cell || !cell->caloDDE()) continue;
316
317 // Skip if this cell is already in the cluster
318 if (std::find(included_cells.begin(), included_cells.end(), cell->ID()) != included_cells.end()) {
319 ATH_MSG_WARNING("Recovered cell " << cell->ID() << " already included in cluster. Skipping to avoid double counting.");
320 continue;
321 }
322 else {
323 ATH_MSG_DEBUG("Adding recovered cell " << cell->ID() << " to cluster inputs.");
324 }
325
326 int sampling = cell->caloDDE()->getSampling();
327 double scale_factor = 1.0;
328 int layer_idx = -1;
329
330 if (sampling == CaloCell_ID::EMB2 || sampling == CaloCell_ID::EME2) {
331 scale_factor = array_layer_scales[2]; layer_idx = 2;
332 } else if (sampling == CaloCell_ID::EMB3 || sampling == CaloCell_ID::EME3) {
333 scale_factor = array_layer_scales[3]; layer_idx = 3;
334 } else {
335 // Fallback
336 if (sampling == CaloCell_ID::PreSamplerB || sampling == CaloCell_ID::PreSamplerE) {
337 scale_factor = array_layer_scales[0]; layer_idx = 0;
338 } else if (sampling == CaloCell_ID::EMB1 || sampling == CaloCell_ID::EME1) {
339 scale_factor = array_layer_scales[1]; layer_idx = 1;
340 } else {
341 continue;
342 }
343 }
344
345 double final_E = cell->e() * scale_factor;
346
347 cells_E.push_back(final_E);
348 cells_eta.push_back(cell->eta());
349 cells_phi.push_back(cell->phi());
350 cells_x.push_back(cell->x());
351 cells_y.push_back(cell->y());
352 cells_z.push_back(cell->z());
353 cells_layer.push_back(layer_idx);
354
355 switch(layer_idx) {
356 case 0: sum_cell_E_L0 += final_E; break;
357 case 1: sum_cell_E_L1 += final_E; break;
358 case 2: sum_cell_E_L2 += final_E; break;
359 case 3: sum_cell_E_L3 += final_E; break;
360 /* case 4 is unreachable
361 case 4: sum_cell_E_Gap += final_E; break;
362 */
363 }
364 }
365 }
366
367 // --- 5. Calculate Derived Features (Post-Loop) ---
368 const size_t nCells = cells_E.size();
369 ATH_MSG_DEBUG("Total number of cells " << nCells);
370 if (nCells == 0) {
371 ATH_MSG_WARNING("No supported calorimeter cells; using configured fallback");
372 return m_clusterEif0 ? clus.e() : 0.0f;
373 }
374
375 double sum_cell_E_total = sum_cell_E_L0 + sum_cell_E_L1 + sum_cell_E_L2 + sum_cell_E_L3;
376 const double cluster_eta = clus.eta();
377 const double cluster_phi = clus.phi();
378
379 std::vector<float> cells_deta, cells_dphi, cells_eFrac;
380 cells_deta.reserve(nCells);
381 cells_dphi.reserve(nCells);
382 cells_eFrac.reserve(nCells);
383
384 for (size_t i = 0; i < nCells; ++i) {
385 float deta = cells_eta[i] - cluster_eta;
386 float dphi = cells_phi[i] - cluster_phi;
387 dphi = std::fmod(dphi + 3.0f * M_PI, 2.0f * M_PI) - M_PI;
388
389 cells_deta.push_back(deta);
390 cells_dphi.push_back(dphi);
391
392 float eFrac_layer = 0.0f;
393 switch (cells_layer[i]) {
394 case 0: eFrac_layer = (sum_cell_E_L0 != 0) ? (cells_E[i] / sum_cell_E_L0) : 0.0f; break;
395 case 1: eFrac_layer = (sum_cell_E_L1 != 0) ? (cells_E[i] / sum_cell_E_L1) : 0.0f; break;
396 case 2: eFrac_layer = (sum_cell_E_L2 != 0) ? (cells_E[i] / sum_cell_E_L2) : 0.0f; break;
397 case 3: eFrac_layer = (sum_cell_E_L3 != 0) ? (cells_E[i] / sum_cell_E_L3) : 0.0f; break;
398 case 4: eFrac_layer = (sum_cell_E_Gap != 0) ? (cells_E[i] / sum_cell_E_Gap) : 0.0f; break;
399 }
400 cells_eFrac.push_back(eFrac_layer);
401 }
402
403 // --- 6. Prepare GNN Inputs and Run Inference ---
404 double ratio_L1_L2 = (sum_cell_E_L2 != 0) ? (sum_cell_E_L1 / sum_cell_E_L2) : 0.0;
405 double main_layers_sum = sum_cell_E_L1 + sum_cell_E_L2 + sum_cell_E_L3;
406 double ratio_L0_total = (main_layers_sum != 0) ? (sum_cell_E_L0 / main_layers_sum) : 0.0;
407 double ratio_Tile_total = (main_layers_sum != 0) ? (sum_cell_E_Gap / main_layers_sum) : 0.0;
408
410
411 static const std::vector<std::string> featN = {
412 "Etot", "E0", "E1", "E2", "E3", "Egap", "cleta", "clphi", "E1/E2", "E0/E123", "Egap/E123",
413 "convR", "convEoP", "convPt1OPt2", "convT" };
414
415 // Cluster Features
416 std::vector<float> cluster_feats = {
417 static_cast<float>(sum_cell_E_total),
418 static_cast<float>(sum_cell_E_L0),
419 static_cast<float>(sum_cell_E_L1),
420 static_cast<float>(sum_cell_E_L2),
421 static_cast<float>(sum_cell_E_L3),
422 static_cast<float>(sum_cell_E_Gap),
423 static_cast<float>(cluster_eta),
424 static_cast<float>(cluster_phi),
425 static_cast<float>(ratio_L1_L2),
426 static_cast<float>(ratio_L0_total),
427 static_cast<float>(ratio_Tile_total)
428 };
429
430 // For converted photons, append conversion-specific features in order: convR, convEtOverPt, convPtRatio, conversionType.
432 const xAOD::Photon* photon = dynamic_cast<const xAOD::Photon*>(eg);
433 if (photon) {
434 // - convR
435 float convR = 799.0f;
436 if (egammaMVAFunctions::compute_ptconv(photon) > 3 * GeV) {
438 }
439
440 // - convEtOverPt
441 float convEtOverPt = 0.0f;
442 float ptconv = egammaMVAFunctions::compute_ptconv(photon);
443 if (xAOD::EgammaHelpers::numberOfSiTracks(photon) == 2 && ptconv > 0.0f) {
444 float eacc = (m_useLayerCorrected ?
445 (raw_Es1 * array_layer_scales[1] + raw_Es2 * array_layer_scales[2] + raw_Es3 * array_layer_scales[3]) :
446 (raw_Es1 + raw_Es2 + raw_Es3));
447 float cl_eta = eg->caloCluster()->eta();
448 convEtOverPt = std::max(0.0f, eacc / (std::cosh(cl_eta) * ptconv));
449 }
450 convEtOverPt = std::min(convEtOverPt, 2.0f);
451
452 // - convPtRatio
453 float convPtRatio = 1.0f;
454 if (xAOD::EgammaHelpers::numberOfSiTracks(photon) == 2) {
455 float pt1 = egammaMVAFunctions::compute_pt1conv(photon);
456 float pt2 = egammaMVAFunctions::compute_pt2conv(photon);
457 if ((pt1 + pt2) > 0.0f) {
458 convPtRatio = std::max(pt1, pt2) / (pt1 + pt2);
459 }
460 }
461
462 // - conversionType
463 float conversionType = static_cast<float>(photon->conversionType());
464 // must push back in this order as the model expects features in this order
465 cluster_feats.push_back(convR);
466 cluster_feats.push_back(convEtOverPt);
467 cluster_feats.push_back(convPtRatio);
468 cluster_feats.push_back(conversionType);
469 } else {
470 cluster_feats.push_back(0.0f);
471 cluster_feats.push_back(0.0f);
472 cluster_feats.push_back(0.0f);
473 cluster_feats.push_back(0.0f);
474 }
475 }
476 ATH_MSG_DEBUG("Cluster features ");
477 for (int ifeat = 0; auto f : cluster_feats) {
478 ATH_MSG_DEBUG("Cluster feature " << ifeat << " " << featN[ifeat] << " = " << f);
479 ifeat++;
480 }
481
482 gnn_input["cluster_features"] = FlavorTagInference::Inputs(cluster_feats, {1, (int64_t)cluster_feats.size()});
483
484 // Cell Features
485 std::vector<float> cell_feats_flat;
486 cell_feats_flat.reserve(nCells * m_num_cell_features);
487 for (size_t i = 0; i < nCells; ++i) {
488 cell_feats_flat.push_back(cells_eFrac[i]);
489 cell_feats_flat.push_back(cells_deta[i]);
490 cell_feats_flat.push_back(cells_dphi[i]);
491 cell_feats_flat.push_back(cells_x[i]);
492 cell_feats_flat.push_back(cells_y[i]);
493 cell_feats_flat.push_back(cells_z[i]);
494 cell_feats_flat.push_back(static_cast<float>(cells_layer[i]));
495 ATH_MSG_DEBUG("Cluster feature for cell " << i << " "
496 << "Layer " << cells_layer[i] << " deta = " << cells_deta[i] << " dphi = " << cells_dphi[i]
497 << " x, y, z = " << cells_x[i] << " " << cells_y[i] << " " << cells_z[i]
498 << " eFrac = " << cells_eFrac[i]);
499 }
500 gnn_input["cell_features"] = FlavorTagInference::Inputs(cell_feats_flat, {(int64_t)nCells, m_num_cell_features});
501
502 // Run Inference
503 auto [out_f, out_vc, out_vf] = m_saltModel->runInference(gnn_input);
504
505 float el_gnn_score = 0.0f;
506 const auto output = out_vf.find(m_outputName);
507 if (output == out_vf.end() || output->second.empty()) {
508 ATH_MSG_ERROR("Expected GNN inference output " << m_outputName << " is missing or empty");
509 } else {
510 el_gnn_score = output->second.front();
511 }
512
513 // what to do if the Transformer response is 0;
514 if (el_gnn_score == 0.0f) {
515 return m_clusterEif0 ? clus.e() : 0.0f;
516 }
517
518 return el_gnn_score * static_cast<float>(sum_cell_E_total);
519}
520#endif
#define M_PI
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_FATAL(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
std::string PathResolverFindCalibFile(const std::string &logical_file_name)
Define macros for attributes used to control the static checker.
Data object for each calorimeter readout cell.
Definition CaloCell.h:57
std::vector< const CaloCell * > addedCells
AsgTool(const std::string &name)
Constructor specifying the tool instance's name.
Definition AsgTool.cxx:58
std::unique_ptr< const FlavorTagInference::SaltModel > m_saltModel
Gaudi::Property< bool > m_isMC
Layer calibration related properties.
Gaudi::Property< std::string > m_unconvertedPhotonModelFile
StatusCode setupTransformerModel(const std::string &fileName)
a utility to set up the transformer model, separated from initialize for better readability
Gaudi::Property< std::string > m_layerCalibTune
Gaudi::Property< bool > m_useLayerCorrected
Gaudi::Property< bool > m_useFixForMissingCells
Gaudi::Property< std::string > m_convertedPhotonModelFile
virtual StatusCode initialize() override
Dummy implementation of the initialisation function.
Gaudi::Property< std::string > m_folder
string with folder for weight files
Gaudi::Property< bool > m_useExtraLayerScales
egammaTransformerCalibTool(const std::string &type)
Gaudi::Property< std::string > m_electronModelFile
Gaudi::Property< bool > m_useSaccCorrection
std::unique_ptr< egammaLayerRecalibTool > m_layerRecalibTool
float getEnergy(const xAOD::CaloCluster &clus, const xAOD::Egamma *eg, const egammaMVACalib::GlobalEventInfo &gei=egammaMVACalib::GlobalEventInfo()) const override final
returns the calibrated energy
ToolHandle< IegammaCellRecoveryTool > m_egammaCellRecoveryTool
Pointer to the egammaCellRecoveryTool.
Gaudi::Property< bool > m_clusterEif0
const CaloClusterCellLink * getCellLinks() const
Get a pointer to the CaloClusterCellLink object (const version).
virtual double eta() const
The pseudorapidity ( ) of the particle.
virtual double e() const
The total energy of the particle.
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.
const xAOD::CaloCluster * caloCluster(size_t index=0) const
Pointer to the xAOD::CaloCluster/s that define the electron candidate.
std::map< std::string, Inputs, std::less<> > InputMap
Definition ISaltModel.h:37
float compute_ptconv(const xAOD::Photon *ph)
This ptconv is the old one used by MVACalib.
float compute_pt2conv(const xAOD::Photon *ph)
float compute_pt1conv(const xAOD::Photon *ph)
std::size_t numberOfSiTracks(const xAOD::Photon *eg)
return the number of Si tracks in the conversion
float conversionRadius(const xAOD::Vertex *vx)
return the conversion radius or 9999.
EventInfo_v1 EventInfo
Definition of the latest event info version.
CaloCluster_v1 CaloCluster
Define the latest version of the calorimeter cluster class.
Egamma_v1 Egamma
Definition of the current "egamma version".
Definition Egamma.h:17
Photon_v1 Photon
Definition of the current "egamma version".
A structure holding some global event information.
std::array< float, 4 > scaleEs
const xAOD::EventInfo * eventInfo