ATLAS Offline Software
Loading...
Searching...
No Matches
CaloClusterTritonTool.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
10#include "GaudiKernel/SystemOfUnits.h"
11
12#include <cmath>
13#include <cstdint>
14#include <utility>
15#include <variant>
16
17CaloClusterTritonTool::CaloClusterTritonTool(const std::string &type, const std::string &name, const IInterface *parent)
18 : base_class(type, name, parent) {}
19
21{
22 ATH_MSG_DEBUG("Initializing " << name() << "...");
23 ATH_CHECK(m_tritonTool.retrieve());
24 ATH_MSG_INFO("Cell energy threshold for graph construction: " << m_cellEThreshold.value() << " GeV");
25 return StatusCode::SUCCESS;
26}
27
29 AthInfer::InputDataMap &inputData,
30 std::size_t &nCells) const
31{
32 nCells = 0;
33
34 const CaloClusterCellLink *links = cluster.getCellLinks();
35 if (!links) {
36 ATH_MSG_DEBUG("Cluster " << cluster.index() << " has no cell links.");
37 return StatusCode::SUCCESS;
38 }
39 // The links store indices into a CaloCellContainer (normally AllCalo).
40 // If that container is not available, dereferencing a link is a null access.
41 if (!links->getCellContainer()) {
42 ATH_MSG_ERROR("Cell links of cluster " << cluster.index()
43 << " point to cell container '" << links->getCellContainerLink().dataID()
44 << "', which is not available in the event store.");
45 return StatusCode::FAILURE;
46 }
47
48 std::vector<int64_t> cellIds;
49 std::vector<float> cellEnergies;
50 cellIds.reserve(cluster.size());
51 cellEnergies.reserve(cluster.size());
52
53 for (auto itCell = cluster.cell_begin(); itCell != cluster.cell_end(); ++itCell) {
54 const CaloCell *cell = *itCell;
55 if (!cell) continue;
56
57 const float cellE = cell->e() * itCell.weight() / Gaudi::Units::GeV;
58 if (cellE < m_cellEThreshold) continue;
59
60 cellIds.push_back(static_cast<int64_t>(cell->ID().get_identifier32().get_compact()));
61 cellEnergies.push_back(cellE);
62 }
63
64 nCells = cellIds.size();
65 const int64_t n = static_cast<int64_t>(nCells);
66
67 std::vector<float> globalFeatures{static_cast<float>(cluster.rawE() / Gaudi::Units::GeV)};
68
69 inputData[m_cellIdsName.value()] =
70 std::make_pair(std::vector<int64_t>{n, 1}, std::move(cellIds));
71 inputData[m_cellFeaturesName.value()] =
72 std::make_pair(std::vector<int64_t>{n, 1}, std::move(cellEnergies));
73 inputData[m_globalFeaturesName.value()] =
74 std::make_pair(std::vector<int64_t>{1}, std::move(globalFeatures));
75
76 return StatusCode::SUCCESS;
77}
78
80 double &energyGeV,
81 bool &valid) const
82{
83 energyGeV = 0.0;
84 valid = false;
85
86 AthInfer::InputDataMap inputData;
87 std::size_t nCells = 0;
88 ATH_CHECK(buildInputs(cluster, inputData, nCells));
89 if (nCells == 0) return StatusCode::SUCCESS;
90
91 AthInfer::OutputDataMap outputData;
92 outputData[m_outputName.value()] =
93 std::make_pair(std::vector<int64_t>{1, 1}, std::vector<float>{});
94
95 ATH_CHECK(m_tritonTool->inference(inputData, outputData));
96
97 const auto itOut = outputData.find(m_outputName.value());
98 if (itOut == outputData.end()) {
99 ATH_MSG_ERROR("Output tensor '" << m_outputName.value() << "' not returned by server.");
100 return StatusCode::FAILURE;
101 }
102
103 const auto &data = itOut->second.second;
104 if (const auto *vf = std::get_if<std::vector<float>>(&data); vf && !vf->empty()) {
105 energyGeV = vf->front();
106 valid = true;
107 } else if (const auto *vi = std::get_if<std::vector<int64_t>>(&data); vi && !vi->empty()) {
108 energyGeV = static_cast<double>(vi->front());
109 valid = true;
110 }
111
112 return StatusCode::SUCCESS;
113}
114
116 std::vector<double> &clusterE_GNN_vec) const
117{
118 ATH_MSG_DEBUG("Executing " << name() << "...");
119
120 clusterE_GNN_vec.clear();
121 clusterE_GNN_vec.reserve(clusters.size());
122
123 std::size_t nFallback = 0;
124
125 for (const xAOD::CaloCluster *cluster : clusters) {
126 const double rawE = cluster->rawE(); // MeV
127
128 double energyGeV = 0.0;
129 bool valid = false;
130 ATH_CHECK(inferCluster(*cluster, energyGeV, valid));
131
132 if (valid && std::isfinite(energyGeV) && energyGeV > 0.0) {
133 clusterE_GNN_vec.push_back(energyGeV * Gaudi::Units::GeV);
134 } else {
135 clusterE_GNN_vec.push_back(rawE);
136 ++nFallback;
137 }
138 }
139
140 if (nFallback > 0) {
141 ATH_MSG_DEBUG(nFallback << " of " << clusters.size()
142 << " clusters fell back to raw energy (no cells above threshold or invalid prediction).");
143 }
144
145 return StatusCode::SUCCESS;
146}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_DEBUG(x,...)
#define ATH_MSG_ERROR(x,...)
#define ATH_MSG_INFO(x,...)
Data object for each calorimeter readout cell.
Definition CaloCell.h:57
virtual StatusCode initialize() override
Gaudi::Property< std::string > m_cellIdsName
Gaudi::Property< std::string > m_outputName
StatusCode buildInputs(const xAOD::CaloCluster &cluster, AthInfer::InputDataMap &inputData, std::size_t &nCells) const
Fill the input tensor map for one cluster; nCells is the number of cells retained after the energy th...
virtual StatusCode inference(const xAOD::CaloClusterContainer &clusters, std::vector< double > &clusterE_GNN_vec) const override
Gaudi::Property< std::string > m_globalFeaturesName
CaloClusterTritonTool(const std::string &type, const std::string &name, const IInterface *parent)
ToolHandle< AthInfer::IAthInferenceTool > m_tritonTool
StatusCode inferCluster(const xAOD::CaloCluster &cluster, double &energyGeV, bool &valid) const
Run inference for one cluster. energyGeV is meaningful only if valid.
Gaudi::Property< float > m_cellEThreshold
Gaudi::Property< std::string > m_cellFeaturesName
flt_t rawE() const
const CaloClusterCellLink * getCellLinks() const
Get a pointer to the CaloClusterCellLink object (const version).
size_t size() const
size method (forwarded from CaloClusterCellLink obj)
const_cell_iterator cell_end() const
const_cell_iterator cell_begin() const
Iterator of the underlying CaloClusterCellLink (const version).
std::map< std::string, InferenceData > OutputDataMap
std::map< std::string, InferenceData > InputDataMap
CaloCluster_v1 CaloCluster
Define the latest version of the calorimeter cluster class.
CaloClusterContainer_v1 CaloClusterContainer
Define the latest version of the calorimeter cluster container.