ATLAS Offline Software
Loading...
Searching...
No Matches
BasicConstantGPUDataExporter.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
16
17#include "boost/chrono/chrono.hpp"
18#include "boost/chrono/thread_clock.hpp"
19
20#include <algorithm>
21
22using namespace CaloRecGPU;
23
24BasicConstantGPUDataExporter::BasicConstantGPUDataExporter(const std::string & type, const std::string & name, const IInterface * parent):
25 base_class(type, name, parent),
26 CaloGPUTimed(this),
28{
29}
30
32{
34 {
35 ATH_MSG_INFO("Initializing data tool again...");
36 return StatusCode::SUCCESS;
37 }
38
39 ATH_CHECK(m_noiseCDOKey.initialize());
40
41 ATH_CHECK(m_caloMgrKey.initialize());
42
44
45 return StatusCode::SUCCESS;
46}
47
49{
50 ATH_MSG_ERROR("BasicConstantGPUDataExporter (" << this->name() << ") must be used with the "
51 "GPU data preparation happening on the first event.");
52
53 return StatusCode::FAILURE;
54}
55
56StatusCode BasicConstantGPUDataExporter::convert(const EventContext & ctx, ConstantDataHolder & cd, const bool keep_CPU_info) const
57{
58 using clock_type = boost::chrono::thread_clock;
59 auto time_cast = [](const auto & before, const auto & after)
60 {
61 return boost::chrono::duration_cast<boost::chrono::microseconds>(after - before).count();
62 };
63
64 auto start = clock_type::now();
65
67 const CaloDetDescrManager * calo_dd_man = *caloMgrHandle;
68
69 cd.m_geometry.allocate();
70
71 const CaloCell_ID * calo_id = calo_dd_man->getCaloCell_ID();
72
73#if CALORECGPU_ETA_PHI_MAP_DEBUG
74 float min_eta_pos[NumSamplings], max_eta_pos[NumSamplings],
75 min_eta_neg[NumSamplings], max_eta_neg[NumSamplings],
76 min_phi_pos[NumSamplings], max_phi_pos[NumSamplings],
77 min_phi_neg[NumSamplings], max_phi_neg[NumSamplings],
78 min_deta [NumSamplings], min_dphi [NumSamplings],
79 max_deta [NumSamplings], max_dphi [NumSamplings],
80 avg_deta [NumSamplings], avg_dphi [NumSamplings],
81 min_dr [NumSamplings], min_dz [NumSamplings],
82 max_dr [NumSamplings], max_dz [NumSamplings];
83
84 for (int i = 0; i < NumSamplings; ++i)
85 {
86 min_eta_pos[i] = std::numeric_limits<float>::max();
87 max_eta_pos[i] = std::numeric_limits<float>::lowest();
88 min_eta_neg[i] = std::numeric_limits<float>::max();
89 max_eta_neg[i] = std::numeric_limits<float>::lowest();
90 min_phi_pos[i] = std::numeric_limits<float>::max();
91 max_phi_pos[i] = std::numeric_limits<float>::lowest();
92 min_phi_neg[i] = std::numeric_limits<float>::max();
93 max_phi_neg[i] = std::numeric_limits<float>::lowest();
94 min_deta [i] = std::numeric_limits<float>::max();
95 min_dphi [i] = std::numeric_limits<float>::max();
96 max_deta [i] = std::numeric_limits<float>::lowest();
97 max_dphi [i] = std::numeric_limits<float>::lowest();
98 avg_deta [i] = 0.f;
99 avg_dphi [i] = 0.f;
100 min_dr [i] = std::numeric_limits<float>::max();
101 min_dz [i] = std::numeric_limits<float>::max();
102 max_dr [i] = std::numeric_limits<float>::lowest();
103 max_dz [i] = std::numeric_limits<float>::lowest();
104
105 cd.m_geometry->nCellsPerSampling[i] = 0;
106 }
107#else
108 float min_eta[NumSamplings], max_eta[NumSamplings];
109
110 for (int i = 0; i < NumSamplings; ++i)
111 {
112 min_eta[i] = std::numeric_limits<float>::max();
113 max_eta[i] = std::numeric_limits<float>::lowest();
114
115 cd.m_geometry->nCellsPerSampling[i] = 0;
116 }
117#endif
118
119 for (int cell = 0; cell < NCaloCells; ++cell)
120 {
121 const CaloDetDescrElement * caloElement = calo_dd_man->get_element((IdentifierHash) cell);
122
123 const Identifier cell_identifier = calo_id->cell_id((IdentifierHash) cell);
124
125 const int sampling = calo_id->calo_sample(cell_identifier);
126 const int intra_calo_sampling = calo_id->sampling(cell_identifier);
127 const int subcalo = caloElement->getSubCalo();
128 const int region = calo_id->region(cell_identifier);
129
130 const bool is_PS = (subcalo == CaloCell_ID::LAREM && intra_calo_sampling == 0);
131
132 const bool is_HECIW_or_FCAL = ( (subcalo == CaloCell_ID::LARHEC && region == 1 ) ||
133 (subcalo == CaloCell_ID::LARFCAL && intra_calo_sampling > 1 ) );
134
135 cd.m_geometry->otherCellInfo[cell] = OtherCellInfo(sampling,
139 is_PS,
140 is_HECIW_or_FCAL);
141 cd.m_geometry->x[cell] = caloElement->x();
142 cd.m_geometry->y[cell] = caloElement->y();
143 cd.m_geometry->z[cell] = caloElement->z();
144 cd.m_geometry->r[cell] = caloElement->r();
145 cd.m_geometry->eta[cell] = caloElement->eta();
146 cd.m_geometry->phi[cell] = caloElement->phi();
147
148 cd.m_geometry->dx[cell] = caloElement->dx();
149 cd.m_geometry->dy[cell] = caloElement->dy();
150 cd.m_geometry->dz[cell] = caloElement->dz();
151 cd.m_geometry->dr[cell] = caloElement->dr();
152 cd.m_geometry->deta[cell] = caloElement->deta();
153 cd.m_geometry->dphi[cell] = caloElement->dphi();
154
155 cd.m_geometry->volume[cell] = caloElement->volume();
156 cd.m_geometry->neighbours.offsets[cell] = 0;
157
158#if CALORECGPU_ETA_PHI_MAP_DEBUG
159 const float eta_minus = caloElement->eta() - caloElement->deta() / 2;
160 const float eta_plus = caloElement->eta() + caloElement->deta() / 2;
161 const float phi_minus = caloElement->phi() - caloElement->dphi() / 2;
162 const float phi_plus = caloElement->phi() + caloElement->dphi() / 2;
163
164 if (caloElement->eta() >= 0)
165 {
166 min_eta_pos[sampling] = std::min({min_eta_pos[sampling], eta_minus, eta_plus});
167 min_phi_pos[sampling] = std::min({min_phi_pos[sampling], phi_minus, phi_plus});
168 max_eta_pos[sampling] = std::max({max_eta_pos[sampling], eta_minus, eta_plus});
169 max_phi_pos[sampling] = std::max({max_phi_pos[sampling], phi_minus, phi_plus});
170 }
171 else
172 {
173 min_eta_neg[sampling] = std::min({min_eta_neg[sampling], eta_minus, eta_plus});
174 min_phi_neg[sampling] = std::min({min_phi_neg[sampling], phi_minus, phi_plus});
175 max_eta_neg[sampling] = std::max({max_eta_neg[sampling], eta_minus, eta_plus});
176 max_phi_neg[sampling] = std::max({max_phi_neg[sampling], phi_minus, phi_plus});
177 }
178 min_deta[sampling] = std::min(min_deta[sampling], caloElement->deta());
179 min_dphi[sampling] = std::min(min_dphi[sampling], caloElement->dphi());
180 max_deta[sampling] = std::max(max_deta[sampling], caloElement->deta());
181 max_dphi[sampling] = std::max(max_dphi[sampling], caloElement->dphi());
182 min_dr [sampling] = std::min(min_dr [sampling], caloElement->dr ());
183 min_dz [sampling] = std::min(min_dz [sampling], caloElement->dz ());
184 max_dr [sampling] = std::max(max_dr [sampling], caloElement->dr ());
185 max_dz [sampling] = std::max(max_dz [sampling], caloElement->dz ());
186
187 avg_deta[sampling] += caloElement->deta();
188 avg_dphi[sampling] += caloElement->dphi();
189#else
190 const float eta_below = fabsf(caloElement->eta() - caloElement->deta() / 2);
191 const float eta_above = fabsf(caloElement->eta() + caloElement->deta() / 2);
192 min_eta[sampling] = std::min(min_eta[sampling], std::min(eta_below, eta_above));
193 max_eta[sampling] = std::max(max_eta[sampling], std::max(eta_below, eta_above));
194#endif
195
196 cd.m_geometry->nCellsPerSampling[sampling] += 1;
197 }
198
199 auto after_geo = clock_type::now();
200
201 for (int i = 0; i < NumSamplings; ++i)
202 {
203#if CALORECGPU_ETA_PHI_MAP_DEBUG
204 avg_deta[i] /= cd.m_geometry->nCellsPerSampling[i];
205 avg_dphi[i] /= cd.m_geometry->nCellsPerSampling[i];
206 if (cd.m_geometry->nCellsPerSampling[i] > 0)
207 {
208 printf("CALORECGPU ETA PHI MAP DEBUG OUTPUT: %d | %f %f %f %f | %f %f %f %f | %f %f | %f %f | %f %f %d | %f %f | %f %f\n",
209 i, min_eta_neg[i], min_phi_neg[i], max_eta_neg[i], max_phi_neg[i],
210 min_eta_pos[i], min_phi_pos[i], max_eta_pos[i], max_phi_pos[i],
211 min_deta[i], min_dphi[i], max_deta[i], max_dphi[i],
212 avg_deta[i], avg_dphi[i], cd.m_geometry->nCellsPerSampling[i],
213 min_dr[i], min_dz[i], max_dr[i], max_dz[i]);
214 }
215 const float this_min_eta = std::min(fabsf(max_eta_neg[i]), fabsf(min_eta_pos[i]));
216 const float this_max_eta = std::max(fabsf(min_eta_neg[i]), fabsf(max_eta_pos[i]));
217#else
218 const float this_min_eta = min_eta[i];
219 const float this_max_eta = max_eta[i];
220#endif
221
222 if (cd.m_geometry->nCellsPerSampling[i] <= 0)
223 {
224 cd.m_geometry->etaPhiToCell.initialize(i, -1, 1);
225 //Just to prevent NaN.
226 }
227 else
228 {
229 cd.m_geometry->etaPhiToCell.initialize(i, this_min_eta, this_max_eta);
230 }
231 }
232
233 cd.m_geometry->fill_eta_phi_map();
234
235#if CALORECGPU_ETA_PHI_MAP_DEBUG
236 for (int i = 0; i < NumSamplings; ++i)
237 {
238 auto printer = [&](const auto & entry)
239 {
240 printf("CALORECGPU ETA PHI MAP DEBUG OUTPUT: %d | %d\n", i, entry.get_max_real_overlap());
241 };
242
243 cd.m_geometry->etaPhiToCell.apply_to_sampling(i, printer);
244 }
245#endif
246
247 auto after_eta_phi = clock_type::now();
248
249 std::vector<IdentifierHash> neighbour_vector, full_neighs, prev_neighs;
250
251 for (int cell = 0; cell < NCaloCells; ++cell)
252 {
253 for (int neigh_bit_set = 0; neigh_bit_set < NumNeighOptions; ++neigh_bit_set)
254 {
255 const unsigned int curr_neigh_opt = (1U << neigh_bit_set);
256
257 if (curr_neigh_opt == LArNeighbours::corners2D || curr_neigh_opt == LArNeighbours::corners3D)
258 //Scanning the ATLAS codebase, neighbour handling has special cases
259 //for all2D (LarFCAL_Base_ID.cxx, LArMiniFCAL_ID.cxx, Tile_Base_ID.cxx)
260 //and all3DwithCorners (Tile_Base_ID.cxx), which include
261 //neighbours not returned when just the constituent bits are set separately.
262 //As an imperfect workaround, we stuff them in the immediately previous option
263 //(corners, for both 2D and 3D).
264 {
265 if (curr_neigh_opt == LArNeighbours::corners2D)
266 {
267 calo_id->get_neighbours((IdentifierHash) cell,
269 full_neighs);
270 }
271 else /*if (curr_neigh_opt == LArNeighbours::corners3D)*/
272 {
273 calo_id->get_neighbours((IdentifierHash) cell,
275 prev_neighs);
276 calo_id->get_neighbours((IdentifierHash) cell,
278 neighbour_vector);
279 //We will exclude the cells that could come from later options
280 //(it seems, from Tile_Base_ID.cxx, all3DwithCorners will give more than super3D),
281 //which... might make some sense, but seems unexpected.
282
283
284 std::sort(neighbour_vector.begin(), neighbour_vector.end());
285 std::sort(prev_neighs.begin(), prev_neighs.end());
286
287 full_neighs.clear();
288
289 std::set_difference( prev_neighs.begin(), prev_neighs.end(),
290 neighbour_vector.begin(), neighbour_vector.end(),
291 std::back_inserter(full_neighs) );
292
293 }
294
295 prev_neighs.resize(cd.m_geometry->neighbours.get_total_number_of_neighbours(cell));
296 //We want to add just the neighbours that are not part of this.
297
298 for (size_t neigh = 0; neigh < prev_neighs.size(); ++neigh)
299 {
300 prev_neighs[neigh] = cd.m_geometry->neighbours.get_neighbour(cell, neigh);
301 }
302
303 std::sort(full_neighs.begin(), full_neighs.end());
304 std::sort(prev_neighs.begin(), prev_neighs.end());
305
306 neighbour_vector.clear();
307
308 std::set_difference( full_neighs.begin(), full_neighs.end(),
309 prev_neighs.begin(), prev_neighs.end(),
310 std::back_inserter(neighbour_vector) );
311 }
312 else
313 {
314 calo_id->get_neighbours((IdentifierHash) cell, (LArNeighbours::neighbourOption) curr_neigh_opt, neighbour_vector);
315 }
316
317 std::sort(neighbour_vector.begin(), neighbour_vector.end());
318
319 const int neighs_start = cd.m_geometry->neighbours.get_total_number_of_neighbours(cell);
320
321 for (size_t neigh_num = 0; neigh_num < neighbour_vector.size(); ++neigh_num)
322 {
323 cd.m_geometry->neighbours.set_neighbour(cell, neighs_start + neigh_num, neighbour_vector[neigh_num]);
324 }
325
326 cd.m_geometry->neighbours.offsets[cell] += NeighOffset::offset_delta(neigh_bit_set) * neighbour_vector.size();
327
328 }
329 }
330
331#if CALORECGPU_ADD_FULL_PAIRS_LIST_TO_CONSTANT_INFORMATION
332
333//Note: the commented out code is used to output the hard-coded numbers
334//in NeighPairsArr. For the time being, it should remain here until
335//a more definitive solution for the geometry is found.
336
337 {
338 int num_pairs = 0;
339
340 auto add_neighbours = [&](const int cell, const unsigned int curr_neigh_opt)
341 {
342 int neighbours[NMaxNeighbours];
343
344 const int num_neighs = cd.m_geometry->neighbours.get_neighbours(curr_neigh_opt, cell, neighbours);
345
346 for (int neigh = 0; neigh < num_neighs; ++neigh)
347 {
348 cd.m_geometry->neighPairs.cell_A[num_pairs] = cell;
349 cd.m_geometry->neighPairs.cell_B[num_pairs] = neighbours[neigh];
350 ++num_pairs;
351 }
352 };
353
354 for (int neigh_bit_set = 0; neigh_bit_set < NumNeighOptions; ++neigh_bit_set)
355 {
356 const unsigned int curr_neigh_opt = (1U << neigh_bit_set);
357
358 for (int cell = 0; cell < NCaloCells; ++cell)
359 {
360 if (cd.m_geometry->is_PS(cell) || cd.m_geometry->is_HECIW_or_FCal(cell))
361 {
362 continue;
363 }
364
365 add_neighbours(cell, curr_neigh_opt);
366 }
367
368 //const int PS_start = num_pairs;
369
370 for (int cell = 0; cell < NCaloCells; ++cell)
371 {
372 if (!cd.m_geometry->is_PS(cell))
373 {
374 continue;
375 }
376
377 add_neighbours(cell, curr_neigh_opt);
378 }
379
380 //const int HECIW_FCal_start = num_pairs;
381
382 for (int cell = 0; cell < NCaloCells; ++cell)
383 {
384 if (!cd.m_geometry->is_HECIW_or_FCal(cell))
385 {
386 continue;
387 }
388
389 add_neighbours(cell, curr_neigh_opt);
390 }
391
392 //std::cout << neigh_bit_set << " " << num_pairs << " " << PS_start << " " << HECIW_FCal_start << std::endl;
393 }
394 }
395#endif
396
397 auto after_pairs = clock_type::now();
398
399 /*
400 //Useful output for debugging and studying regularities in calorimeter geometry...
401
402 std::cout << "ID\tCaloSample\tSampling\tRegion\tSubCalo";
403 for (int j = 0; j < NumNeighOptions; ++j)
404 {
405 std::cout << "\tn_" << j;
406 }
407 std::cout << "\tn_total\tOffset" << std::endl;
408
409 for (int cell = 0; cell < NCaloCells; ++cell)
410 {
411
412 const CaloDetDescrElement * caloElement = calo_dd_man->get_element((IdentifierHash) cell);
413 std::cout << cell << "\t"
414 << (int) calo_id->calo_sample(calo_id->cell_id((IdentifierHash) cell)) << "\t"
415 << (int) calo_id->sampling(calo_id->cell_id((IdentifierHash) cell)) << "\t"
416 << (int) calo_id->region(calo_id->cell_id((IdentifierHash) cell)) << "\t"
417 << (int) caloElement->getSubCalo();
418
419 const NeighOffset n_off = cd.m_geometry->neighbours.offsets[cell];
420
421 for (int j = 0; j < NumNeighOptions; ++j)
422 {
423 std::cout << "\t" << n_off.get_num_cells(j);
424 }
425
426 std::cout << "\t" << n_off.get_total_number() << "\t" << n_off << std::endl;
427 }
428 // */
429
431 const CaloNoise * noise_tool = *noise_handle;
432
433 IdentifierHash t_start, t_end;
434 calo_id->calo_cell_hash_range(CaloCell_ID::TILE, t_start, t_end);
435
436 if (t_start != TileCellStart)
437 {
438 ATH_MSG_WARNING("Tile start (" << t_start << ") differs from assumed constant value (" << TileCellStart << ")!");
439 }
440 if (t_end != TileCellAfterEnd)
441 {
442 ATH_MSG_WARNING("Tile end (" << t_end << ") differs from assumed constant value (" << TileCellAfterEnd << ")!");
443 }
444
445 const CaloCondBlobFlt * blob = noise_tool->getTileBlob();
446
447 cd.m_cell_noise.allocate();
448
449 if (!blob)
450 {
451 cd.m_cell_noise->noise_properties = CellNoiseProperties::invalid_value();
452 }
453 else
454 {
455 cd.m_cell_noise->noise_properties = CellNoiseProperties(blob->getObjVersion(), noise_tool->getNoiseType());
456 }
457
458 cd.m_cell_noise->luminosity = noise_tool->getLumi();
459
460 for (int cell = 0; cell < int(t_start); ++cell)
461 {
462 for (int gain_state = 0; gain_state < CaloRecGPU::NumGainStates; ++gain_state)
463 {
464 cd.m_cell_noise->noise[cell][gain_state] = noise_tool->larStorage()[(gain_state > 2 ? 0 : gain_state)][cell];
465 }
466 }
467 for (int cell = t_start; cell < int(t_end); ++cell)
468 {
469 for (int gain_state = 0; gain_state < CaloRecGPU::NumGainStates; ++gain_state)
470 {
471 cd.m_cell_noise->noise[cell][gain_state] = noise_tool->tileStorage()[gain_state][cell - t_start];
472 cd.m_cell_noise->double_gaussian_constants[0][cell - t_start][gain_state] = blob->getData(cell - t_start, gain_state, 2);
473 cd.m_cell_noise->double_gaussian_constants[1][cell - t_start][gain_state] = blob->getData(cell - t_start, gain_state, 3);
474 cd.m_cell_noise->double_gaussian_constants[2][cell - t_start][gain_state] = blob->getData(cell - t_start, gain_state, 4);
475 cd.m_cell_noise->double_gaussian_constants[3][cell - t_start][gain_state] = blob->getData(cell - t_start, gain_state, 1);
476 }
477 }
478 for (int cell = t_end; cell < NCaloCells; ++cell)
479 {
480 for (int gain_state = 0; gain_state < CaloRecGPU::NumGainStates; ++gain_state)
481 {
482 cd.m_cell_noise->noise[cell][gain_state] = 0;
483 }
484 }
485
486 auto after_noise = clock_type::now();
487
488 cd.sendToGPU(!(m_keepCPUData || keep_CPU_info));
489
490
491 auto after_send = clock_type::now();
492
493 if (m_measureTimes)
494 {
495 record_times(ctx.evt(),
496 time_cast(start, after_geo),
497 time_cast(after_geo, after_eta_phi),
498 time_cast(after_eta_phi, after_pairs),
499 time_cast(after_pairs, after_noise),
500 time_cast(after_noise, after_send)
501 );
502 }
503
504 return StatusCode::SUCCESS;
505
506}
507
509{
510
511 if (m_measureTimes)
512 {
513 print_times("Basic_Geometry Eta_Phi_Map_Finalize Pairs Noise Transfer_to_GPU", 5);
514 }
515 return StatusCode::SUCCESS;
516}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_WARNING(x)
Helpers for checking error return status codes and reporting errors.
Define macros for attributes used to control the static checker.
virtual StatusCode initialize() override
virtual StatusCode convert(CaloRecGPU::ConstantDataHolder &constant_data, const bool override_keep_CPU_info) const override
SG::ReadCondHandleKey< CaloDetDescrManager > m_caloMgrKey
Key for the CaloDetDescrManager in the Condition Store.
BasicConstantGPUDataExporter(const std::string &type, const std::string &name, const IInterface *parent)
Gaudi::Property< bool > m_keepCPUData
If true, do not delete the CPU version of the GPU-friendly data representation.
SG::ReadCondHandleKey< CaloNoise > m_noiseCDOKey
Key of the CaloNoise Conditions data object.
int sampling(const Identifier id) const
LAr field values (NOT_VALID == invalid request)
int get_neighbours(const IdentifierHash caloHash, const LArNeighbours::neighbourOption &option, std::vector< IdentifierHash > &neighbourList) const
access to hashes for neighbours return == 0 for neighbours found
void calo_cell_hash_range(const Identifier id, IdentifierHash &caloCellMin, IdentifierHash &caloCellMax) const
to loop on 'global' cell hashes of one sub-calorimeter alone
int region(const Identifier id) const
LAr field values (NOT_VALID == invalid request)
int calo_sample(const Identifier id) const
returns an int taken from Sampling enum and describing the subCalo to which the Id belongs.
Identifier cell_id(const int subCalo, const int barec_or_posneg, const int sampling_or_fcalmodule, const int region_or_dummy, const int eta, const int phi) const
Make a cell (== channel) ID from constituting fields and subCalo index; for (Mini)FCAL,...
Helper class for offline cell identifiers.
Definition CaloCell_ID.h:34
Class for storing a number of floats (Flt) and functions on those.
This class groups all DetDescr information related to a CaloCell.
const CaloDetDescrElement * get_element(const Identifier &cellId) const
get element by its identifier
This class provides the client interface for accessing the detector description information common to...
const CaloCell_ID * getCaloCell_ID() const
get calo cell ID helper
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
const CaloCondBlobFlt * getTileBlob() const
Definition CaloNoise.h:84
boost::multi_array< float, 2 > & larStorage()
Non-const accessor to underlying storage for filling:
Definition CaloNoise.h:72
NOISETYPE getNoiseType() const
Definition CaloNoise.h:88
float getLumi() const
Definition CaloNoise.h:86
boost::multi_array< float, 2 > & tileStorage()
Definition CaloNoise.h:73
Holds CPU and GPU versions of the geometry and cell noise information, which are assumed to be consta...
Definition DataHolders.h:27
static constexpr int from_region_enum(const int region)
static constexpr int from_subcalo_enum(const int subcalo)
static constexpr int from_intra_calorimeter_sampling_enum(const int sampling)
This is a "hash" representation of an Identifier.
Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration.
constexpr int NumSamplings
constexpr int NMaxNeighbours
constexpr int TileCellAfterEnd
constexpr int NumNeighOptions
constexpr int NCaloCells
constexpr int TileCellStart
constexpr int NumGainStates
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
static constexpr carrier invalid_value()
static constexpr carrier offset_delta(const int i)
Returns, for each i, what must be added to the offset to increase the stores numbers appropriately wh...
Definition NeighArr.h:144
Packs the calo sampling, the intra-calorimeter sampling, the subcalo, the region and whether the cell...