ATLAS Offline Software
Loading...
Searching...
No Matches
GPUToAthenaImporterWithMoments.cxx
Go to the documentation of this file.
1//
2// Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3//
4// Dear emacs, this is -*- c++ -*-
5//
6
8
10
12
13#include <vector>
14#include <algorithm>
15#include <memory>
16
19
20#include "boost/chrono/chrono.hpp"
21#include "boost/chrono/thread_clock.hpp"
22
23using namespace CaloRecGPU;
24
25GPUToAthenaImporterWithMoments::GPUToAthenaImporterWithMoments(const std::string & type, const std::string & name, const IInterface * parent):
26 base_class(type, name, parent),
27 CaloGPUTimed(this),
28 m_doHVMoments(false)
29{
30}
31
32#include "MacroHelpers.h"
33
35{
36 ATH_CHECK( m_cellsKey.initialize() );
37
38 ATH_CHECK( detStore()->retrieve(m_calo_id, "CaloCell_ID") );
39
40 ATH_CHECK(m_caloMgrKey.initialize());
41
44
45 auto get_cluster_size_from_string = [](const std::string & str, bool & failed)
46 {
47 failed = false;
48 //cppcheck-suppress syntaxError
51 SW_55ele,
52 SW_35ele,
53 SW_37ele,
54 SW_55gam,
55 SW_35gam,
56 SW_37gam,
57 SW_55Econv,
58 SW_35Econv,
59 SW_37Econv,
60 SW_softe,
61 Topo_420,
62 Topo_633,
63 SW_7_11,
64 SuperCluster,
65 Tower_01_01,
66 Tower_005_005,
67 Tower_fixed_area
68 )
69 )
70 //I know Topological Clustering only supports a subset of those,
71 //but this is supposed to be a general data exporting tool...
72 else
73 {
74 //failed = true;
76 }
77 };
78
79 bool size_failed = false;
80 m_clusterSize = get_cluster_size_from_string(m_clusterSizeString, size_failed);
81
83 {
84 ATH_MSG_ERROR("Invalid Cluster Size: " << m_clusterSizeString);
85 }
86
87 if (size_failed)
88 {
89 return StatusCode::FAILURE;
90 }
91
92
93 auto get_moment_from_string = [](const std::string & str, bool & failed)
94 {
95 failed = false;
98 FIRST_PHI,
99 FIRST_ETA,
100 SECOND_R,
101 SECOND_LAMBDA,
102 DELTA_PHI,
103 DELTA_THETA,
104 DELTA_ALPHA,
105 CENTER_X,
106 CENTER_Y,
107 CENTER_Z,
108 CENTER_MAG,
109 CENTER_LAMBDA,
110 LATERAL,
111 LONGITUDINAL,
112 ENG_FRAC_EM,
113 ENG_FRAC_MAX,
114 ENG_FRAC_CORE,
115 FIRST_ENG_DENS,
116 SECOND_ENG_DENS,
117 ISOLATION,
118 ENG_BAD_CELLS,
119 N_BAD_CELLS,
120 N_BAD_CELLS_CORR,
121 BAD_CELLS_CORR_E,
122 BADLARQ_FRAC,
123 ENG_POS,
124 SIGNIFICANCE,
125 CELL_SIGNIFICANCE,
126 CELL_SIG_SAMPLING,
127 AVG_LAR_Q,
128 AVG_TILE_Q,
129 ENG_BAD_HV_CELLS,
130 N_BAD_HV_CELLS,
131 PTD,
132 MASS,
133 EM_PROBABILITY,
134 HAD_WEIGHT,
135 OOC_WEIGHT,
136 DM_WEIGHT,
137 TILE_CONFIDENCE_LEVEL,
138 SECOND_TIME,
139 NCELL_SAMPLING,
140 VERTEX_FRACTION,
141 NVERTEX_FRACTION,
142 ETACALOFRAME,
143 PHICALOFRAME,
144 ETA1CALOFRAME,
145 PHI1CALOFRAME,
146 ETA2CALOFRAME,
147 PHI2CALOFRAME,
148 ENG_CALIB_TOT,
149 ENG_CALIB_OUT_L,
150 ENG_CALIB_OUT_M,
151 ENG_CALIB_OUT_T,
152 ENG_CALIB_DEAD_L,
153 ENG_CALIB_DEAD_M,
154 ENG_CALIB_DEAD_T,
155 ENG_CALIB_EMB0,
156 ENG_CALIB_EME0,
157 ENG_CALIB_TILEG3,
158 ENG_CALIB_DEAD_TOT,
159 ENG_CALIB_DEAD_EMB0,
160 ENG_CALIB_DEAD_TILE0,
161 ENG_CALIB_DEAD_TILEG3,
162 ENG_CALIB_DEAD_EME0,
163 ENG_CALIB_DEAD_HEC0,
164 ENG_CALIB_DEAD_FCAL,
165 ENG_CALIB_DEAD_LEAKAGE,
166 ENG_CALIB_DEAD_UNCLASS,
167 ENG_CALIB_FRAC_EM,
168 ENG_CALIB_FRAC_HAD,
169 ENG_CALIB_FRAC_REST)
170 )
171 else
172 {
173 failed = true;
175 }
176 };
177
178
179 auto process_moments = [&](const std::vector<std::string> & moment_names, std::string & invalid_names)
180 {
181 for (const std::string & mom_name : moment_names)
182 {
183 bool failed = false;
184 const int linear_num = MomentsOptionsArray::moment_to_linear(get_moment_from_string(mom_name, failed));
185
186 failed = failed || linear_num >= MomentsOptionsArray::num_moments;
187
188 if (failed)
189 {
190 if (invalid_names.size() == 0)
191 {
192 invalid_names = "'" + mom_name + "'";
193 }
194 else
195 {
196 invalid_names += ", '" + mom_name + "'";
197 }
198 }
199 else
200 {
201 m_momentsToDo.array[linear_num] = true;
202 }
203 }
204 };
205
206 std::string invalid_names;
207
208 process_moments(m_momentsNames, invalid_names);
209
210 if (invalid_names.size() > 0)
211 {
212 ATH_MSG_ERROR( "Moments " << invalid_names
213 << " are not valid moments and will be ignored!" );
214 }
215
217 return StatusCode::SUCCESS;
218}
219
220
221StatusCode GPUToAthenaImporterWithMoments::convert (const EventContext & ctx,
222 const ConstantDataHolder &,
223 EventDataHolder & ed,
224 xAOD::CaloClusterContainer * cluster_container) const
225{
226
227 using clock_type = boost::chrono::thread_clock;
228 auto time_cast = [](const auto & before, const auto & after)
229 {
230 return boost::chrono::duration_cast<boost::chrono::microseconds>(after - before).count();
231 };
232
233 cluster_container->clear();
234
235 const auto start = clock_type::now();
236
237 SG::ReadHandle<CaloCellContainer> cell_collection(m_cellsKey, ctx);
238
239 if ( !cell_collection.isValid() )
240 {
241 ATH_MSG_ERROR( " Cannot retrieve CaloCellContainer: " << cell_collection.name() );
242 return StatusCode::FAILURE;
243 }
244 const DataLink<CaloCellContainer> cell_collection_link (cell_collection.name(), ctx);
245
246 size_t extra_times[6];
247
248 const auto before_export = clock_type::now();
249
250 ed.returnAndExportClusters(cluster_container,
251 &cell_collection_link,
253 false,
255 false,
257 m_measureTimes ? extra_times : nullptr);
258
259 const auto after_export = clock_type::now();
260
261 for (size_t i = 0; i < cluster_container->size(); ++i)
262 {
263 (*cluster_container)[i]->setClusterSize(m_clusterSize);
264 }
265
266 const auto after_size = clock_type::now();
267
268 if (m_doHVMoments)
269 {
272 const LArOnOffIdMapping * cabling = *cablingHdl;
273 const ILArHVScaleCorr * hvcorr = *hvScaleHdl;
274
275 std::vector<double> HV_energies(ed.m_clusters->number, 0.);
276 std::vector<int> HV_numbers(ed.m_clusters->number, 0.);
277
278 for (int i = 0; i < ed.m_clusters->number_cells; ++i)
279 {
280 const int this_cluster = ed.m_clusters->clusterIndices[i];
281
282 const int this_cell_index = ed.m_clusters->cells.indices[i];
283 const int this_hash_ID = ed.m_cell_info->get_hash_ID(this_cell_index, ed.m_cell_info->complete);
284
285 if (GeometryArr::is_tile(this_hash_ID))
286 {
287 continue;
288 }
289
290 HWIdentifier hwid = cabling->createSignalChannelIDFromHash(this_hash_ID);
291 const float corr = hvcorr->HVScaleCorr(hwid);
292
293 if (corr > 0.f && corr < 100.f && fabsf(corr - 1.f) > m_HVthreshold)
294 {
295 HV_energies[this_cluster] += fabsf(ed.m_cell_info->energy[this_cell_index]);
296 ++HV_numbers[this_cluster];
297 }
298 }
299
300 for (int i = 0; i < ed.m_clusters->number; ++i)
301 {
302 xAOD::CaloCluster * cluster = (*cluster_container)[i];
304 {
305 cluster->insertMoment(xAOD::CaloCluster::ENG_BAD_HV_CELLS, HV_energies[i]);
306 }
308 {
309 cluster->insertMoment(xAOD::CaloCluster::N_BAD_HV_CELLS, HV_numbers[i]);
310 }
311 }
312 }
313
314 if (!m_keepGPUData)
315 {
316 ed.clear_GPU();
317 }
318
319 const auto after_HV = clock_type::now();
320
321 if (m_measureTimes)
322 {
323 record_times(ctx.evt(),
324 time_cast(start, before_export),
325 extra_times[0],
326 extra_times[1],
327 extra_times[2],
328 extra_times[3],
329 extra_times[4],
330 extra_times[5],
331 time_cast(after_export, after_size),
332 time_cast(after_size, after_HV)
333 );
334 }
335
336 return StatusCode::SUCCESS;
337
338}
339
340
342{
343 if (m_measureTimes)
344 {
345 print_times("Preprocessing Number_and_State Link_Creation Cell_Processing Sorting Basic_Info Moments Cluster_Size HV_Moments", 9);
346 }
347 return StatusCode::SUCCESS;
348}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
Definition of CaloDetDescrManager.
Helpers for checking error return status codes and reporting errors.
Contains some helpful macros to help with repetitive code...
#define CRGPU_RECURSIVE_MACRO(...)
Expands recursive macros.
#define CRGPU_CHEAP_STRING_TO_ENUM(VAR, PREFIX, ONE,...)
Checks a string variable, VAR, for matching enum identifiers (ONE and the remaining variadic argument...
Gaudi::Property< bool > m_measureTimes
If true, times are recorded to the file given by m_timeFileName.
CaloGPUTimed(T *ptr)
void print_times(const std::string &header, const size_t time_size) const
void record_times(const size_t event_num, const std::vector< size_t > &times) const
Holds CPU and GPU versions of the geometry and cell noise information, which are assumed to be consta...
Definition DataHolders.h:27
Holds the mutable per-event information (clusters and cells) and provides utilities to convert betwee...
Definition DataHolders.h:73
CaloRecGPU::Helpers::CUDA_pinned_CPU_object< CaloRecGPU::CellInfoArr > m_cell_info
CaloRecGPU::Helpers::CUDA_pinned_CPU_object< CaloRecGPU::ClusterInfoArr > m_clusters
void returnAndExportClusters(void *cluster_collection, const void *cell_collection_link, const MomentsOptionsArray &moments_to_add, const bool sort_clusters=true, const bool save_uncalibrated=true, const bool output_extra_moments=false, const std::vector< int > &extra_cells_to_fill={}, size_t *time_measurements=nullptr, CaloRecGPU::CUDA_Helpers::CUDAStreamPtrHolder stream={})
We are using a void* for API to make this able to compile on the GPU without Athena-specific dependen...
size_type size() const noexcept
Returns the number of elements in the collection.
void clear()
Erase all the elements in the collection.
SG::ReadHandleKey< CaloCellContainer > m_cellsKey
vector of names of the cell containers to use as input.
Gaudi::Property< std::string > m_clusterSizeString
Cluster size. Should be set accordingly to the threshold.
SG::ReadCondHandleKey< CaloDetDescrManager > m_caloMgrKey
Key for the CaloDetDescrManager in the Condition Store.
const CaloCell_ID * m_calo_id
Pointer to Calo ID Helper.
GPUToAthenaImporterWithMoments(const std::string &type, const std::string &name, const IInterface *parent)
xAOD::CaloCluster::ClusterSize m_clusterSize
virtual StatusCode convert(const EventContext &ctx, const CaloRecGPU::ConstantDataHolder &constant_data, CaloRecGPU::EventDataHolder &event_data, xAOD::CaloClusterContainer *cluster_collection) const override
Gaudi::Property< bool > m_keepGPUData
If true, do not delete the GPU data representation.
Gaudi::Property< float > m_HVthreshold
Threshold above which a cell contributes to the HV moments.
SG::ReadCondHandleKey< LArOnOffIdMapping > m_HVCablingKey
Cabling for the CPU-based HV moments calculation.
SG::ReadCondHandleKey< ILArHVScaleCorr > m_HVScaleKey
HV corrections for the CPU-based HV moments.
Gaudi::Property< bool > m_saveUncalibrated
if set to true, the uncalibrated state is saved when importing the clusters.
bool m_doHVMoments
To abbreviate checks of m_momentsToDo...
Gaudi::Property< bool > m_fillHVMoments
if set to true, fill the HV-related moments using the respective tools.
Gaudi::Property< std::vector< std::string > > m_momentsNames
vector holding the input list of names of moments to calculate.
CaloRecGPU::MomentsOptionsArray m_momentsToDo
Holds (in a linearized way) the moments and whether to add them to the clusters.
Gaudi::Property< std::vector< int > > m_missingCellsToFill
Cell indices to fill as disabled cells (useful if the cell vector is always missing the same cells).
virtual const float & HVScaleCorr(const HWIdentifier &id) const =0
virtual bool isValid() override final
Can the handle be successfully dereferenced?
const std::string & name() const
Return the StoreGate ID for the referenced object.
void insertMoment(MomentType type, double value)
@ ENG_BAD_HV_CELLS
Total em-scale energy of cells with bad HV in this cluster.
@ N_BAD_HV_CELLS
number of cells with bad HV
@ ENERGY_DigiHSTruth
First Moment in .
Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration.
CaloCluster_v1 CaloCluster
Define the latest version of the calorimeter cluster class.
CaloClusterContainer_v1 CaloClusterContainer
Define the latest version of the calorimeter cluster container.
static constexpr bool is_tile(const int cell)
static int moment_to_linear(const int moment)
static constexpr int num_moments
Definition DataHolders.h:51