ATLAS Offline Software
Loading...
Searching...
No Matches
DataHolders.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
7#include <vector>
8#include <memory>
9
11#include "MacroHelpers.h"
12
15#include "TileEvent/TileCell.h"
16
18
19#include "boost/chrono/chrono.hpp"
20#include "boost/chrono/thread_clock.hpp"
21
22using namespace CaloRecGPU;
23
25{
28 if (clear_CPU)
29 {
30 m_cell_noise.clear();
31 m_geometry.clear();
32 }
33}
34
36{
37 switch (moment)
38 {
39 default:
40 return num_moments;
42 return 0;
44 return 1;
46 return 2;
48 return 3;
50 return 4;
52 return 5;
54 return 6;
56 return 7;
58 return 8;
60 return 9;
62 return 10;
64 return 11;
66 return 12;
68 return 13;
70 return 14;
72 return 15;
74 return 16;
76 return 17;
78 return 18;
80 return 19;
82 return 20;
84 return 21;
86 return 22;
88 return 23;
90 return 24;
92 return 25;
94 return 26;
96 return 27;
98 return 28;
100 return 29;
102 return 30;
104 return 31;
106 return 32;
108 return 33;
110 return 34;
112 return 35;
114 return 36;
116 return 37;
118 return 38;
120 return 39;
122 return 40;
124 return 41;
126 return 42;
128 return 43;
130 return 44;
132 return 45;
134 return 46;
136 return 47;
138 return 48;
140 return 49;
142 return 50;
144 return 51;
146 return 52;
148 return 53;
150 return 54;
152 return 55;
154 return 56;
156 return 57;
158 return 58;
160 return 59;
162 return 60;
164 return 61;
166 return 62;
168 return 63;
170 return 64;
172 return 65;
174 return 66;
176 return 67;
178 return 68;
180 return 69;
182 return 70;
184 return 71;
185 }
186}
187
189{
190 return array[moment_to_linear(moment)];
191}
192
194{
195 return array[moment_to_linear(moment)];
196}
197
199{
201
202 for (int i = 0; i < num_moments; ++i)
203 {
204 ret.array[i] = true;
205 }
206
207 return ret;
208}
209
210void CaloRecGPU::EventDataHolder::importCells(const void * p_cell_collection, const std::vector<int> & extra_cells_to_fill)
211{
212 const CaloCellContainer * cell_collection = static_cast<const CaloCellContainer *>(p_cell_collection);
213
214 m_cell_info.allocate();
215
216 auto export_cell = [&](const CaloCell * cell, const int hash_ID, const int index_inside)
217 {
218 const float energy = cell->energy();
219 const unsigned int gain = GainConversion::from_standard_gain(cell->gain());
220 m_cell_info->energy[index_inside] = energy;
221 m_cell_info->gain[index_inside] = gain;
222 m_cell_info->time[index_inside] = cell->time();
223
225 {
226 const TileCell * tile_cell = static_cast<const TileCell *>(cell);
227
228 m_cell_info->qualityProvenance[index_inside] = QualityProvenance{tile_cell->qual1(),
229 tile_cell->qual2(),
230 tile_cell->qbit1(),
231 tile_cell->qbit2()};
232 }
233 else
234 {
235 m_cell_info->qualityProvenance[index_inside] = QualityProvenance{cell->quality(), cell->provenance()};
236 }
237
238 m_cell_info->hashID[index_inside] = hash_ID;
239 m_cell_info->hashIDToCollection[hash_ID] = index_inside;
240 };
241
242 if (cell_collection->isOrderedAndComplete())
243 //Fast path: cell indices within the collection and identifierHashes match!
244 {
245 int cell_index = 0;
246 for (auto cell_it = cell_collection->begin(); cell_it != cell_collection->end(); ++cell_it, ++cell_index)
247 {
248 const CaloCell * cell = (*cell_it);
249 export_cell(cell, cell_index, cell_index);
250 }
251
252 m_cell_info->number = CaloRecGPU::NCaloCells;
253 m_cell_info->complete = true;
254 m_cell_info->all_cells_valid = true;
255 }
256 else if (cell_collection->isOrdered() && extra_cells_to_fill.size() > 0)
257 //Remediated: we know the missing cells, force them to be invalid.
258 //(Tests so far, on samples both oldish and newish, had 186986 and 187352 missing...)
259 {
260 int cell_index = 0;
261 size_t missing_cell_count = 0;
262
263 for (CaloCellContainer::const_iterator cell_it = cell_collection->begin(); cell_it != cell_collection->end(); ++cell_it, ++cell_index)
264 {
265 const CaloCell * cell = (*cell_it);
266
267 if (missing_cell_count < extra_cells_to_fill.size() && cell_index == extra_cells_to_fill[missing_cell_count])
268 {
269 --cell_it;
270 m_cell_info->gain[cell_index] = GainConversion::invalid_gain();
271 ++missing_cell_count;
272 m_cell_info->hashID[cell_index] = cell_index;
273 m_cell_info->hashIDToCollection[cell_index] = -1;
274 continue;
275 }
276 else
277 {
278 export_cell(cell, cell_index, cell_index);
279 }
280 }
281
282 m_cell_info->number = CaloRecGPU::NCaloCells;
283 m_cell_info->complete = true;
284 m_cell_info->all_cells_valid = false;
285 }
286 else
287 {
288 for (unsigned int cell_index = 0; cell_index < CaloRecGPU::NCaloCells; ++cell_index)
289 {
290 m_cell_info->hashIDToCollection[cell_index] = -1;
291 }
292
293 int index_inside = 0;
294
295 const auto cells_end = cell_collection->end();
296
297 for (CaloCellContainer::const_iterator cell_it = cell_collection->begin(); cell_it != cells_end; ++cell_it, ++index_inside)
298 {
299 CaloPrefetch::nextDDE(cell_it, cells_end, 2);
300 //May be adjusted later...
301
302 const CaloCell * cell = (*cell_it);
303
304 const int cell_index = cell->caloDDE()->calo_hash();
305 export_cell(cell, cell_index, index_inside);
306 }
307
308 m_cell_info->number = cell_collection->size();
309 m_cell_info->complete = false;
310 m_cell_info->all_cells_valid = true;
311 }
312}
313
314
315void CaloRecGPU::EventDataHolder::importClusters(const void * p_cluster_collection,
316 const MomentsOptionsArray & moments_to_add,
317 const bool output_tags,
318 const bool consider_shared_cells,
319 const bool output_moments,
320 const bool output_extra_moments,
321 const std::vector<int> & extra_cells_to_fill)
322{
323 const xAOD::CaloClusterContainer * cluster_collection = static_cast<const xAOD::CaloClusterContainer *>(p_cluster_collection);
324
325 m_clusters.allocate();
326
327 if (cluster_collection->size() > 0)
328 {
329 std::vector<int> real_cells_to_fill;
330
331 if (m_cell_info->number == CaloRecGPU::NCaloCells && !m_cell_info->all_cells_valid)
332 {
333 real_cells_to_fill.reserve(extra_cells_to_fill.size());
334
335 for (const int cell : extra_cells_to_fill)
336 {
337 if (m_cell_info->hashIDToCollection[cell] <= 0)
338 {
339 real_cells_to_fill.push_back(cell);
340 }
341 }
342 }
343
344 auto index_to_corrected_index = [&](const int index)
345 {
346 if (m_cell_info->all_cells_valid)
347 {
348 return index;
349 }
350
351 int ret = index;
352
353 for (const int cell : real_cells_to_fill)
354 {
355 ret += (index > cell);
356 }
357
358 return ret;
359 };
360
361 auto get_cell_tag = [&](const int index) -> tag_type &
362 {
363 if (output_tags)
364 {
365 return m_clusters->cells.tags[index];
366 }
367 else
368 {
369 return m_clusters->get_extra_cell_info(index);
370 }
371
372 };
373
374 for (int i = 0; i < CaloRecGPU::NCaloCells; ++i)
375 {
376 get_cell_tag(i) = ClusterTag::make_invalid_tag();
377 }
378
379 if (output_tags)
380 {
382 }
383 else
384 {
385 m_clusters->state = (output_moments ?
388 m_clusters->cellsPrefixSum[0] = 0;
389 }
390
391 m_clusters->has_deleted_clusters = false;
392
393 const auto cluster_end = cluster_collection->end();
394 auto cluster_iter = cluster_collection->begin();
395
396 int overall_cell_index = 0;
397
398 for (int cluster_number = 0; cluster_iter != cluster_end; ++cluster_iter, ++cluster_number)
399 {
400 const xAOD::CaloCluster * cluster = (*cluster_iter);
401 const CaloClusterCellLink * cell_links = cluster->getCellLinks();
402
403 m_clusters->clusterEnergy[cluster_number] = cluster->e();
404 m_clusters->clusterEt[cluster_number] = cluster->et();
405 m_clusters->clusterEta[cluster_number] = cluster->eta();
406 m_clusters->clusterPhi[cluster_number] = cluster->phi();
407
408 const int seed_cell_index = (cluster->cell_begin() != cluster->cell_end() ? cluster->cell_begin().index() : -1);
409
410 if (cluster->cell_begin() == cluster->cell_end())
411 {
412 m_clusters->has_deleted_clusters = true;
413 m_clusters->seedCellIndex[cluster_number] = -1;
414 }
415 else
416 {
417 m_clusters->seedCellIndex[cluster_number] = index_to_corrected_index(seed_cell_index);
418 }
419
420 for (auto it = cell_links->begin(); it != cell_links->end(); ++it)
421 {
422 const int cell_index_in_collection = index_to_corrected_index(it.index());
423 if (consider_shared_cells)
424 {
425 const float weight = it.weight();
426
427 uint32_t weight_as_int = 0;
428 std::memcpy(&weight_as_int, &weight, sizeof(float));
429 //On the platforms we expect to be running this, it should be fine.
430 //Still UB.
431 //With C++20, we could do that bit-cast thing.
432
433 if (weight_as_int == 0)
434 {
435 weight_as_int = 1;
436 //Subnormal,
437 //but just to distinguish from
438 //a non-shared cluster.
439 }
440
441 const ClusterTag other_tag = get_cell_tag(cell_index_in_collection);
442
443 const int other_index = other_tag.is_part_of_cluster() ? other_tag.cluster_index() : -1;
444
445 if (other_index < 0)
446 {
447 if (weight < 0.5f)
448 {
449 get_cell_tag(cell_index_in_collection) = ClusterTag::make_tag(cluster_number, weight_as_int, 0);
450 }
451 else
452 {
453 get_cell_tag(cell_index_in_collection) = ClusterTag::make_tag(cluster_number);
454 }
455 }
456 else if (weight > 0.5f)
457 {
458 get_cell_tag(cell_index_in_collection) = ClusterTag::make_tag(cluster_number, other_tag.secondary_cluster_weight(), other_index);
459 }
460 else if (weight == 0.5f)
461 //Unlikely, but...
462 {
463 const int max_cluster = cluster_number > other_index ? cluster_number : other_index;
464 const int min_cluster = cluster_number > other_index ? other_index : cluster_number;
465 get_cell_tag(cell_index_in_collection) = ClusterTag::make_tag(max_cluster, weight_as_int, min_cluster);
466 }
467 else /*if (weight < 0.5f)*/
468 {
469 get_cell_tag(cell_index_in_collection) = ClusterTag::make_tag(other_index, weight_as_int, cluster_number);
470 }
471
472 //All of this logic assumes a cell is shared by at most two clusters
473 //with weights such that w_1 + w_2 = 1.
474 //This is not necessarily valid with local calibrations.
475
476 }
477 else
478 {
479 get_cell_tag(cell_index_in_collection) = ClusterTag::make_tag(cluster_number);
480 }
481 }
482
483 if (!output_tags)
484 {
485 for (auto it = cell_links->begin(); it != cell_links->end(); ++it, ++overall_cell_index)
486 {
487 m_clusters->cells.indices[overall_cell_index] = index_to_corrected_index(it.index());
488 m_clusters->clusterIndices[overall_cell_index] = cluster_number;
489 m_clusters->cellWeights[overall_cell_index] = it.weight();
490 }
491
492 m_clusters->cellsPrefixSum[cluster_number + 1] = overall_cell_index;
493 }
494
495 if (output_moments)
496 {
497 for (int s = 0; s < NumSamplings; ++s)
498 {
499 m_clusters->moments.nCellSampling[s][cluster_number] = cluster->numberCellsInSampling(static_cast<CaloSampling::CaloSample>(s), false);
500 }
501
502 m_clusters->moments.nExtraCellSampling[cluster_number] = cluster->numberCellsInSampling(CaloSampling::EME2, true);
503
504 for (int s = 0; s < NumSamplings; ++s)
505 {
506 m_clusters->moments.energyPerSample[s][cluster_number] = cluster->eSample(static_cast<CaloSampling::CaloSample>(s));
507 }
508 for (int s = 0; s < NumSamplings; ++s)
509 {
510 m_clusters->moments.maxEPerSample[s][cluster_number] = cluster->energy_max(static_cast<CaloSampling::CaloSample>(s));
511 }
512 for (int s = 0; s < NumSamplings; ++s)
513 {
514 m_clusters->moments.maxEtaPerSample[s][cluster_number] = cluster->etamax(static_cast<CaloSampling::CaloSample>(s));
515 }
516 for (int s = 0; s < NumSamplings; ++s)
517 {
518 m_clusters->moments.maxPhiPerSample[s][cluster_number] = cluster->phimax(static_cast<CaloSampling::CaloSample>(s));
519 }
520 for (int s = 0; s < NumSamplings; ++s)
521 {
522 m_clusters->moments.etaPerSample[s][cluster_number] = cluster->etaSample(static_cast<CaloSampling::CaloSample>(s));
523 }
524 for (int s = 0; s < NumSamplings; ++s)
525 {
526 m_clusters->moments.phiPerSample[s][cluster_number] = cluster->phiSample(static_cast<CaloSampling::CaloSample>(s));
527 }
528
529 m_clusters->moments.time[cluster_number] = cluster->time();
530
531#define CALORECGPU_MOMENTS_INPUT_HELPER(VAR_NAME, PROPER_MOMENT, NORMAL_ASSIGN, IS_CALCULATED, MOMENT_NAME, ...) \
532 CRGPU_CONCAT(CRGPU_CONCAT(CALORECGPU_MOMENTS_INPUT_HELPER_, NORMAL_ASSIGN), IS_CALCULATED) (VAR_NAME, MOMENT_NAME)
533
534#define CALORECGPU_MOMENTS_INPUT_HELPER_11(VAR_NAME, MOMENT_NAME) \
535 if (moments_to_add[xAOD::CaloCluster:: MOMENT_NAME]) \
536 { \
537 m_clusters->moments. VAR_NAME [cluster_number] = cluster->getMomentValue(xAOD::CaloCluster:: MOMENT_NAME ); \
538 }
539
540#define CALORECGPU_MOMENTS_INPUT_HELPER_10(VAR_NAME, MOMENT_NAME) \
541 if (output_extra_moments && moments_to_add[xAOD::CaloCluster:: MOMENT_NAME]) \
542 { \
543 m_clusters->moments. VAR_NAME [cluster_number] = cluster->getMomentValue(xAOD::CaloCluster:: MOMENT_NAME ); \
544 }
545
546#define CALORECGPU_MOMENTS_INPUT_HELPER_00(...)
547#define CALORECGPU_MOMENTS_INPUT_HELPER_01(...)
548
550
551 double second_time_retriever = 0;
552
553 if (!cluster->retrieveMoment(xAOD::CaloCluster::SECOND_TIME, second_time_retriever))
554 {
555 m_clusters->moments.secondTime[cluster_number] = cluster->secondTime();
556 //Special casing for SECOND_TIME as it comes from CalculateKine instead,
557 //thus stored in a member variable instead of the moment.
558 }
559 else
560 {
561 m_clusters->moments.secondTime[cluster_number] = second_time_retriever;
562 }
563 }
564 }
565
566 m_clusters->number = cluster_collection->size();
567 m_clusters->number_cells = (output_tags ? m_cell_info->number : overall_cell_index);
568 }
569 else
570 {
572 m_clusters->has_deleted_clusters = false;
573 m_clusters->number = 0;
574 m_clusters->number_cells = 0;
575 }
576}
577
578template <class ReadStateFrom, class OutputCells, class InputCells, class CopyFunc>
579static void cell_transfer_helper(ReadStateFrom & state_holder,
580 OutputCells & output_cells,
581 InputCells & input_cells,
582 CopyFunc copy_func,
583 const bool full_copy,
585{
586 if (full_copy)
587 {
588 copy_func(output_cells, input_cells, sizeof(CaloRecGPU::CellInfoArr), stream);
589 }
590 else
591 {
592 copy_func(output_cells->gain,
593 input_cells->gain,
594 sizeof(unsigned char) * state_holder->number, stream);
595
596 copy_func(output_cells->energy,
597 input_cells->energy,
598 sizeof(float) * state_holder->number, stream);
599
600 copy_func(output_cells->time,
601 input_cells->time,
602 sizeof(float) * state_holder->number, stream);
603
604 copy_func(output_cells->qualityProvenance,
605 input_cells->qualityProvenance,
606 sizeof(QualityProvenance::carrier) * state_holder->number, stream);
607
608 copy_func(output_cells->hashID,
609 input_cells->hashID,
610 sizeof(int) * state_holder->number, stream);
611
612 copy_func(output_cells->hashIDToCollection,
613 input_cells->hashIDToCollection,
614 sizeof(int) * CaloRecGPU::NCaloCells, stream);
615
616 }
617}
618
619template <class ReadStateFrom, class OutputClusters, class InputClusters, class CopyFunc>
620static void cluster_transfer_helper_basic_info(ReadStateFrom & state_holder,
621 OutputClusters & output_clusters,
622 InputClusters & input_clusters,
623 CopyFunc copy_func,
625{
626
627 if (state_holder->has_basic_info())
628 {
629 copy_func(output_clusters->clusterEnergy,
630 input_clusters->clusterEnergy,
631 sizeof(float) * state_holder->number, stream);
632
633 copy_func(output_clusters->clusterEt,
634 input_clusters->clusterEt,
635 sizeof(float) * state_holder->number, stream);
636
637 copy_func(output_clusters->clusterEta,
638 input_clusters->clusterEta,
639 sizeof(float) * state_holder->number, stream);
640
641 copy_func(output_clusters->clusterPhi,
642 input_clusters->clusterPhi,
643 sizeof(float) * state_holder->number, stream);
644
645 copy_func(output_clusters->seedCellIndex,
646 input_clusters->seedCellIndex,
647 sizeof(int) * state_holder->number, stream);
648 }
649
650}
651
652template <class ReadStateFrom, class OutputClusters, class InputClusters, class CopyFunc>
653static void cluster_transfer_helper_cell_assignment(ReadStateFrom & state_holder,
654 OutputClusters & output_clusters,
655 InputClusters & input_clusters,
656 CopyFunc copy_func,
658 const int num_total_cells = NCaloCells)
659{
660
661 if (state_holder->has_cells_per_cluster())
662 {
663 copy_func(output_clusters->cellsPrefixSum,
664 input_clusters->cellsPrefixSum,
665 sizeof(int) * (state_holder->number + 1), stream);
666
667 copy_func(output_clusters->cells.indices,
668 input_clusters->cells.indices,
669 sizeof(int) * state_holder->number_cells, stream);
670
671 copy_func(output_clusters->cellWeights,
672 input_clusters->cellWeights,
673 sizeof(float) * state_holder->number_cells, stream);
674
675 copy_func(output_clusters->clusterIndices,
676 input_clusters->clusterIndices,
677 sizeof(int) * state_holder->number_cells, stream);
678
679 int remaining_cells = num_total_cells;
680
681#define CALORECGPU_MOMENTS_EXTRA_TAGS_HELPER(VARNAME) \
682 if (remaining_cells > 0) \
683 { \
684 constexpr int max_size_per_array = (sizeof(float) * NMaxClusters)/sizeof(tag_type); \
685 copy_func(output_clusters->moments. VARNAME, \
686 input_clusters->moments. VARNAME, \
687 sizeof(tag_type) * std::min(remaining_cells, max_size_per_array), stream); \
688 remaining_cells -= max_size_per_array; \
689 } (void) 0 \
690
697
698 }
699 else if (state_holder->state != CaloRecGPU::ClusterInformationState::None)
700 {
701 copy_func(output_clusters->cells.tags,
702 input_clusters->cells.tags,
703 sizeof(tag_type) * state_holder->number_cells, stream);
704
705 }
706}
707
708template <class ReadStateFrom, class OutputClusters, class InputClusters, class CopyFunc>
709static void cluster_transfer_helper_moments(ReadStateFrom & state_holder,
710 OutputClusters & output_clusters,
711 InputClusters & input_clusters,
712 const MomentsOptionsArray & moments_to_add,
713 CopyFunc copy_func,
715{
716 if (state_holder->has_moments())
717 {
718 auto moments_copy_helper = [&](auto & output_arr, const auto & input_arr)
719 {
720 if constexpr(std::is_pointer_v<std::decay_t<decltype(*input_arr)>>)
721 //This is a per-sampling array.
722 {
723 for (int i = 0; i < CaloRecGPU::NumSamplings; ++i)
724 {
725 copy_func(output_arr[i],
726 input_arr[i],
727 sizeof(decltype(input_arr[0][0])) * state_holder->number,
728 stream);
729 }
730 }
731 else
732 {
733 copy_func(output_arr,
734 input_arr,
735 sizeof(decltype(input_arr[0])) * state_holder->number,
736 stream);
737 }
738 };
739
740#define CALORECGPU_MOMENTS_TO_GPU_HELPER(VAR_NAME, PROPER_MOMENT, NORMAL_ASSIGN, IS_CALCULATED, MOMENT_NAME, ...) \
741 CRGPU_CONCAT(CRGPU_CONCAT(CALORECGPU_MOMENTS_TO_GPU_HELPER_, PROPER_MOMENT), IS_CALCULATED) (VAR_NAME, MOMENT_NAME)
742
743#define CALORECGPU_MOMENTS_TO_GPU_HELPER_11(VAR_NAME, MOMENT_NAME) \
744 if (moments_to_add[xAOD::CaloCluster:: MOMENT_NAME ]) \
745 { \
746 moments_copy_helper(output_clusters->moments. VAR_NAME, input_clusters->moments. VAR_NAME); \
747 }
748
749#define CALORECGPU_MOMENTS_TO_GPU_HELPER_10(VAR_NAME, MOMENT_NAME) \
750 if ( state_holder->state == CaloRecGPU::ClusterInformationState::WithExtraMoments && \
751 moments_to_add[xAOD::CaloCluster:: MOMENT_NAME ] ) \
752 { \
753 moments_copy_helper(output_clusters->moments. VAR_NAME, input_clusters->moments. VAR_NAME); \
754 }
755
756#define CALORECGPU_MOMENTS_TO_GPU_HELPER_01( VAR_NAME, MOMENT_NAME) \
757 moments_copy_helper(output_clusters->moments. VAR_NAME, input_clusters->moments. VAR_NAME);
758
759#define CALORECGPU_MOMENTS_TO_GPU_HELPER_00(PROPER_MOMENT, VAR_NAME, MOMENT_NAME) \
760 if (state_holder->state == CaloRecGPU::ClusterInformationState::WithExtraMoments) \
761 { \
762 moments_copy_helper(output_clusters->moments. VAR_NAME, input_clusters->moments. VAR_NAME); \
763 }
764
766 }
767}
768
769template <class ReadStateFrom, class OutputClusters, class InputClusters, class CopyFunc>
770static void cluster_transfer_helper(ReadStateFrom & state_holder,
771 OutputClusters & output_clusters,
772 InputClusters & input_clusters,
773 const MomentsOptionsArray & moments_to_add,
774 CopyFunc copy_func,
775 const bool full_copy,
777 const int num_total_cells = CaloRecGPU::NCaloCells)
778{
779 if (full_copy)
780 {
781 copy_func(output_clusters, input_clusters, sizeof(CaloRecGPU::ClusterInfoArr), stream);
782 }
783 else
784 {
785 cluster_transfer_helper_basic_info(state_holder, output_clusters, input_clusters, copy_func, stream);
786
787 cluster_transfer_helper_cell_assignment(state_holder, output_clusters, input_clusters, copy_func, stream, num_total_cells);
788
789 cluster_transfer_helper_moments(state_holder, output_clusters, input_clusters, moments_to_add, copy_func, stream);
790 }
791}
792
793
794void CaloRecGPU::EventDataHolder::sendToGPU(const MomentsOptionsArray & moments_to_add,
795 const bool full_copy,
796 const bool clear_CPU,
797 const bool synchronize,
798 CaloRecGPU::CUDA_Helpers::CUDAStreamPtrHolder stream)
799{
800 m_cell_info_dev.allocate();
801 m_clusters_dev.allocate();
802
803 if (!full_copy)
804 {
805 CaloRecGPU::CUDA_Helpers::CPU_to_GPU_async(static_cast<CellBaseInfo *>(m_cell_info_dev),
806 static_cast<const CellBaseInfo *>(m_cell_info),
807 sizeof(CellBaseInfo), stream);
808
809 CaloRecGPU::CUDA_Helpers::CPU_to_GPU_async(static_cast<ClusterBaseInfo *>(m_clusters_dev),
810 static_cast<const ClusterBaseInfo *>(m_clusters),
811 sizeof(ClusterBaseInfo), stream);
812
813 }
814
815 cell_transfer_helper(m_cell_info, m_cell_info_dev, m_cell_info,
817
818 cluster_transfer_helper(m_clusters, m_clusters_dev, m_clusters, moments_to_add,
820 m_cell_info->number);
821
822 if (clear_CPU)
823 {
825
826 m_clusters.clear();
827 m_cell_info.clear();
828 }
829 else if (synchronize)
830 {
832 }
833}
834
835void CaloRecGPU::EventDataHolder::returnToCPU(const MomentsOptionsArray & moments_to_add,
836 const bool full_copy,
837 const bool clear_GPU,
838 const bool synchronize,
839 CaloRecGPU::CUDA_Helpers::CUDAStreamPtrHolder stream,
840 const bool also_return_cells)
841{
842 if (also_return_cells)
843 {
844 m_cell_info.allocate();
845 }
846 m_clusters.allocate();
847
848 if (!full_copy)
849 {
850 if (also_return_cells)
851 {
853 static_cast<CellBaseInfo *>(m_cell_info_dev),
854 sizeof(CellBaseInfo), stream);
855 }
856
858 static_cast<ClusterBaseInfo *>(m_clusters_dev),
859 sizeof(ClusterBaseInfo), stream);
860
862
863 }
864
865 if (also_return_cells)
866 {
867 cell_transfer_helper(m_cell_info, m_cell_info, m_cell_info_dev,
869 }
870
871 cluster_transfer_helper(m_clusters, m_clusters, m_clusters_dev, moments_to_add,
873
874 if (clear_GPU)
875 {
877
878 m_clusters_dev.clear();
879 m_cell_info_dev.clear();
880 }
881 else if (synchronize)
882 {
884 }
885}
886
887//clusters->number must be available!
888//if skip_validation is true, clusters->seedCellIndex must also be available.
890 std::vector<std::unique_ptr<CaloClusterCellLink>> & cell_links,
891 const DataLink<CaloCellContainer> & cell_collection_link,
892 const bool skip_validation)
893{
894 cell_links.reserve(clusters->number);
895
896 for (int i = 0; i < clusters->number; ++i)
897 {
898 if (skip_validation || clusters->seedCellIndex[i] >= 0)
899 {
900 cell_links.emplace_back(std::make_unique<CaloClusterCellLink>(cell_collection_link));
901 cell_links.back()->reserve(256);
902 //To be adjusted.
903 }
904 else
905 {
906 cell_links.emplace_back(nullptr);
907 //The excluded clusters don't have any cells.
908 }
909 }
910}
911
912//The CPU cells must be available!
913//The cluster status and number of cells must be available!
914//
915static void export_cluster_process_cells(const ClusterInfoArr * clusters,
916 const CellInfoArr * cells,
917 std::vector<std::unique_ptr<CaloClusterCellLink>> & cell_links,
918 const std::vector<int> & extra_cells_to_fill)
919{
920
921 std::vector<int> real_cells_to_fill;
922
923 if (cells->number == CaloRecGPU::NCaloCells && !cells->all_cells_valid)
924 {
925 real_cells_to_fill.reserve(extra_cells_to_fill.size());
926
927 for (const int cell : extra_cells_to_fill)
928 {
929 if (cells->hashIDToCollection[cell] <= 0)
930 {
931 real_cells_to_fill.push_back(cell);
932 }
933 }
934 }
935
936 auto corrected_index_to_real_index = [&](const int index)
937 {
938 if (cells->all_cells_valid)
939 {
940 return index;
941 }
942
943 int ret = index;
944
945 for (const int cell : real_cells_to_fill)
946 {
947 ret -= (index > cell);
948 }
949
950 return ret;
951 };
952
953 if (clusters->has_cells_per_cluster())
954 {
955 for (int i = 0; i < clusters->number_cells; ++i)
956 {
957 std::unique_ptr<CaloClusterCellLink> & this_link_ptr = cell_links[clusters->clusterIndices[i]];
958 if (this_link_ptr)
959 //This should always be true at this stage,
960 //but guarding against any potentially invalidated clusters.
961 {
962 this_link_ptr->addCell(corrected_index_to_real_index(clusters->cells.indices[i]), clusters->cellWeights[i]);
963 }
964 }
965 }
966 else
967 {
968 for (int i = 0; i < clusters->number; ++i)
969 {
970 if (cell_links[i])
971 {
972 cell_links[i]->addCell(corrected_index_to_real_index(clusters->seedCellIndex[i]), 1);
973 //Seed cells aren't shared, by construction.
974 }
975 }
976
977 for (int i = 0; i < clusters->number_cells; ++i)
978 {
979 const ClusterTag this_tag = clusters->cells.tags[i];
980
981 if (this_tag.is_part_of_cluster())
982 {
983 const int this_cell_index = corrected_index_to_real_index(i);
984
985 const int this_index = this_tag.cluster_index();
986 const int32_t weight_pattern = this_tag.secondary_cluster_weight();
987
988 float tempf = 1.0f;
989
990 std::memcpy(&tempf, &weight_pattern, sizeof(float));
991
992 const float reverse_weight = tempf;
993
994 const float this_weight = 1.0f - reverse_weight;
995
996 if (cell_links[this_index] && clusters->seedCellIndex[this_index] != i)
997 {
998 cell_links[this_index]->addCell(this_cell_index, this_weight);
999 }
1000
1001 if (this_tag.is_shared_between_clusters())
1002 {
1003 const int other_index = this_tag.secondary_cluster_index();
1004 if (cell_links[other_index] && clusters->seedCellIndex[other_index] != i)
1005 {
1006 cell_links[other_index]->addCell(this_cell_index, reverse_weight);
1007 }
1008 }
1009 }
1010 }
1011 }
1012}
1013
1014static void export_cluster_sort(const ClusterInfoArr * clusters,
1015 std::vector<int> & cluster_order,
1016 const bool really_sort)
1017{
1018 if (really_sort)
1019 {
1020 cluster_order.resize(clusters->number);
1021
1022 std::iota(cluster_order.begin(), cluster_order.end(), 0);
1023
1024 std::sort(cluster_order.begin(), cluster_order.end(), [&](const int a, const int b) -> bool
1025 {
1026 const bool a_valid = clusters->seedCellIndex[a] >= 0;
1027 const bool b_valid = clusters->seedCellIndex[b] >= 0;
1028 if (a_valid && b_valid)
1029 {
1030 return (clusters->clusterEt[a] > clusters->clusterEt[b]);
1031 }
1032 else if (a_valid)
1033 {
1034 return true;
1035 }
1036 else if (b_valid)
1037 {
1038 return false;
1039 }
1040 else
1041 {
1042 return b > a;
1043 }
1044 } );
1045 }
1046 else
1047 {
1048 cluster_order.clear();
1049 }
1050}
1051
1053 xAOD::CaloClusterContainer * cluster_collection,
1054 std::vector<std::unique_ptr<CaloClusterCellLink>> & cell_links,
1055 std::vector<int> & cluster_order,
1056 const bool save_uncalibrated)
1057{
1058 const int total_size = (cluster_order.size() ? cluster_order.size() : clusters->number);
1059 for (int i = 0; i < total_size; ++i)
1060 {
1061 const int cluster_index = (cluster_order.size() ? cluster_order[i] : i);
1062
1063 if (cell_links[cluster_index] != nullptr && cell_links[cluster_index]->size() > 0)
1064 {
1065 xAOD::CaloCluster * cluster = new xAOD::CaloCluster();
1066 cluster_collection->push_back(cluster);
1067
1068 cluster->addCellLink(std::move(cell_links[cluster_index]));
1069
1070 if (clusters->has_basic_info())
1071 {
1072
1073 cluster->setE (clusters->clusterEnergy[cluster_index]);
1074 cluster->setEta(clusters->clusterEta [cluster_index]);
1075 cluster->setPhi(clusters->clusterPhi [cluster_index]);
1076
1077 if (save_uncalibrated)
1078 {
1079 cluster->setRawE(cluster->calE());
1080 cluster->setRawEta(cluster->calEta());
1081 cluster->setRawPhi(cluster->calPhi());
1082 cluster->setRawM(cluster->calM());
1083 }
1084 }
1085 }
1086 }
1087}
1088
1089static void export_cluster_fill_moments(const ClusterInfoArr * clusters,
1090 xAOD::CaloClusterContainer * cluster_collection,
1091 std::vector<int> & cluster_order,
1092 const MomentsOptionsArray & moments_to_add,
1093 const bool output_extra_moments)
1094{
1095 if (clusters->has_moments())
1096 {
1097 const int total_size = (cluster_order.size() ? cluster_order.size() : clusters->number);
1098 for (int i = 0; i < total_size; ++i)
1099 {
1100 const int cluster_index = (cluster_order.size() ? cluster_order[i] : i);
1101
1102 xAOD::CaloCluster * cluster = (*cluster_collection)[cluster_index];
1103
1104 cluster->clearSamplingData();
1105
1106 uint32_t sampling_pattern = 0;
1107 for (int sampl = 0; sampl < NumSamplings; ++sampl)
1108 {
1109 const int cells_per_sampling = clusters->moments.nCellSampling[sampl][cluster_index];
1110
1111 if (cells_per_sampling > 0)
1112 {
1113 sampling_pattern |= (0x1U << sampl);
1114 }
1115 }
1116
1117 if (clusters->moments.nExtraCellSampling[cluster_index] > 0)
1118 {
1119 sampling_pattern |= (1U << static_cast<unsigned int>(CaloSampling::EME2));
1120 }
1121
1122 cluster->setSamplingPattern(sampling_pattern);
1123
1124 for (int s = 0; s < NumSamplings; ++s)
1125 {
1126 if (sampling_pattern & (1U << s))
1127 {
1128 cluster->setNumberCellsInSampling(static_cast<CaloSampling::CaloSample>(s), clusters->moments.nCellSampling[s][cluster_index], false);
1129 }
1130 }
1131
1132 if (clusters->moments.nExtraCellSampling[cluster_index] > 0)
1133 {
1134 cluster->setNumberCellsInSampling(CaloSampling::EME2, clusters->moments.nExtraCellSampling[cluster_index], true);
1135 }
1136
1137 for (int s = 0; s < NumSamplings; ++s)
1138 {
1139 if (sampling_pattern & (1U << s))
1140 {
1141 cluster->setEnergy(static_cast<CaloSampling::CaloSample>(s), clusters->moments.energyPerSample[s][cluster_index]);
1142 }
1143 }
1144 for (int s = 0; s < NumSamplings; ++s)
1145 {
1146 if (sampling_pattern & (1U << s))
1147 {
1148 cluster->setEmax(static_cast<CaloSampling::CaloSample>(s), clusters->moments.maxEPerSample[s][cluster_index]);
1149 }
1150 }
1151 for (int s = 0; s < NumSamplings; ++s)
1152 {
1153 if (sampling_pattern & (1U << s))
1154 {
1155 cluster->setEtamax(static_cast<CaloSampling::CaloSample>(s), clusters->moments.maxEtaPerSample[s][cluster_index] );
1156 }
1157 }
1158 for (int s = 0; s < NumSamplings; ++s)
1159 {
1160 if (sampling_pattern & (1U << s))
1161 {
1162 cluster->setPhimax(static_cast<CaloSampling::CaloSample>(s), clusters->moments.maxPhiPerSample[s][cluster_index]);
1163 }
1164 }
1165 for (int s = 0; s < NumSamplings; ++s)
1166 {
1167 if (sampling_pattern & (1U << s))
1168 {
1169 cluster->setEta(static_cast<CaloSampling::CaloSample>(s), clusters->moments.etaPerSample[s][cluster_index]);
1170 }
1171 }
1172 for (int s = 0; s < NumSamplings; ++s)
1173 {
1174 if (sampling_pattern & (1U << s))
1175 {
1176 cluster->setPhi(static_cast<CaloSampling::CaloSample>(s), clusters->moments.phiPerSample[s][cluster_index]);
1177 }
1178 }
1179
1180 cluster->setTime(clusters->moments.time[cluster_index]);
1181 cluster->setSecondTime(clusters->moments.secondTime[cluster_index]);
1182
1183#define CALORECGPU_MOMENTS_OUTPUT_HELPER(VAR_NAME, PROPER_MOMENT, NORMAL_ASSIGN, IS_CALCULATED, MOMENT_NAME, ...) \
1184 CRGPU_CONCAT(CRGPU_CONCAT(CALORECGPU_MOMENTS_OUTPUT_HELPER_, NORMAL_ASSIGN), IS_CALCULATED) (VAR_NAME, MOMENT_NAME)
1185
1186#define CALORECGPU_MOMENTS_OUTPUT_HELPER_11(VAR_NAME, MOMENT_NAME) \
1187 if (moments_to_add[xAOD::CaloCluster:: MOMENT_NAME]) \
1188 { \
1189 cluster->insertMoment(xAOD::CaloCluster:: MOMENT_NAME , clusters->moments. VAR_NAME [cluster_index]); \
1190 }
1191
1192#define CALORECGPU_MOMENTS_OUTPUT_HELPER_10(VAR_NAME, MOMENT_NAME) \
1193 if (output_extra_moments && moments_to_add[xAOD::CaloCluster:: MOMENT_NAME]) \
1194 { \
1195 cluster->insertMoment(xAOD::CaloCluster:: MOMENT_NAME , clusters->moments. VAR_NAME [cluster_index]); \
1196 }
1197
1198#define CALORECGPU_MOMENTS_OUTPUT_HELPER_00(...)
1199#define CALORECGPU_MOMENTS_OUTPUT_HELPER_01(...)
1200
1202 }
1203 }
1204}
1205
1206
1207void CaloRecGPU::EventDataHolder::exportClusters(void * p_cluster_collection,
1208 const void * p_cell_collection_link,
1209 const MomentsOptionsArray & moments_to_add,
1210 bool sort_clusters,
1211 const bool save_uncalibrated,
1212 const bool output_extra_moments,
1213 const std::vector<int> & extra_cells_to_fill,
1214 size_t * time_measurements)
1215{
1216 using clock_type = boost::chrono::thread_clock;
1217 auto time_cast = [](const auto & before, const auto & after)
1218 {
1219 return boost::chrono::duration_cast<boost::chrono::microseconds>(after - before).count();
1220 };
1221
1222 xAOD::CaloClusterContainer * cluster_collection = static_cast<xAOD::CaloClusterContainer *>(p_cluster_collection);
1223 const DataLink<CaloCellContainer> & cell_collection_link = *(static_cast<const DataLink<CaloCellContainer> *>(p_cell_collection_link));
1224
1225 const auto start = clock_type::now();
1226
1227 std::vector<std::unique_ptr<CaloClusterCellLink>> cell_links;
1228
1229 export_cluster_initialize_links(m_clusters, cell_links, cell_collection_link, false);
1230
1231 const auto after_link_creation = clock_type::now();
1232
1233 export_cluster_process_cells(m_clusters, m_cell_info, cell_links, extra_cells_to_fill);
1234
1235 const auto after_cell_processing = clock_type::now();
1236
1237 std::vector<int> cluster_order;
1238
1239 export_cluster_sort(m_clusters, cluster_order, sort_clusters);
1240
1241 const auto after_sorting = clock_type::now();
1242
1243 export_cluster_fill_cells_and_basic_info(m_clusters, cluster_collection, cell_links, cluster_order, save_uncalibrated);
1244
1245 const auto after_basic_info = clock_type::now();
1246
1247 export_cluster_fill_moments(m_clusters, cluster_collection, cluster_order, moments_to_add, output_extra_moments);
1248
1249 const auto after_moments = clock_type::now();
1250
1251 if (time_measurements)
1252 {
1253 time_measurements[0] = time_cast(start, after_link_creation);
1254 time_measurements[1] = time_cast(after_link_creation, after_cell_processing);
1255 time_measurements[2] = time_cast(after_cell_processing, after_sorting);
1256 time_measurements[3] = time_cast(after_sorting, after_basic_info);
1257 time_measurements[4] = time_cast(after_basic_info, after_moments);
1258 }
1259}
1260
1261
1263 const void * p_cell_collection_link,
1264 const MomentsOptionsArray & moments_to_add,
1265 bool sort_clusters,
1266 const bool save_uncalibrated,
1267 const bool output_extra_moments,
1268 const std::vector<int> & extra_cells_to_fill,
1269 size_t * time_measurements,
1271{
1272 using clock_type = boost::chrono::thread_clock;
1273 auto time_cast = [](const auto & before, const auto & after)
1274 {
1275 return boost::chrono::duration_cast<boost::chrono::microseconds>(after - before).count();
1276 };
1277
1278 xAOD::CaloClusterContainer * cluster_collection = static_cast<xAOD::CaloClusterContainer *>(p_cluster_collection);
1279 const DataLink<CaloCellContainer> & cell_collection_link = *(static_cast<const DataLink<CaloCellContainer> *>(p_cell_collection_link));
1280
1281 const auto start = clock_type::now();
1282
1283 m_clusters.allocate();
1284
1286 static_cast<const ClusterBaseInfo *>(m_clusters_dev),
1287 sizeof(ClusterBaseInfo), stream);
1288
1290
1291 const auto after_first_transfer = clock_type::now();
1292
1294
1295 std::vector<std::unique_ptr<CaloClusterCellLink>> cell_links;
1296
1297 export_cluster_initialize_links(m_clusters, cell_links, cell_collection_link, true);
1298
1299 const auto after_link_creation = clock_type::now();
1300
1302
1304
1305 export_cluster_process_cells(m_clusters, m_cell_info, cell_links, extra_cells_to_fill);
1306
1307 const auto after_cell_processing = clock_type::now();
1308
1309 std::vector<int> cluster_order;
1310
1311 export_cluster_sort(m_clusters, cluster_order, sort_clusters);
1312
1313 const auto after_sorting = clock_type::now();
1314
1316
1318
1319 export_cluster_fill_cells_and_basic_info(m_clusters, cluster_collection, cell_links, cluster_order, save_uncalibrated);
1320
1321 const auto after_basic_info = clock_type::now();
1322
1324
1325 export_cluster_fill_moments(m_clusters, cluster_collection, cluster_order, moments_to_add, output_extra_moments);
1326
1327 const auto after_moments = clock_type::now();
1328
1329 if (time_measurements)
1330 {
1331 time_measurements[0] = time_cast(start, after_first_transfer);
1332 time_measurements[1] = time_cast(after_first_transfer, after_link_creation);
1333 time_measurements[2] = time_cast(after_link_creation, after_cell_processing);
1334 time_measurements[3] = time_cast(after_cell_processing, after_sorting);
1335 time_measurements[4] = time_cast(after_sorting, after_basic_info);
1336 time_measurements[5] = time_cast(after_basic_info, after_moments);
1337 }
1338}
1339
1341{
1342 m_cell_info.allocate();
1343 m_clusters.allocate();
1344
1345 if (also_GPU)
1346 {
1347 m_cell_info_dev.allocate();
1348 m_clusters_dev.allocate();
1349 }
1350}
1351
1353{
1354 m_cell_info_dev.clear();
1355 m_clusters_dev.clear();
1356}
Definition of CaloDetDescrManager.
#define CALORECGPU_MOMENTS_INPUT_HELPER(VAR_NAME, PROPER_MOMENT, NORMAL_ASSIGN, IS_CALCULATED, MOMENT_NAME,...)
static void cluster_transfer_helper_moments(ReadStateFrom &state_holder, OutputClusters &output_clusters, InputClusters &input_clusters, const MomentsOptionsArray &moments_to_add, CopyFunc copy_func, CaloRecGPU::CUDA_Helpers::CUDAStreamPtrHolder stream)
static void export_cluster_fill_moments(const ClusterInfoArr *clusters, xAOD::CaloClusterContainer *cluster_collection, std::vector< int > &cluster_order, const MomentsOptionsArray &moments_to_add, const bool output_extra_moments)
#define CALORECGPU_MOMENTS_OUTPUT_HELPER(VAR_NAME, PROPER_MOMENT, NORMAL_ASSIGN, IS_CALCULATED, MOMENT_NAME,...)
static void export_cluster_fill_cells_and_basic_info(const ClusterInfoArr *clusters, xAOD::CaloClusterContainer *cluster_collection, std::vector< std::unique_ptr< CaloClusterCellLink > > &cell_links, std::vector< int > &cluster_order, const bool save_uncalibrated)
static void cell_transfer_helper(ReadStateFrom &state_holder, OutputCells &output_cells, InputCells &input_cells, CopyFunc copy_func, const bool full_copy, CaloRecGPU::CUDA_Helpers::CUDAStreamPtrHolder stream)
static void export_cluster_sort(const ClusterInfoArr *clusters, std::vector< int > &cluster_order, const bool really_sort)
static void cluster_transfer_helper(ReadStateFrom &state_holder, OutputClusters &output_clusters, InputClusters &input_clusters, const MomentsOptionsArray &moments_to_add, CopyFunc copy_func, const bool full_copy, CaloRecGPU::CUDA_Helpers::CUDAStreamPtrHolder stream, const int num_total_cells=CaloRecGPU::NCaloCells)
static void cluster_transfer_helper_cell_assignment(ReadStateFrom &state_holder, OutputClusters &output_clusters, InputClusters &input_clusters, CopyFunc copy_func, CaloRecGPU::CUDA_Helpers::CUDAStreamPtrHolder stream, const int num_total_cells=NCaloCells)
#define CALORECGPU_MOMENTS_EXTRA_TAGS_HELPER(VARNAME)
#define CALORECGPU_MOMENTS_TO_GPU_HELPER(VAR_NAME, PROPER_MOMENT, NORMAL_ASSIGN, IS_CALCULATED, MOMENT_NAME,...)
static void export_cluster_process_cells(const ClusterInfoArr *clusters, const CellInfoArr *cells, std::vector< std::unique_ptr< CaloClusterCellLink > > &cell_links, const std::vector< int > &extra_cells_to_fill)
static void cluster_transfer_helper_basic_info(ReadStateFrom &state_holder, OutputClusters &output_clusters, InputClusters &input_clusters, CopyFunc copy_func, CaloRecGPU::CUDA_Helpers::CUDAStreamPtrHolder stream)
static void export_cluster_initialize_links(const ClusterInfoArr *clusters, std::vector< std::unique_ptr< CaloClusterCellLink > > &cell_links, const DataLink< CaloCellContainer > &cell_collection_link, const bool skip_validation)
#define CALORECGPU_FORALLMOMENTS_INSTANTIATE(MACRO,...)
static Double_t a
if(febId1==febId2)
Contains some helpful macros to help with repetitive code...
Container class for CaloCell.
bool isOrdered() const
tell wether container is ordered
bool isOrderedAndComplete() const
tell wether container is complete and in order
Data object for each calorimeter readout cell.
Definition CaloCell.h:57
CaloRecGPU::Helpers::CPU_object< CaloRecGPU::GeometryArr > m_geometry
Definition DataHolders.h:32
void sendToGPU(const bool clear_CPU=true)
CaloRecGPU::Helpers::CUDA_object< CaloRecGPU::CellNoiseArr > m_cell_noise_dev
Definition DataHolders.h:38
CaloRecGPU::Helpers::CUDA_object< CaloRecGPU::GeometryArr > m_geometry_dev
Definition DataHolders.h:36
CaloRecGPU::Helpers::CPU_object< CaloRecGPU::CellNoiseArr > m_cell_noise
Definition DataHolders.h:34
CaloRecGPU::Helpers::CUDA_pinned_CPU_object< CaloRecGPU::CellInfoArr > m_cell_info
CaloRecGPU::Helpers::CUDA_object< CaloRecGPU::CellInfoArr > m_cell_info_dev
CaloRecGPU::Helpers::CUDA_pinned_CPU_object< CaloRecGPU::ClusterInfoArr > m_clusters
void allocate(const bool also_GPU=true)
CaloRecGPU::Helpers::CUDA_object< CaloRecGPU::ClusterInfoArr > m_clusters_dev
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...
static constexpr GainType from_standard_gain(const int gain)
static constexpr GainType invalid_gain()
DataModel_detail::const_iterator< DataVector > const_iterator
Definition DataVector.h:838
value_type push_back(value_type pElem)
Add an element to the end of the collection.
const_iterator end() const noexcept
Return a const_iterator pointing past the end of the collection.
const_iterator begin() const noexcept
Return a const_iterator pointing at the beginning of the collection.
size_type size() const noexcept
Returns the number of elements in the collection.
uint8_t qual1(void) const
get quality of first PMT (data member)
Definition TileCell.h:197
uint8_t qbit2(void) const
get quality bits of second PMT (data member)
Definition TileCell.h:206
uint8_t qual2(void) const
get quality of second PMT (data member)
Definition TileCell.h:200
uint8_t qbit1(void) const
get quality bits of first PMT (data member)
Definition TileCell.h:203
void setRawEta(flt_t)
Set for signal state UNCALIBRATED.
bool retrieveMoment(MomentType type, double &value) const
Retrieve individual moment.
void setRawPhi(flt_t)
Set for signal state UNCALIBRATED.
void setSecondTime(flt_t stime)
Set second moment of cell timing distribution.
bool setPhi(const CaloSample sampling, const float phi)
Set in a given sampling. Returns false if the sample isn't part of the cluster.
const CaloClusterCellLink * getCellLinks() const
Get a pointer to the CaloClusterCellLink object (const version)
flt_t calPhi() const
Get in signal state CALIBRATED.
float phiSample(const CaloSample sampling) const
Retrieve barycenter in a given sample.
float energy_max(const CaloSample sampling) const
Retrieve maximum cell energy in given sampling.
int numberCellsInSampling(const CaloSample samp, bool isInnerWheel=false) const
Returns number of cells in given sampling.
void addCellLink(CaloClusterCellLink *CCCL)
flt_t time() const
Access cluster time.
void setRawE(flt_t)
Set Energy for signal state UNCALIBRATED.
void setRawM(flt_t)
Set mass for singal state UNCALIBRATED.
virtual double eta() const
The pseudorapidity ( ) of the particle.
void setTime(flt_t)
Set cluster time.
virtual double e() const
The total energy of the particle.
bool setPhimax(const CaloSample sampling, const float phiMax)
Set the phi of the cell with the highest energy in a particular sampling.
const_cell_iterator cell_end() const
bool setEta(const CaloSample sampling, const float eta)
Set in a given sampling. Returns false if the sample isn't part of the cluster.
bool setEmax(const CaloSample sampling, const float eMax)
Set the Energy of the cell with the highest energy in a particular sampling.
float eSample(const CaloSample sampling) const
flt_t calEta() const
Get in signal state CALIBRATED.
flt_t secondTime() const
Access second moment of cell timing distribution.
bool setEnergy(const CaloSample sampling, const float e)
Set energy for a given sampling. Returns false if the sample isn't part of the cluster.
virtual double phi() const
The azimuthal angle ( ) of the particle.
void setSamplingPattern(const unsigned sp, const bool clearSamplingVars=false)
Set sampling pattern (one bit per sampling.
float etamax(const CaloSample sampling) const
Retrieve of cell with maximum energy in given sampling.
@ ENG_CALIB_OUT_M
Attached Calibration Hit energy outside clusters but inside the calorimeter with medium matching (Ang...
@ PTD
relative spread of pT of constiuent cells = sqrt(n)*RMS/Mean
@ SECOND_ENG_DENS
Second Moment in E/V.
@ DELTA_PHI
Angular shower axis deviation ( ) from IP-to-Center.
@ ETA2CALOFRAME
Eta of sampling 2 in the calo frame (for egamma)
@ DELTA_ALPHA
Angular shower axis deviation ( ) from IP-to-Center.
@ OOC_WEIGHT
Out-of-cluster weight (E_ooc/E_w)
@ AVG_TILE_Q
Sum(E_cell_Tile^2 Q_cell_Tile)/Sum(E_cell_Tile^2)
@ DELTA_THETA
Angular shower axis deviation ( ) from IP-to-Center.
@ SECOND_LAMBDA
Second Moment in .
@ ETACALOFRAME
Eta in the calo frame (for egamma)
@ FIRST_PHI
First Moment in .
@ ENG_CALIB_OUT_L
Attached Calibration Hit energy outside clusters but inside the calorimeter with loose matching (Angl...
@ CELL_SIGNIFICANCE
Cell significance = E/sig of the cell with the largest |E|/sig.
@ CELL_SIG_SAMPLING
CaloSample of the cell with the largest |E|/sig.
@ EM_PROBABILITY
Classification probability to be em-like.
@ PHI2CALOFRAME
Phi of sampling 2 in the calo frame (for egamma)
@ VERTEX_FRACTION
Vertex fraction of this cluster wrt.
@ ENG_CALIB_DEAD_T
Attached Calibration Hit energy in dead material with tight matching (Angle < 0.3).
@ NCELL_SAMPLING
Number of cells in sampling layer.
@ NVERTEX_FRACTION
slightly updated vertex fraction more pile up independent (similar to nJVF)
@ SECOND_TIME
Second moment of cell time distribution in cluster.
@ N_BAD_CELLS_CORR
Number of bad cells with energy density average correction applied.
@ DM_WEIGHT
Dead-material weight (E_dm/E_ooc)
@ LATERAL
Normalized lateral moment.
@ N_BAD_CELLS
number of bad cells
@ LONGITUDINAL
Normalized longitudinal moment.
@ ENG_FRAC_MAX
Energy fraction of hottest cell.
@ AVG_LAR_Q
Sum(E_cell_LAr^2 Q_cell_LAr)/Sum(E_cell_LAr^2)
@ ENG_CALIB_DEAD_UNCLASS
Attached Calibration Hit energy in dead material in unclassified areas of the detector.
@ PHI1CALOFRAME
Phi of sampling 1 in the calo frame (for egamma)
@ ENG_FRAC_EM
Energy fraction in EM calorimeters.
@ SECOND_R
Second Moment in .
@ ENG_CALIB_DEAD_HEC0
Attached Calibration Hit energy in dead material between EME3 and HEC0.
@ FIRST_ETA
First Moment in .
@ PHICALOFRAME
Phi in the calo frame (for egamma)
@ ENG_BAD_HV_CELLS
Total em-scale energy of cells with bad HV in this cluster.
@ FIRST_ENG_DENS
First Moment in E/V.
@ HAD_WEIGHT
Hadronic weight (E_w/E_em)
@ ENG_CALIB_DEAD_TILEG3
Attached Calibration Hit energy in dead material before scintillator.
@ N_BAD_HV_CELLS
number of cells with bad HV
@ ENG_FRAC_CORE
Energy fraction of the sum of the hottest cells in each sampling.
@ CENTER_LAMBDA
Shower depth at Cluster Centroid.
@ SIGNIFICANCE
Cluster significance.
@ CENTER_MAG
Cluster Centroid ( )
@ MASS
cell based mass i.e. the mass of the 4-vector sum of all massless positive energetic cells
@ ENG_CALIB_DEAD_M
Attached Calibration Hit energy in dead material with medium matching (Angle < 0.5).
@ ENG_CALIB_FRAC_REST
Calibration Hit energy inside the cluster caused by other particles.
@ ENG_CALIB_DEAD_L
Attached Calibration Hit energy in dead material with loose matching (Angle < 1.0).
@ ENG_CALIB_DEAD_EME0
Attached Calibration Hit energy in dead material before EME0, between EME0 and EME1.
@ ENG_CALIB_DEAD_TILE0
Attached Calibration Hit energy in dead material between EMB3 and TILE0.
@ CENTER_Z
Cluster Centroid ( )
@ BAD_CELLS_CORR_E
Energy of bad cells with energy density average correction applied.
@ ETA1CALOFRAME
Eta of sampling 1 in the calo frame (for egamma)
@ ENG_CALIB_FRAC_EM
Calibration Hit energy inside the cluster caused by e/gamma/pi0.
@ ENG_BAD_CELLS
Total em-scale energy of bad cells in this cluster.
@ ENG_CALIB_DEAD_FCAL
Attached Calibration Hit energy in dead material before FCAL, between FCAL and HEC.
@ ENG_CALIB_TOT
Calibration Hit energy inside the cluster.
@ ENG_CALIB_OUT_T
Attached Calibration Hit energy outside clusters but inside the calorimeter with tight matching (Angl...
@ ENG_CALIB_DEAD_LEAKAGE
Attached Calibration Hit energy in dead material behind calorimeters.
@ ENG_CALIB_FRAC_HAD
Calibration Hit energy inside the cluster caused by charged pi+ and pi-.
@ ENG_CALIB_EMB0
Calibration Hit energy inside the cluster barrel presampler.
@ ENG_CALIB_EME0
Calibration Hit energy inside the cluster endcap presampler.
@ ENG_POS
Total positive Energy of this cluster.
@ BADLARQ_FRAC
Energy fraction of LAr cells with quality larger than a given cut.
@ CENTER_X
Cluster Centroid ( )
@ ENG_CALIB_DEAD_EMB0
Attached Calibration Hit energy in dead material before EMB0, between EMB0 and EMB1.
@ ISOLATION
Energy weighted fraction of non-clustered perimeter cells.
@ ENG_CALIB_DEAD_TOT
Attached Calibration Hit energy in dead material.
@ CENTER_Y
Cluster Centroid ( )
@ ENG_CALIB_TILEG3
Calibration Hit energy inside the cluster scintillator.
@ TILE_CONFIDENCE_LEVEL
Confidence Level of a tile calorimeter cluster to be noise.
const_cell_iterator cell_begin() const
Iterator of the underlying CaloClusterCellLink (const version)
float etaSample(const CaloSample sampling) const
Retrieve barycenter in a given sample.
void setNumberCellsInSampling(CaloSampling::CaloSample samp, int ncells, bool isInnerWheel=false)
Set the number of cells in a sampling layer.
float phimax(const CaloSample sampling) const
Retrieve of cell with maximum energy in given sampling.
flt_t calE() const
Geet Energy in signal state CALIBRATED.
bool setEtamax(const CaloSample sampling, const float etaMax)
Set the eta of the cell with the highest energy in a particular sampling.
void clearSamplingData()
Clear the sampling data.
flt_t calM() const
Get mass in signal state CALIBRATED.
void nextDDE(Iter iter, Iter endIter)
Prefetch next CaloDDE.
void CPU_to_GPU_async(void *dest, const void *const source, const size_t num, CUDAStreamPtrHolder stream={})
Copies num bytes from source in CPU memory to dest in GPU memory, asynchronously.
void GPU_synchronize(CUDAStreamPtrHolder stream={})
Synchronizes the stream.
void GPU_to_CPU_async(void *dest, const void *const source, const size_t num, CUDAStreamPtrHolder stream={})
Copies num bytes from source in GPU memory to dest in CPU memory, asynchronously.
Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration.
constexpr int NumSamplings
TagBase::carrier tag_type
constexpr int NCaloCells
str index
Definition DeMoScan.py:362
Definition index.py:1
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
CaloCluster_v1 CaloCluster
Define the latest version of the calorimeter cluster class.
CaloClusterContainer_v1 CaloClusterContainer
Define the latest version of the calorimeter cluster container.
setEventNumber uint32_t
Contains the fundamental information that allows interacting with CellInfoArr so that it is easier to...
Contains the per-event cell information: energy, timing, gain, quality and provenance.
Contains the fundamental information that allows interacting with ClusterInfoArr so that it is easier...
The class that actually expresses the cluster assignment.
constexpr int32_t secondary_cluster_index() const
constexpr int32_t secondary_cluster_weight() const
constexpr bool is_shared_between_clusters() const
constexpr bool is_part_of_cluster() const
constexpr int32_t cluster_index() const
static constexpr carrier make_tag(const uint16_t cluster_index=0, const int32_t weight=0, const uint16_t second_cluster_index=0)
static constexpr bool is_tile(const int cell)
Holds an array of bools to represent the different moments that may be calculated and transferred to/...
Definition DataHolders.h:50
bool array[num_moments+1]
Definition DataHolders.h:52
static MomentsOptionsArray all()
static int moment_to_linear(const int moment)
bool & operator[](const int moment)
static constexpr int num_moments
Definition DataHolders.h:51
Just two uint16_t bit-packed onto a uint32_t.
static constexpr carrier make_invalid_tag()