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 if (!moments_to_add[xAOD::CaloCluster::NCELL_SAMPLING])
741 //We need to tranfer the number of cells per sampling in any case
742 //to be able to properly populate the sampling bit pattern...
743 {
744 moments_copy_helper(output_clusters->moments.nCellSampling, input_clusters->moments.nCellSampling);
745 }
746
747#define CALORECGPU_MOMENTS_TO_GPU_HELPER(VAR_NAME, PROPER_MOMENT, NORMAL_ASSIGN, IS_CALCULATED, MOMENT_NAME, ...) \
748 CRGPU_CONCAT(CRGPU_CONCAT(CALORECGPU_MOMENTS_TO_GPU_HELPER_, PROPER_MOMENT), IS_CALCULATED) (VAR_NAME, MOMENT_NAME)
749
750#define CALORECGPU_MOMENTS_TO_GPU_HELPER_11(VAR_NAME, MOMENT_NAME) \
751 if (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_10(VAR_NAME, MOMENT_NAME) \
757 if ( state_holder->state == CaloRecGPU::ClusterInformationState::WithExtraMoments && \
758 moments_to_add[xAOD::CaloCluster:: MOMENT_NAME ] ) \
759 { \
760 moments_copy_helper(output_clusters->moments. VAR_NAME, input_clusters->moments. VAR_NAME); \
761 }
762
763#define CALORECGPU_MOMENTS_TO_GPU_HELPER_01(VAR_NAME, MOMENT_NAME) \
764 moments_copy_helper(output_clusters->moments. VAR_NAME, input_clusters->moments. VAR_NAME);
765
766#define CALORECGPU_MOMENTS_TO_GPU_HELPER_00(VAR_NAME, MOMENT_NAME) \
767 if (state_holder->state == CaloRecGPU::ClusterInformationState::WithExtraMoments) \
768 { \
769 moments_copy_helper(output_clusters->moments. VAR_NAME, input_clusters->moments. VAR_NAME); \
770 }
771
773 }
774}
775
776template <class ReadStateFrom, class OutputClusters, class InputClusters, class CopyFunc>
777static void cluster_transfer_helper(ReadStateFrom & state_holder,
778 OutputClusters & output_clusters,
779 InputClusters & input_clusters,
780 const MomentsOptionsArray & moments_to_add,
781 CopyFunc copy_func,
782 const bool full_copy,
784 const int num_total_cells = CaloRecGPU::NCaloCells)
785{
786 if (full_copy)
787 {
788 copy_func(output_clusters, input_clusters, sizeof(CaloRecGPU::ClusterInfoArr), stream);
789 }
790 else
791 {
792 cluster_transfer_helper_basic_info(state_holder, output_clusters, input_clusters, copy_func, stream);
793
794 cluster_transfer_helper_cell_assignment(state_holder, output_clusters, input_clusters, copy_func, stream, num_total_cells);
795
796 cluster_transfer_helper_moments(state_holder, output_clusters, input_clusters, moments_to_add, copy_func, stream);
797 }
798}
799
800
801void CaloRecGPU::EventDataHolder::sendToGPU(const MomentsOptionsArray & moments_to_add,
802 const bool full_copy,
803 const bool clear_CPU,
804 const bool synchronize,
805 CaloRecGPU::CUDA_Helpers::CUDAStreamPtrHolder stream)
806{
807 m_cell_info_dev.allocate();
808 m_clusters_dev.allocate();
809
810 if (!full_copy)
811 {
812 CaloRecGPU::CUDA_Helpers::CPU_to_GPU_async(static_cast<CellBaseInfo *>(m_cell_info_dev),
813 static_cast<const CellBaseInfo *>(m_cell_info),
814 sizeof(CellBaseInfo), stream);
815
816 CaloRecGPU::CUDA_Helpers::CPU_to_GPU_async(static_cast<ClusterBaseInfo *>(m_clusters_dev),
817 static_cast<const ClusterBaseInfo *>(m_clusters),
818 sizeof(ClusterBaseInfo), stream);
819
820 }
821
822 cell_transfer_helper(m_cell_info, m_cell_info_dev, m_cell_info,
824
825 cluster_transfer_helper(m_clusters, m_clusters_dev, m_clusters, moments_to_add,
827 m_cell_info->number);
828
829 if (clear_CPU)
830 {
832
833 m_clusters.clear();
834 m_cell_info.clear();
835 }
836 else if (synchronize)
837 {
839 }
840}
841
842void CaloRecGPU::EventDataHolder::returnToCPU(const MomentsOptionsArray & moments_to_add,
843 const bool full_copy,
844 const bool clear_GPU,
845 const bool synchronize,
846 CaloRecGPU::CUDA_Helpers::CUDAStreamPtrHolder stream,
847 const bool also_return_cells)
848{
849 if (also_return_cells)
850 {
851 m_cell_info.allocate();
852 }
853 m_clusters.allocate();
854
855 if (!full_copy)
856 {
857 if (also_return_cells)
858 {
860 static_cast<CellBaseInfo *>(m_cell_info_dev),
861 sizeof(CellBaseInfo), stream);
862 }
863
865 static_cast<ClusterBaseInfo *>(m_clusters_dev),
866 sizeof(ClusterBaseInfo), stream);
867
869
870 }
871
872 if (also_return_cells)
873 {
874 cell_transfer_helper(m_cell_info, m_cell_info, m_cell_info_dev,
876 }
877
878 cluster_transfer_helper(m_clusters, m_clusters, m_clusters_dev, moments_to_add,
880
881 if (clear_GPU)
882 {
884
885 m_clusters_dev.clear();
886 m_cell_info_dev.clear();
887 }
888 else if (synchronize)
889 {
891 }
892}
893
894//clusters->number must be available!
895//if skip_validation is true, clusters->seedCellIndex must also be available.
897 std::vector<std::unique_ptr<CaloClusterCellLink>> & cell_links,
898 const DataLink<CaloCellContainer> & cell_collection_link,
899 const bool skip_validation)
900{
901 cell_links.reserve(clusters->number);
902
903 for (int i = 0; i < clusters->number; ++i)
904 {
905 if (skip_validation || clusters->seedCellIndex[i] >= 0)
906 {
907 cell_links.emplace_back(std::make_unique<CaloClusterCellLink>(cell_collection_link));
908 cell_links.back()->reserve(256);
909 //To be adjusted.
910 }
911 else
912 {
913 cell_links.emplace_back(nullptr);
914 //The excluded clusters don't have any cells.
915 }
916 }
917}
918
919//The CPU cells must be available!
920//The cluster status and number of cells must be available!
921//
922static void export_cluster_process_cells(const ClusterInfoArr * clusters,
923 const CellInfoArr * cells,
924 std::vector<std::unique_ptr<CaloClusterCellLink>> & cell_links,
925 const std::vector<int> & extra_cells_to_fill)
926{
927
928 std::vector<int> real_cells_to_fill;
929
930 if (cells->number == CaloRecGPU::NCaloCells && !cells->all_cells_valid)
931 {
932 real_cells_to_fill.reserve(extra_cells_to_fill.size());
933
934 for (const int cell : extra_cells_to_fill)
935 {
936 if (cells->hashIDToCollection[cell] <= 0)
937 {
938 real_cells_to_fill.push_back(cell);
939 }
940 }
941 }
942
943 auto corrected_index_to_real_index = [&](const int index)
944 {
945 if (cells->all_cells_valid)
946 {
947 return index;
948 }
949
950 int ret = index;
951
952 for (const int cell : real_cells_to_fill)
953 {
954 ret -= (index > cell);
955 }
956
957 return ret;
958 };
959
960 if (clusters->has_cells_per_cluster())
961 {
962 for (int i = 0; i < clusters->number_cells; ++i)
963 {
964 std::unique_ptr<CaloClusterCellLink> & this_link_ptr = cell_links[clusters->clusterIndices[i]];
965 if (this_link_ptr)
966 //This should always be true at this stage,
967 //but guarding against any potentially invalidated clusters.
968 {
969 this_link_ptr->addCell(corrected_index_to_real_index(clusters->cells.indices[i]), clusters->cellWeights[i]);
970 }
971 }
972 }
973 else
974 {
975 for (int i = 0; i < clusters->number; ++i)
976 {
977 if (cell_links[i])
978 {
979 cell_links[i]->addCell(corrected_index_to_real_index(clusters->seedCellIndex[i]), 1);
980 //Seed cells aren't shared, by construction.
981 }
982 }
983
984 for (int i = 0; i < clusters->number_cells; ++i)
985 {
986 const ClusterTag this_tag = clusters->cells.tags[i];
987
988 if (this_tag.is_part_of_cluster())
989 {
990 const int this_cell_index = corrected_index_to_real_index(i);
991
992 const int this_index = this_tag.cluster_index();
993 const int32_t weight_pattern = this_tag.secondary_cluster_weight();
994
995 float tempf = 1.0f;
996
997 std::memcpy(&tempf, &weight_pattern, sizeof(float));
998
999 const float reverse_weight = tempf;
1000
1001 const float this_weight = 1.0f - reverse_weight;
1002
1003 if (cell_links[this_index] && clusters->seedCellIndex[this_index] != i)
1004 {
1005 cell_links[this_index]->addCell(this_cell_index, this_weight);
1006 }
1007
1008 if (this_tag.is_shared_between_clusters())
1009 {
1010 const int other_index = this_tag.secondary_cluster_index();
1011 if (cell_links[other_index] && clusters->seedCellIndex[other_index] != i)
1012 {
1013 cell_links[other_index]->addCell(this_cell_index, reverse_weight);
1014 }
1015 }
1016 }
1017 }
1018 }
1019}
1020
1021static void export_cluster_sort(const ClusterInfoArr * clusters,
1022 std::vector<int> & cluster_order,
1023 const bool really_sort)
1024{
1025 if (really_sort)
1026 {
1027 cluster_order.resize(clusters->number);
1028
1029 std::iota(cluster_order.begin(), cluster_order.end(), 0);
1030
1031 std::sort(cluster_order.begin(), cluster_order.end(), [&](const int a, const int b) -> bool
1032 {
1033 const bool a_valid = clusters->seedCellIndex[a] >= 0;
1034 const bool b_valid = clusters->seedCellIndex[b] >= 0;
1035 if (a_valid && b_valid)
1036 {
1037 return (clusters->clusterEt[a] > clusters->clusterEt[b]);
1038 }
1039 else if (a_valid)
1040 {
1041 return true;
1042 }
1043 else if (b_valid)
1044 {
1045 return false;
1046 }
1047 else
1048 {
1049 return b > a;
1050 }
1051 } );
1052 }
1053 else
1054 {
1055 cluster_order.clear();
1056 }
1057}
1058
1060 xAOD::CaloClusterContainer * cluster_collection,
1061 std::vector<std::unique_ptr<CaloClusterCellLink>> & cell_links,
1062 std::vector<int> & cluster_order,
1063 const bool save_uncalibrated)
1064{
1065 const int total_size = (cluster_order.size() ? cluster_order.size() : clusters->number);
1066 for (int i = 0; i < total_size; ++i)
1067 {
1068 const int cluster_index = (cluster_order.size() ? cluster_order[i] : i);
1069
1070 if (cell_links[cluster_index] != nullptr && cell_links[cluster_index]->size() > 0)
1071 {
1072 xAOD::CaloCluster * cluster = new xAOD::CaloCluster();
1073 cluster_collection->push_back(cluster);
1074
1075 cluster->addCellLink(std::move(cell_links[cluster_index]));
1076
1077 if (clusters->has_basic_info())
1078 {
1079
1080 cluster->setE (clusters->clusterEnergy[cluster_index]);
1081 cluster->setEta(clusters->clusterEta [cluster_index]);
1082 cluster->setPhi(clusters->clusterPhi [cluster_index]);
1083
1084 if (save_uncalibrated)
1085 {
1086 cluster->setRawE(cluster->calE());
1087 cluster->setRawEta(cluster->calEta());
1088 cluster->setRawPhi(cluster->calPhi());
1089 cluster->setRawM(cluster->calM());
1090 }
1091 }
1092 }
1093 }
1094}
1095
1096static void export_cluster_fill_moments(const ClusterInfoArr * clusters,
1097 xAOD::CaloClusterContainer * cluster_collection,
1098 std::vector<int> & cluster_order,
1099 const MomentsOptionsArray & moments_to_add,
1100 const bool output_extra_moments)
1101{
1102 if (clusters->has_moments())
1103 {
1104 const int total_size = (cluster_order.size() ? cluster_order.size() : clusters->number);
1105 for (int i = 0; i < total_size; ++i)
1106 {
1107 const int cluster_index = (cluster_order.size() ? cluster_order[i] : i);
1108
1109 xAOD::CaloCluster * cluster = (*cluster_collection)[cluster_index];
1110
1111 cluster->clearSamplingData();
1112
1113 uint32_t sampling_pattern = 0;
1114 for (int sampl = 0; sampl < NumSamplings; ++sampl)
1115 {
1116 const int cells_per_sampling = clusters->moments.nCellSampling[sampl][cluster_index];
1117
1118 if (cells_per_sampling > 0)
1119 {
1120 sampling_pattern |= (0x1U << sampl);
1121 }
1122 }
1123
1124 if (clusters->moments.nExtraCellSampling[cluster_index] > 0)
1125 {
1126 sampling_pattern |= (1U << static_cast<unsigned int>(CaloSampling::EME2));
1127 }
1128
1129 cluster->setSamplingPattern(sampling_pattern);
1130
1131 for (int s = 0; s < NumSamplings; ++s)
1132 {
1133 if (sampling_pattern & (1U << s))
1134 {
1135 cluster->setNumberCellsInSampling(static_cast<CaloSampling::CaloSample>(s), clusters->moments.nCellSampling[s][cluster_index], false);
1136 }
1137 }
1138
1139 if (clusters->moments.nExtraCellSampling[cluster_index] > 0)
1140 {
1141 cluster->setNumberCellsInSampling(CaloSampling::EME2, clusters->moments.nExtraCellSampling[cluster_index], true);
1142 }
1143
1144 for (int s = 0; s < NumSamplings; ++s)
1145 {
1146 if (sampling_pattern & (1U << s))
1147 {
1148 cluster->setEnergy(static_cast<CaloSampling::CaloSample>(s), clusters->moments.energyPerSample[s][cluster_index]);
1149 }
1150 }
1151 for (int s = 0; s < NumSamplings; ++s)
1152 {
1153 if (sampling_pattern & (1U << s))
1154 {
1155 cluster->setEmax(static_cast<CaloSampling::CaloSample>(s), clusters->moments.maxEPerSample[s][cluster_index]);
1156 }
1157 }
1158 for (int s = 0; s < NumSamplings; ++s)
1159 {
1160 if (sampling_pattern & (1U << s))
1161 {
1162 cluster->setEtamax(static_cast<CaloSampling::CaloSample>(s), clusters->moments.maxEtaPerSample[s][cluster_index] );
1163 }
1164 }
1165 for (int s = 0; s < NumSamplings; ++s)
1166 {
1167 if (sampling_pattern & (1U << s))
1168 {
1169 cluster->setPhimax(static_cast<CaloSampling::CaloSample>(s), clusters->moments.maxPhiPerSample[s][cluster_index]);
1170 }
1171 }
1172 for (int s = 0; s < NumSamplings; ++s)
1173 {
1174 if (sampling_pattern & (1U << s))
1175 {
1176 cluster->setEta(static_cast<CaloSampling::CaloSample>(s), clusters->moments.etaPerSample[s][cluster_index]);
1177 }
1178 }
1179 for (int s = 0; s < NumSamplings; ++s)
1180 {
1181 if (sampling_pattern & (1U << s))
1182 {
1183 cluster->setPhi(static_cast<CaloSampling::CaloSample>(s), clusters->moments.phiPerSample[s][cluster_index]);
1184 }
1185 }
1186
1187 cluster->setTime(clusters->moments.time[cluster_index]);
1188 cluster->setSecondTime(clusters->moments.secondTime[cluster_index]);
1189
1190#define CALORECGPU_MOMENTS_OUTPUT_HELPER(VAR_NAME, PROPER_MOMENT, NORMAL_ASSIGN, IS_CALCULATED, MOMENT_NAME, ...) \
1191 CRGPU_CONCAT(CRGPU_CONCAT(CALORECGPU_MOMENTS_OUTPUT_HELPER_, NORMAL_ASSIGN), IS_CALCULATED) (VAR_NAME, MOMENT_NAME)
1192
1193#define CALORECGPU_MOMENTS_OUTPUT_HELPER_11(VAR_NAME, MOMENT_NAME) \
1194 if (moments_to_add[xAOD::CaloCluster:: MOMENT_NAME]) \
1195 { \
1196 cluster->insertMoment(xAOD::CaloCluster:: MOMENT_NAME , clusters->moments. VAR_NAME [cluster_index]); \
1197 }
1198
1199#define CALORECGPU_MOMENTS_OUTPUT_HELPER_10(VAR_NAME, MOMENT_NAME) \
1200 if (output_extra_moments && moments_to_add[xAOD::CaloCluster:: MOMENT_NAME]) \
1201 { \
1202 cluster->insertMoment(xAOD::CaloCluster:: MOMENT_NAME , clusters->moments. VAR_NAME [cluster_index]); \
1203 }
1204
1205#define CALORECGPU_MOMENTS_OUTPUT_HELPER_00(...)
1206#define CALORECGPU_MOMENTS_OUTPUT_HELPER_01(...)
1207
1209 }
1210 }
1211}
1212
1213
1214void CaloRecGPU::EventDataHolder::exportClusters(void * p_cluster_collection,
1215 const void * p_cell_collection_link,
1216 const MomentsOptionsArray & moments_to_add,
1217 bool sort_clusters,
1218 const bool save_uncalibrated,
1219 const bool output_extra_moments,
1220 const std::vector<int> & extra_cells_to_fill,
1221 size_t * time_measurements)
1222{
1223 using clock_type = boost::chrono::thread_clock;
1224 auto time_cast = [](const auto & before, const auto & after)
1225 {
1226 return boost::chrono::duration_cast<boost::chrono::microseconds>(after - before).count();
1227 };
1228
1229 xAOD::CaloClusterContainer * cluster_collection = static_cast<xAOD::CaloClusterContainer *>(p_cluster_collection);
1230 const DataLink<CaloCellContainer> & cell_collection_link = *(static_cast<const DataLink<CaloCellContainer> *>(p_cell_collection_link));
1231
1232 const auto start = clock_type::now();
1233
1234 std::vector<std::unique_ptr<CaloClusterCellLink>> cell_links;
1235
1236 export_cluster_initialize_links(m_clusters, cell_links, cell_collection_link, false);
1237
1238 const auto after_link_creation = clock_type::now();
1239
1240 export_cluster_process_cells(m_clusters, m_cell_info, cell_links, extra_cells_to_fill);
1241
1242 const auto after_cell_processing = clock_type::now();
1243
1244 std::vector<int> cluster_order;
1245
1246 export_cluster_sort(m_clusters, cluster_order, sort_clusters);
1247
1248 const auto after_sorting = clock_type::now();
1249
1250 export_cluster_fill_cells_and_basic_info(m_clusters, cluster_collection, cell_links, cluster_order, save_uncalibrated);
1251
1252 const auto after_basic_info = clock_type::now();
1253
1254 export_cluster_fill_moments(m_clusters, cluster_collection, cluster_order, moments_to_add, output_extra_moments);
1255
1256 const auto after_moments = clock_type::now();
1257
1258 if (time_measurements)
1259 {
1260 time_measurements[0] = time_cast(start, after_link_creation);
1261 time_measurements[1] = time_cast(after_link_creation, after_cell_processing);
1262 time_measurements[2] = time_cast(after_cell_processing, after_sorting);
1263 time_measurements[3] = time_cast(after_sorting, after_basic_info);
1264 time_measurements[4] = time_cast(after_basic_info, after_moments);
1265 }
1266}
1267
1268
1270 const void * p_cell_collection_link,
1271 const MomentsOptionsArray & moments_to_add,
1272 bool sort_clusters,
1273 const bool save_uncalibrated,
1274 const bool output_extra_moments,
1275 const std::vector<int> & extra_cells_to_fill,
1276 size_t * time_measurements,
1278{
1279 using clock_type = boost::chrono::thread_clock;
1280 auto time_cast = [](const auto & before, const auto & after)
1281 {
1282 return boost::chrono::duration_cast<boost::chrono::microseconds>(after - before).count();
1283 };
1284
1285 xAOD::CaloClusterContainer * cluster_collection = static_cast<xAOD::CaloClusterContainer *>(p_cluster_collection);
1286 const DataLink<CaloCellContainer> & cell_collection_link = *(static_cast<const DataLink<CaloCellContainer> *>(p_cell_collection_link));
1287
1288 const auto start = clock_type::now();
1289
1290 m_clusters.allocate();
1291
1293 static_cast<const ClusterBaseInfo *>(m_clusters_dev),
1294 sizeof(ClusterBaseInfo), stream);
1295
1297
1298 const auto after_first_transfer = clock_type::now();
1299
1301
1302 std::vector<std::unique_ptr<CaloClusterCellLink>> cell_links;
1303
1304 export_cluster_initialize_links(m_clusters, cell_links, cell_collection_link, true);
1305
1306 const auto after_link_creation = clock_type::now();
1307
1309
1311
1312 export_cluster_process_cells(m_clusters, m_cell_info, cell_links, extra_cells_to_fill);
1313
1314 const auto after_cell_processing = clock_type::now();
1315
1316 std::vector<int> cluster_order;
1317
1318 export_cluster_sort(m_clusters, cluster_order, sort_clusters);
1319
1320 const auto after_sorting = clock_type::now();
1321
1323
1325
1326 export_cluster_fill_cells_and_basic_info(m_clusters, cluster_collection, cell_links, cluster_order, save_uncalibrated);
1327
1328 const auto after_basic_info = clock_type::now();
1329
1331
1332 export_cluster_fill_moments(m_clusters, cluster_collection, cluster_order, moments_to_add, output_extra_moments);
1333
1334 const auto after_moments = clock_type::now();
1335
1336 if (time_measurements)
1337 {
1338 time_measurements[0] = time_cast(start, after_first_transfer);
1339 time_measurements[1] = time_cast(after_first_transfer, after_link_creation);
1340 time_measurements[2] = time_cast(after_link_creation, after_cell_processing);
1341 time_measurements[3] = time_cast(after_cell_processing, after_sorting);
1342 time_measurements[4] = time_cast(after_sorting, after_basic_info);
1343 time_measurements[5] = time_cast(after_basic_info, after_moments);
1344 }
1345}
1346
1348{
1349 m_cell_info.allocate();
1350 m_clusters.allocate();
1351
1352 if (also_GPU)
1353 {
1354 m_cell_info_dev.allocate();
1355 m_clusters_dev.allocate();
1356 }
1357}
1358
1360{
1361 m_cell_info_dev.clear();
1362 m_clusters_dev.clear();
1363}
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()