ATLAS Offline Software
Loading...
Searching...
No Matches
GPUToAthenaImporterWithMoments.cxx
Go to the documentation of this file.
1//
2// Copyright (C) 2002-2025 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;
50 SW_55ele,
51 SW_35ele,
52 SW_37ele,
53 SW_55gam,
54 SW_35gam,
55 SW_37gam,
56 SW_55Econv,
57 SW_35Econv,
58 SW_37Econv,
59 SW_softe,
60 Topo_420,
61 Topo_633,
62 SW_7_11,
63 SuperCluster,
64 Tower_01_01,
65 Tower_005_005,
66 Tower_fixed_area
67 )
68 )
69 //I know Topological Clustering only supports a subset of those,
70 //but this is supposed to be a general data exporting tool...
71 else
72 {
73 //failed = true;
75 }
76 };
77
78 bool size_failed = false;
79 m_clusterSize = get_cluster_size_from_string(m_clusterSizeString, size_failed);
80
82 {
83 ATH_MSG_ERROR("Invalid Cluster Size: " << m_clusterSizeString);
84 }
85
86 if (size_failed)
87 {
88 return StatusCode::FAILURE;
89 }
90
91
92 auto get_moment_from_string = [](const std::string & str, bool & failed)
93 {
94 failed = false;
97 FIRST_PHI,
98 FIRST_ETA,
99 SECOND_R,
100 SECOND_LAMBDA,
101 DELTA_PHI,
102 DELTA_THETA,
103 DELTA_ALPHA,
104 CENTER_X,
105 CENTER_Y,
106 CENTER_Z,
107 CENTER_MAG,
108 CENTER_LAMBDA,
109 LATERAL,
110 LONGITUDINAL,
111 ENG_FRAC_EM,
112 ENG_FRAC_MAX,
113 ENG_FRAC_CORE,
114 FIRST_ENG_DENS,
115 SECOND_ENG_DENS,
116 ISOLATION,
117 ENG_BAD_CELLS,
118 N_BAD_CELLS,
119 N_BAD_CELLS_CORR,
120 BAD_CELLS_CORR_E,
121 BADLARQ_FRAC,
122 ENG_POS,
123 SIGNIFICANCE,
124 CELL_SIGNIFICANCE,
125 CELL_SIG_SAMPLING,
126 AVG_LAR_Q,
127 AVG_TILE_Q,
128 ENG_BAD_HV_CELLS,
129 N_BAD_HV_CELLS,
130 PTD,
131 MASS,
132 EM_PROBABILITY,
133 HAD_WEIGHT,
134 OOC_WEIGHT,
135 DM_WEIGHT,
136 TILE_CONFIDENCE_LEVEL,
137 SECOND_TIME,
138 NCELL_SAMPLING,
139 VERTEX_FRACTION,
140 NVERTEX_FRACTION,
141 ETACALOFRAME,
142 PHICALOFRAME,
143 ETA1CALOFRAME,
144 PHI1CALOFRAME,
145 ETA2CALOFRAME,
146 PHI2CALOFRAME,
147 ENG_CALIB_TOT,
148 ENG_CALIB_OUT_L,
149 ENG_CALIB_OUT_M,
150 ENG_CALIB_OUT_T,
151 ENG_CALIB_DEAD_L,
152 ENG_CALIB_DEAD_M,
153 ENG_CALIB_DEAD_T,
154 ENG_CALIB_EMB0,
155 ENG_CALIB_EME0,
156 ENG_CALIB_TILEG3,
157 ENG_CALIB_DEAD_TOT,
158 ENG_CALIB_DEAD_EMB0,
159 ENG_CALIB_DEAD_TILE0,
160 ENG_CALIB_DEAD_TILEG3,
161 ENG_CALIB_DEAD_EME0,
162 ENG_CALIB_DEAD_HEC0,
163 ENG_CALIB_DEAD_FCAL,
164 ENG_CALIB_DEAD_LEAKAGE,
165 ENG_CALIB_DEAD_UNCLASS,
166 ENG_CALIB_FRAC_EM,
167 ENG_CALIB_FRAC_HAD,
168 ENG_CALIB_FRAC_REST)
169 )
170 else
171 {
172 failed = true;
174 }
175 };
176
177
178 auto process_moments = [&](const std::vector<std::string> & moment_names, std::string & invalid_names)
179 {
180 for (const std::string & mom_name : moment_names)
181 {
182 bool failed = false;
183 const int linear_num = MomentsOptionsArray::moment_to_linear(get_moment_from_string(mom_name, failed));
184
185 failed = failed || linear_num >= MomentsOptionsArray::num_moments;
186
187 if (failed)
188 {
189 if (invalid_names.size() == 0)
190 {
191 invalid_names = "'" + mom_name + "'";
192 }
193 else
194 {
195 invalid_names += ", '" + mom_name + "'";
196 }
197 }
198 else
199 {
200 m_momentsToDo.array[linear_num] = true;
201 }
202 }
203 };
204
205 std::string invalid_names;
206
207 process_moments(m_momentsNames, invalid_names);
208
209 if (invalid_names.size() > 0)
210 {
211 ATH_MSG_ERROR( "Moments " << invalid_names
212 << " are not valid moments and will be ignored!" );
213 }
214
216 return StatusCode::SUCCESS;
217}
218
219
220StatusCode GPUToAthenaImporterWithMoments::convert (const EventContext & ctx,
221 const ConstantDataHolder &,
222 EventDataHolder & ed,
223 xAOD::CaloClusterContainer * cluster_container) const
224{
225
226 using clock_type = boost::chrono::thread_clock;
227 auto time_cast = [](const auto & before, const auto & after)
228 {
229 return boost::chrono::duration_cast<boost::chrono::microseconds>(after - before).count();
230 };
231
232 cluster_container->clear();
233
234 const auto start = clock_type::now();
235
236 SG::ReadHandle<CaloCellContainer> cell_collection(m_cellsKey, ctx);
237
238 if ( !cell_collection.isValid() )
239 {
240 ATH_MSG_ERROR( " Cannot retrieve CaloCellContainer: " << cell_collection.name() );
241 return StatusCode::FAILURE;
242 }
243 const DataLink<CaloCellContainer> cell_collection_link (cell_collection.name(), ctx);
244
245 size_t extra_times[6];
246
247 const auto before_export = clock_type::now();
248
249 ed.returnAndExportClusters(cluster_container,
250 &cell_collection_link,
252 false,
254 false,
256 m_measureTimes ? extra_times : nullptr);
257
258 const auto after_export = clock_type::now();
259
260 for (size_t i = 0; i < cluster_container->size(); ++i)
261 {
262 (*cluster_container)[i]->setClusterSize(m_clusterSize);
263 }
264
265 const auto after_size = clock_type::now();
266
267 if (m_doHVMoments)
268 {
271 const LArOnOffIdMapping * cabling = *cablingHdl;
272 const ILArHVScaleCorr * hvcorr = *hvScaleHdl;
273
274 std::vector<double> HV_energies(ed.m_clusters->number, 0.);
275 std::vector<int> HV_numbers(ed.m_clusters->number, 0.);
276
277 for (int i = 0; i < ed.m_clusters->number_cells; ++i)
278 {
279 const int this_cluster = ed.m_clusters->clusterIndices[i];
280
281 const int this_cell_index = ed.m_clusters->cells.indices[i];
282 const int this_hash_ID = ed.m_cell_info->get_hash_ID(this_cell_index, ed.m_cell_info->complete);
283
284 if (GeometryArr::is_tile(this_hash_ID))
285 {
286 continue;
287 }
288
289 HWIdentifier hwid = cabling->createSignalChannelIDFromHash(this_hash_ID);
290 const float corr = hvcorr->HVScaleCorr(hwid);
291
292 if (corr > 0.f && corr < 100.f && fabsf(corr - 1.f) > m_HVthreshold)
293 {
294 HV_energies[this_cluster] += fabsf(ed.m_cell_info->energy[this_cell_index]);
295 ++HV_numbers[this_cluster];
296 }
297 }
298
299 for (int i = 0; i < ed.m_clusters->number; ++i)
300 {
301 xAOD::CaloCluster * cluster = (*cluster_container)[i];
303 {
304 cluster->insertMoment(xAOD::CaloCluster::ENG_BAD_HV_CELLS, HV_energies[i]);
305 }
307 {
308 cluster->insertMoment(xAOD::CaloCluster::N_BAD_HV_CELLS, HV_numbers[i]);
309 }
310 }
311 }
312
313 if (!m_keepGPUData)
314 {
315 ed.clear_GPU();
316 }
317
318 const auto after_HV = clock_type::now();
319
320 if (m_measureTimes)
321 {
322 record_times(ctx.evt(),
323 time_cast(start, before_export),
324 extra_times[0],
325 extra_times[1],
326 extra_times[2],
327 extra_times[3],
328 extra_times[4],
329 extra_times[5],
330 time_cast(after_export, after_size),
331 time_cast(after_size, after_HV)
332 );
333 }
334
335 return StatusCode::SUCCESS;
336
337}
338
339
341{
342 if (m_measureTimes)
343 {
344 print_times("Preprocessing Number_and_State Link_Creation Cell_Processing Sorting Basic_Info Moments Cluster_Size HV_Moments", 9);
345 }
346 return StatusCode::SUCCESS;
347}
#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