ATLAS Offline Software
Loading...
Searching...
No Matches
CaloGPUClusterAndCellDataMonitor.cxx
Go to the documentation of this file.
1//
2// Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3//
4// Dear emacs, this is -*- c++ -*-
5//
6
7
8#ifndef CALORECGPU_DATA_MONITOR_EXTRA_PRINTOUTS
9
10 #define CALORECGPU_DATA_MONITOR_EXTRA_PRINTOUTS 0
11
12#endif
13
15#include "CaloRecGPU/Helpers.h"
20#include "CaloRecUtilities.h"
22
23#include "CLHEP/Units/SystemOfUnits.h"
24
25#include <map>
26#include <numeric>
27#include <algorithm>
28#include <string_view>
29
30using namespace CaloRecGPU;
31
32CaloGPUClusterAndCellDataMonitor::CaloGPUClusterAndCellDataMonitor(const std::string & type, const std::string & name, const IInterface * parent):
33 base_class(type, name, parent),
35{
36}
37
39{
40 ATH_CHECK( m_cellsKey.initialize() );
41
42 ATH_CHECK( detStore()->retrieve(m_calo_id, "CaloCell_ID") );
43
44 const std::string this_name = this->name();
45
46 const std::string algorithm_name_prefix = this_name.substr(0, this_name.rfind('.'));
47 //This is so we take into account the fact that tools
48 //are prefixed with the parent algorithm's name.
49
50 auto final_string = [& algorithm_name_prefix](const std::string & unpref_str) -> std::string
51 {
52 return algorithm_name_prefix + "." + unpref_str;
53 };
54
56
57 m_min_similarity = opts.min_similarity;
58 m_seed_weight = opts.seed_w;
59 m_grow_weight = opts.grow_w;
60 m_terminal_weight = opts.term_w;
61
62 for (const auto & tool : m_toolsToPlot)
63 {
64 const std::string tool_name = final_string(tool.tool);
65 m_toolToIdMap[tool_name] = tool.plot_id;
66 m_toolsToCheckFor[tool_name] = -1;
67 }
68
69 auto add_tool_from_pair = [this](const std::string & name) -> int
70 {
71 if (!m_toolsToCheckFor.count(name))
72 {
74 m_toolToIdMap[name] = "";
75 return m_numToolsToKeep++;
76 }
77 else
78 {
79 const int current = m_toolsToCheckFor[name];
80 if (current >= 0)
81 {
82 return current;
83 }
84 else
85 {
87 return m_numToolsToKeep++;
88 }
89 }
90 };
91
92 for (const auto & pair : m_pairsToPlot)
93 {
94 const int first_index = add_tool_from_pair(final_string(pair.tool_ref));
95 const int second_index = add_tool_from_pair(final_string(pair.tool_test));
96 m_toolCombinations.emplace_back(pair_to_plot{first_index, second_index, pair.plot_id,
97 pair.match_in_energy,
98 pair.match_without_shared,
99 pair.match_perfectly});
100 }
101
102 ATH_CHECK( m_moniTool.retrieve() );
103
104 return StatusCode::SUCCESS;
105}
106
108{
109 //Well, not do plots, just monitor the number of events and the total number of clusters...
110
111 auto mon_num_events = Monitored::Scalar("num_events", m_numEvents);
112
113 for (const auto & k_v : m_toolToIdMap)
114 {
115 auto mon_num_clust = Monitored::Scalar(k_v.second + "_num_total_clusters", m_numClustersPerTool.at(k_v.first).load());
116 }
117
118 return StatusCode::SUCCESS;
119}
120
121StatusCode CaloGPUClusterAndCellDataMonitor::update_plots_start(const EventContext & /*ctx*/,
122 const ConstantDataHolder & /*constant_data*/,
123 const xAOD::CaloClusterContainer * /*cluster_collection_ptr*/) const
124{
126 {
127 std::lock_guard<std::mutex> lock_guard(m_mutex);
129 {
131 //We have the mutex.
132 //It's safe.
133 ATH_CHECK( dhis->initialize_plotted_variables() );
135 }
136 }
137 if (m_numToolsToKeep > 0)
138 {
139 m_storageHolder.get_one().resize(m_numToolsToKeep);
140 }
141 //Allocate a vector of data holders for this thread and resize it to the necessary size.
142
143 return StatusCode::SUCCESS;
144}
145
146StatusCode CaloGPUClusterAndCellDataMonitor::update_plots_end(const EventContext & ctx,
147 const ConstantDataHolder & constant_data,
148 const xAOD::CaloClusterContainer * /*cluster_collection_ptr*/) const
149{
150 ATH_MSG_INFO("");
151
152 for (const auto & combination : m_toolCombinations)
153 {
154 if (combination.index_ref < 0 || combination.index_test < 0)
155 {
156 ATH_MSG_WARNING("Invalid tool combination, please check your configuration! " << combination.prefix);
157 continue;
158 }
159 ATH_CHECK( add_combination(ctx, constant_data, combination.index_ref, combination.index_test, combination.prefix,
160 combination.match_in_energy, combination.match_without_shared, combination.match_perfectly) );
161 }
162
163 ATH_MSG_INFO("");
164
165 if (m_numToolsToKeep > 0)
166 {
167 m_storageHolder.release_one();
168 //Release the tool storage.
169 }
170
171 return StatusCode::SUCCESS;
172}
173
174StatusCode CaloGPUClusterAndCellDataMonitor::update_plots(const EventContext & ctx,
175 const ConstantDataHolder & constant_data,
176 const xAOD::CaloClusterContainer * cluster_collection_ptr,
177 const CaloClusterCollectionProcessor * tool) const
178{
179 if (filter_tool_by_name(tool->name()))
180 {
181 SG::ReadHandle<CaloCellContainer> cell_collection(m_cellsKey, ctx);
182
184
185 ed.allocate(false);
186
187 ed.importCells(static_cast<const CaloCellContainer *>(&(*cell_collection)), m_missingCellsToFill);
188
189 ed.importClusters(cluster_collection_ptr, MomentsOptionsArray::all(), false, true, true, true, m_missingCellsToFill);
190
191 std::vector<int> cells_prefix_sum;
192
193 ATH_CHECK(update_cell_representation(ctx, constant_data, ed.m_cell_info, ed.m_clusters, cells_prefix_sum));
194
195 return add_data(ctx, constant_data, ed.m_cell_info, ed.m_clusters, cells_prefix_sum, tool->name());
196 }
197 else
198 {
199 return StatusCode::SUCCESS;
200 }
201}
202
203StatusCode CaloGPUClusterAndCellDataMonitor::update_plots(const EventContext & ctx,
204 const ConstantDataHolder & constant_data,
205 const xAOD::CaloClusterContainer * /*cluster_collection_ptr*/,
206 const EventDataHolder & event_data,
207 const ICaloClusterGPUInputTransformer * tool) const
208{
209 if (filter_tool_by_name(tool->name()))
210 {
213
214 std::vector<int> cells_prefix_sum;
215
216 ATH_CHECK(update_cell_representation(ctx, constant_data, cell_info, clusters, cells_prefix_sum));
217
218 return add_data(ctx, constant_data, cell_info, clusters, cells_prefix_sum, tool->name());
219 }
220 else
221 {
222 return StatusCode::SUCCESS;
223 }
224}
225
226StatusCode CaloGPUClusterAndCellDataMonitor::update_plots(const EventContext & ctx,
227 const ConstantDataHolder & constant_data,
228 const xAOD::CaloClusterContainer * /*cluster_collection_ptr*/,
229 const EventDataHolder & event_data,
230 const CaloClusterGPUProcessor * tool) const
231{
232 if (filter_tool_by_name(tool->name()))
233 {
236
237 std::vector<int> cells_prefix_sum;
238
239 ATH_CHECK(update_cell_representation(ctx, constant_data, cell_info, clusters, cells_prefix_sum));
240
241 return add_data(ctx, constant_data, cell_info, clusters, cells_prefix_sum, tool->name());
242 }
243 else
244 {
245 return StatusCode::SUCCESS;
246 }
247}
248
249StatusCode CaloGPUClusterAndCellDataMonitor::update_plots(const EventContext & ctx,
250 const ConstantDataHolder & constant_data,
251 const xAOD::CaloClusterContainer * cluster_collection_ptr,
252 const EventDataHolder & /*event_data*/,
253 const ICaloClusterGPUOutputTransformer * tool) const
254{
255 if (filter_tool_by_name(tool->name()))
256 {
257 SG::ReadHandle<CaloCellContainer> cell_collection(m_cellsKey, ctx);
258
260
261 ed.allocate(false);
262
263 ed.importCells(static_cast<const CaloCellContainer *>(&(*cell_collection)), m_missingCellsToFill);
264
265 ed.importClusters(cluster_collection_ptr, MomentsOptionsArray::all(), false, true, true, true, m_missingCellsToFill);
266
267 std::vector<int> cells_prefix_sum;
268
269 ATH_CHECK(update_cell_representation(ctx, constant_data, ed.m_cell_info, ed.m_clusters, cells_prefix_sum));
270
271 return add_data(ctx, constant_data, ed.m_cell_info, ed.m_clusters, cells_prefix_sum, tool->name());
272 }
273 else
274 {
275 return StatusCode::SUCCESS;
276 }
277}
278
279bool CaloGPUClusterAndCellDataMonitor::filter_tool_by_name(const std::string & tool_name) const
280{
281 ATH_MSG_DEBUG("Checking : '" << tool_name << "': " << m_toolsToCheckFor.count(tool_name));
282 return m_toolsToCheckFor.count(tool_name) > 0;
283}
284
285
286
287
290 const CaloRecGPU::CellInfoArr * cell_info,
292 std::vector<int> & cells_prefix_sum) const
293{
294 if (!clusters->has_cells_per_cluster())
295 {
296 for (int i = 0; i <= clusters->number; ++i)
297 {
298 clusters->cellsPrefixSum[i] = 0;
299 }
300
301 for (int i = 0; i < clusters->number_cells; ++i)
302 {
303 clusters->get_extra_cell_info(i) = clusters->cells.tags[i];
304 //We overwrite some non-calculated moments that we shouldn't even have
305 //at this point...
306 }
307
308 const int old_num_cells = clusters->number_cells;
309 clusters->number_cells = 0;
310 for (int i = 0; i < old_num_cells; ++i)
311 {
312 ClusterTag this_tag = clusters->get_extra_cell_info(i);
313
314 const int first_cluster = this_tag.is_part_of_cluster() ? this_tag.cluster_index() : -1;
315
316 const int second_cluster = this_tag.is_part_of_cluster() && this_tag.is_shared_between_clusters() ? this_tag.secondary_cluster_index() : -1;
317
318 const float secondary_cluster_weight = (this_tag.is_part_of_cluster() && this_tag.is_shared_between_clusters() ?
319 float_unhack(this_tag.secondary_cluster_weight()) : 0.f);
320
321 if (second_cluster >= 0)
322 {
323 if (second_cluster >= clusters->number)
324 {
325 ATH_MSG_WARNING("Impossible cell assignment: " << i << " " << second_cluster << " (" << std::hex << this_tag << std::dec << ")");
326 }
327 clusters->cells.indices[clusters->number_cells] = i;
328 clusters->cellWeights[clusters->number_cells] = secondary_cluster_weight;
329 clusters->clusterIndices[clusters->number_cells] = second_cluster;
330 clusters->number_cells += 1;
331 clusters->cellsPrefixSum[second_cluster + 1] += 1;
332 }
333
334 if (first_cluster >= 0)
335 {
336 if (second_cluster >= clusters->number)
337 {
338 ATH_MSG_WARNING("Impossible cell assignment: " << i << " " << first_cluster << " (" << std::hex << this_tag << std::dec << ")");
339 }
340 clusters->cells.indices[clusters->number_cells] = i;
341 clusters->cellWeights[clusters->number_cells] = 1.0f - secondary_cluster_weight;
342 clusters->clusterIndices[clusters->number_cells] = first_cluster;
343 clusters->number_cells += 1;
344 clusters->cellsPrefixSum[first_cluster + 1] += 1;
345 }
346 }
347 int prefix = 0;
348 for (int i = 0; i <= clusters->number; ++i)
349 {
350 prefix += clusters->cellsPrefixSum[i];
351
352 clusters->cellsPrefixSum[i] = prefix;
353 }
354 }
355
356 //Do note that, from here on, the assignment between cells and clusters is broken:
357 //we simply have a list of cells in clusters...
358
359 std::vector<int> cell_orderer(clusters->number_cells);
360
361 std::iota(cell_orderer.begin(), cell_orderer.end(), 0);
362
363 std::sort(cell_orderer.begin(), cell_orderer.end(), [&](const int a, const int b)
364 {
365 if (clusters->cells.indices[a] == clusters->cells.indices[b])
366 {
367 return clusters->cellWeights[a] < clusters->cellWeights[b];
368 }
369 else
370 {
371 const int hash_ID_a = cell_info->get_hash_ID(clusters->cells.indices[a]);
372 const int hash_ID_b = cell_info->get_hash_ID(clusters->cells.indices[b]);
373 if (hash_ID_a < 0)
374 {
375 ATH_MSG_WARNING("Attempting to sort impossible cell: " << a << " " << hash_ID_a);
376 }
377 if (hash_ID_b < 0)
378 {
379 ATH_MSG_WARNING("Attempting to sort impossible cell: " << b << " " << hash_ID_b);
380 }
381 return hash_ID_a < hash_ID_b;
382 }
383 } );
384
385 auto order_array = [&](auto * ptr)
386 {
387 std::vector<std::decay_t<decltype(ptr[0])>> prev(clusters->number_cells);
388
389 for (int i = 0; i < clusters->number_cells; ++i)
390 {
391 prev[i] = ptr[i];
392 }
393
394 for (int i = 0; i < clusters->number_cells; ++i)
395 {
396 ptr[i] = prev[cell_orderer[i]];
397 }
398 };
399
400 order_array(clusters->cells.indices);
401 order_array(clusters->cellWeights);
402 order_array(clusters->clusterIndices);
403
404 cells_prefix_sum.clear();
405 cells_prefix_sum.resize(NCaloCells + 1, 0);
406
407 int prev_cell_index = -1;
408 int cell_count = 0;
409
410 for (int i = 0; i < clusters->number_cells; ++i)
411 {
412 const int this_cell_index = clusters->cells.indices[i];
413
414 if (this_cell_index != prev_cell_index)
415 {
416 //prev_cell_index is used directly as an index into a c-style array, so must
417 //not be negative (should also check upper bound?)
418 const int prev_cell_ID = (prev_cell_index < 0 ? -1 : cell_info->get_hash_ID(prev_cell_index));
419 const int this_cell_ID = cell_info->get_hash_ID(this_cell_index);
420
421 for (int j = prev_cell_ID + 1; j <= this_cell_ID; ++j)
422 {
423 cells_prefix_sum[j] = cell_count;
424 }
425 }
426
427 ++cell_count;
428
429 prev_cell_index = this_cell_index;
430 }
431
432 if (clusters->number_cells > 0)
433 {
434 for (int i = cell_info->get_hash_ID(clusters->cells.indices[clusters->number_cells - 1]); i <= NCaloCells; ++i)
435 {
436 cells_prefix_sum[i + 1] = cell_count;
437 }
438 }
439
440 return StatusCode::SUCCESS;
441}
442
443
444//WeighMatch takes as arguments the cell index
445//and two vectors of pairs of cluster index and cell weight,
446//for the reference and test assignments.
447//WeighMatch takes as arguments a bool that indicates
448//whether this assignment is for test (false for reference),
449//and a vector of pairs of cluster index and cell weight.
450template <class WeighMatch, class WeighNotMatch>
451static void build_similarity_map_helper(const CaloRecGPU::CellInfoArr & /*cell_info_1*/,
452 const CaloRecGPU::CellInfoArr & /*cell_info_2*/,
453 const std::vector<int> & cells_prefix_sum_1,
454 const std::vector<int> & cells_prefix_sum_2,
455 const CaloRecGPU::ClusterInfoArr & cluster_info_1,
456 const CaloRecGPU::ClusterInfoArr & cluster_info_2,
457 WeighMatch match,
458 WeighNotMatch not_match)
459{
460 std::vector<std::pair<int, float>> cluster_weights_1, cluster_weights_2;
461
462 for (unsigned int this_hash_ID = 0; this_hash_ID < NCaloCells; ++this_hash_ID)
463 {
464 cluster_weights_1.clear();
465 cluster_weights_2.clear();
466
467 for (int i = cells_prefix_sum_1[this_hash_ID]; i < cells_prefix_sum_1[this_hash_ID + 1]; ++i)
468 {
469 cluster_weights_1.push_back({cluster_info_1.clusterIndices[i], cluster_info_1.cellWeights[i] + 1e-8});
470 }
471 for (int i = cells_prefix_sum_2[this_hash_ID]; i < cells_prefix_sum_2[this_hash_ID + 1]; ++i)
472 {
473 cluster_weights_2.push_back({cluster_info_2.clusterIndices[i], cluster_info_2.cellWeights[i] + 1e-8});
474 }
475
476 if (cluster_weights_1.size() != 0 && cluster_weights_2.size() != 0)
477 {
478 match(this_hash_ID, cluster_weights_1, cluster_weights_2);
479 }
480 else if (cluster_weights_1.size() != 0)
481 {
482 not_match(false, this_hash_ID, cluster_weights_1);
483 }
484 else if (cluster_weights_2.size() != 0)
485 {
486 not_match(true, this_hash_ID, cluster_weights_2);
487 }
488 }
489}
490
492 const CaloRecGPU::ConstantDataHolder & constant_data,
493 const CaloRecGPU::CellInfoArr & cell_info_1,
494 const CaloRecGPU::CellInfoArr & cell_info_2,
495 const std::vector<int> & cells_prefix_sum_1,
496 const std::vector<int> & cells_prefix_sum_2,
497 const CaloRecGPU::ClusterInfoArr & cluster_info_1,
498 const CaloRecGPU::ClusterInfoArr & cluster_info_2,
499 const bool match_in_energy,
500 const bool match_without_shared) const
501{
502 sch.r2t_table.clear();
503 sch.r2t_table.resize(cluster_info_1.number, -1);
504
505 sch.t2r_table.clear();
506 sch.t2r_table.resize(cluster_info_2.number, -1);
507
508 std::vector<double> similarity_map(cluster_info_1.number * cluster_info_2.number, 0.);
509
510 std::vector<double> ref_normalization(cluster_info_1.number, 0.);
511 std::vector<double> test_normalization(cluster_info_2.number, 0.);
512
513 auto calculate_weight = [&](const int cell)
514 {
515 double SNR = 0.00001;
516
517 if (!cell_info_1.is_bad(cell))
518 {
519 const int gain = cell_info_1.gain[cell];
520
521 const double cellNoise = constant_data.m_cell_noise->get_noise(cell_info_1.get_hash_ID(cell), gain);
522 if (std::isfinite(cellNoise) && cellNoise > 0.0f)
523 {
524 SNR = std::abs(cell_info_1.energy[cell] / cellNoise);
525 }
526 }
527
528 const double quantity = ( match_in_energy ? std::abs(cell_info_1.energy[cell]) : SNR );
529 const double weight = (quantity + 1e-7) *
530 ( SNR > m_seedThreshold ? (match_in_energy ? 1000 : m_seed_weight) :
531 (
532 SNR > m_growThreshold ? (match_in_energy ? 950 : m_grow_weight) :
533 (
534 SNR > m_termThreshold ? (match_in_energy ? 900 : m_terminal_weight) : (match_in_energy ? 100 : 1e-8)
535 )
536 )
537 );
538
539 return weight + 1e-8;
540 };
541
542 auto matched_clusters = [&](const int hash_ID, const std::vector<std::pair<int, float>> & v1, const std::vector<std::pair<int, float>> & v2)
543 {
544#if CALORECGPU_DATA_MONITOR_EXTRA_PRINTOUTS && CALORECGPU_DATA_MONITOR_EXTRA_PRINTOUTS > 1
545 msg(MSG::INFO) << "MATCH: " << hash_ID << " " << calculate_weight(cell_info_1.get_cell_with_hash_ID(hash_ID)) << " |";
546 for (const auto & p : v1)
547 {
548 msg() << " (" << p.first << ", " << p.second << ")";
549 }
550 msg() << " |";
551 for (const auto & p : v2)
552 {
553 msg() << " (" << p.first << ", " << p.second << ")";
554 }
555 msg() << endmsg;
556#endif
557
558 if (match_without_shared && (v1.size() > 1 || v2.size() > 1))
559 {
560 return;
561 }
562
563 const float weight = calculate_weight(cell_info_1.get_cell_with_hash_ID(hash_ID));
564
565 for (const auto & p1 : v1)
566 {
567 for (const auto & p2 : v2)
568 {
569 similarity_map[p2.first * cluster_info_1.number + p1.first] += weight * p1.second * p2.second;
570 }
571 }
572
573 for (const auto & p1 : v1)
574 {
575 ref_normalization[p1.first] += weight * p1.second * p1.second;
576 }
577
578 for (const auto & p2 : v2)
579 {
580 test_normalization[p2.first] += weight * p2.second * p2.second;
581 }
582 };
583
584 auto unmatched_clusters = [&](const bool is_test, const int hash_ID, const std::vector<std::pair<int, float>> & v)
585 {
586#if CALORECGPU_DATA_MONITOR_EXTRA_PRINTOUTS
587 msg(MSG::INFO) << "UNMATCH: " << hash_ID << " " << calculate_weight(cell_info_1.get_cell_with_hash_ID(hash_ID)) << " | " << is_test << " |";
588 for (const auto & p : v)
589 {
590 msg() << " (" << p.first << ", " << p.second << ")";
591 }
592 msg() << endmsg;
593#endif
594
595 if (match_without_shared && v.size() > 1)
596 {
597 return;
598 }
599
600 const float weight = calculate_weight(cell_info_1.get_cell_with_hash_ID(hash_ID));
601
602 std::vector<double> & normalization = (is_test ? test_normalization : ref_normalization);
603
604 for (const auto & p : v)
605 {
606 normalization[p.first] += weight * p.second * p.second;
607 }
608 };
609
610 build_similarity_map_helper(cell_info_1, cell_info_2,
611 cells_prefix_sum_1, cells_prefix_sum_2,
612 cluster_info_1, cluster_info_2,
613 matched_clusters, unmatched_clusters);
614
615 for (int testc = 0; testc < cluster_info_2.number; ++testc)
616 {
617 const double test_norm = test_normalization[testc] + double(test_normalization[testc] == 0.);
618 for (int refc = 0; refc < cluster_info_1.number; ++refc)
619 {
620 const double ref_norm = ref_normalization[refc] + double(ref_normalization[refc] == 0.);
621 similarity_map[testc * cluster_info_1.number + refc] /= std::sqrt(ref_norm * test_norm);
622 }
623 }
624
625 //In essence, the Gale-Shapley Algorithm
626
627 std::vector<std::vector<int>> sorted_GPU_matches;
628
629 sorted_GPU_matches.reserve(cluster_info_2.number);
630
631 for (int testc = 0; testc < cluster_info_2.number; ++testc)
632 {
633 std::vector<int> sorter(cluster_info_1.number);
634 std::iota(sorter.begin(), sorter.end(), 0);
635
636 std::sort(sorter.begin(), sorter.end(),
637 [&](const int a, const int b)
638 {
639 const double a_weight = similarity_map[testc * cluster_info_1.number + a];
640 const double b_weight = similarity_map[testc * cluster_info_1.number + b];
641 return a_weight > b_weight;
642 }
643 );
644
645 size_t wanted_size = 0;
646
647 for (; wanted_size < sorter.size(); ++wanted_size)
648 {
649 const double match_weight = similarity_map[testc * cluster_info_1.number + sorter[wanted_size]];
650 if (match_weight < m_min_similarity)
651 {
652 break;
653 }
654 }
655
656 //Yeah, we could do a binary search for best worst-case complexity,
657 //but we are expecting 1~2 similar clusters and the rest garbage,
658 //so we're expecting only 1~2 iterations.
659 //This actually means all that sorting is way way overkill,
660 //but we must make sure in the most general case that this works...
661
662 sorter.resize(wanted_size);
663
664 sorted_GPU_matches.push_back(std::move(sorter));
665 }
666
667 int num_iter = 0;
668
669 constexpr int max_iter = 32;
670
671 std::vector<double> matched_weights(cluster_info_1.number, -1.);
672
673 std::vector<size_t> skipped_matching(cluster_info_2.number, 0);
674
675 for (int stop_counter = 0; stop_counter < cluster_info_2.number && num_iter < max_iter; ++num_iter)
676 {
677 stop_counter = 0;
678 for (int testc = 0; testc < int(sorted_GPU_matches.size()); ++testc)
679 {
680 if (skipped_matching[testc] < sorted_GPU_matches[testc].size())
681 {
682 const int match_c = sorted_GPU_matches[testc][skipped_matching[testc]];
683 const double match_weight = similarity_map[testc * cluster_info_1.number + match_c];
684 if (match_weight >= m_min_similarity && match_weight > matched_weights[match_c])
685 {
686 const int prev_match = sch.r2t_table[match_c];
687 if (prev_match >= 0)
688 {
689 ++skipped_matching[prev_match];
690 --stop_counter;
691 }
692 sch.r2t_table[match_c] = testc;
693 matched_weights[match_c] = match_weight;
694 ++stop_counter;
695 }
696 else
697 {
698 ++skipped_matching[testc];
699 }
700 }
701 else
702 {
703 ++stop_counter;
704 }
705 }
706 }
707
708 sch.unmatched_ref_list.clear();
709 sch.unmatched_test_list.clear();
710
711 for (size_t i = 0; i < sch.r2t_table.size(); ++i)
712 {
713 const int match = sch.r2t_table[i];
714 if (match < 0)
715 {
716 sch.unmatched_ref_list.push_back(i);
717 }
718 else
719 {
720 sch.t2r_table[match] = i;
721 }
722 }
723
724 for (size_t i = 0; i < sch.t2r_table.size(); ++i)
725 {
726 if (sch.t2r_table[i] < 0)
727 {
728 sch.unmatched_test_list.push_back(i);
729 }
730 }
731
732 {
733 char message_buffer[256];
734 snprintf(message_buffer, 256,
735 "%2d: %5d / %5d || %5d / %5d || %3d || %5d | %5d || %5d",
736 num_iter,
737 int(sch.r2t_table.size()) - int(sch.unmatched_ref_list.size()), int(sch.r2t_table.size()),
738 int(sch.t2r_table.size()) - int(sch.unmatched_test_list.size()), int(sch.t2r_table.size()),
739 int(sch.r2t_table.size()) - int(sch.t2r_table.size()),
740 int(sch.unmatched_ref_list.size()),
741 int(sch.unmatched_test_list.size()),
742 int(sch.unmatched_ref_list.size()) - int(sch.unmatched_test_list.size())
743 );
744 ATH_MSG_INFO(message_buffer);
745 }
746
747 return StatusCode::SUCCESS;
748
749}
750
752 const CaloRecGPU::ConstantDataHolder & /*constant_data*/,
753 const CaloRecGPU::CellInfoArr & cell_info_1,
754 const CaloRecGPU::CellInfoArr & cell_info_2,
755 const std::vector<int> & cells_prefix_sum_1,
756 const std::vector<int> & cells_prefix_sum_2,
757 const CaloRecGPU::ClusterInfoArr & cluster_info_1,
758 const CaloRecGPU::ClusterInfoArr & cluster_info_2,
759 const bool match_without_shared) const
760{
761 sch.r2t_table.clear();
762 sch.r2t_table.resize(cluster_info_1.number, -1);
763
764 sch.t2r_table.clear();
765 sch.t2r_table.resize(cluster_info_2.number, -1);
766
767 std::vector<char> match_possibilities(cluster_info_1.number * cluster_info_2.number, 1);
768
769 auto matched_clusters = [&]([[maybe_unused]] const int hash_ID, const std::vector<std::pair<int, float>> & v1, const std::vector<std::pair<int, float>> & v2)
770 {
771#if CALORECGPU_DATA_MONITOR_EXTRA_PRINTOUTS && CALORECGPU_DATA_MONITOR_EXTRA_PRINTOUTS > 1
772 msg(MSG::INFO) << "MATCH: " << hash_ID << " <> |";
773 for (const auto & p : v1)
774 {
775 msg() << " (" << p.first << ", " << p.second << ")";
776 }
777 msg() << " |";
778 for (const auto & p : v2)
779 {
780 msg() << " (" << p.first << ", " << p.second << ")";
781 }
782 msg() << endmsg;
783#endif
784
785 if (match_without_shared && (v1.size() > 1 || v2.size() > 1))
786 {
787 return;
788 }
789
790 for (const auto & t_p : v2)
791 {
792 for (int rc = 0; rc < cluster_info_1.number; ++rc)
793 {
794 bool is_possibility = false;
795
796 for (const auto & p: v1)
797 {
798 if (p.first == rc)
799 {
800 is_possibility = true;
801 break;
802 }
803 }
804
805 if (is_possibility)
806 {
807 continue;
808 }
809
810 match_possibilities[t_p.first * cluster_info_1.number + rc] = 0;
811 }
812 }
813
814 for (const auto & r_p : v1)
815 {
816 for (int tc = 0; tc < cluster_info_2.number; ++tc)
817 {
818 bool is_possibility = false;
819
820 for (const auto & p: v2)
821 {
822 if (p.first == tc)
823 {
824 is_possibility = true;
825 break;
826 }
827 }
828
829 if (is_possibility)
830 {
831 continue;
832 }
833
834 match_possibilities[tc * cluster_info_1.number + r_p.first] = 0;
835 }
836 }
837 };
838
839 auto unmatched_clusters = [&](const bool is_test, [[maybe_unused]] const int hash_ID, const std::vector<std::pair<int, float>> & v)
840 {
841#if CALORECGPU_DATA_MONITOR_EXTRA_PRINTOUTS
842 msg(MSG::INFO) << "UNMATCH: " << hash_ID << " <> | " << is_test << " |";
843 for (const auto & p : v)
844 {
845 msg() << " (" << p.first << ", " << p.second << ")";
846 }
847 msg() << endmsg;
848#endif
849
850 if (match_without_shared && v.size() > 1)
851 {
852 return;
853 }
854
855 const int cluster_number = is_test ? cluster_info_2.number : cluster_info_1.number;
856
857 for (const auto & p : v)
858 {
859 for (int i = 0; i < cluster_number; ++i)
860 {
861 const int this_index = (is_test ? p.first * cluster_info_1.number + i : i * cluster_info_1.number + p.first);
862 match_possibilities[this_index] = 0;
863 }
864 }
865 };
866
867 build_similarity_map_helper(cell_info_1, cell_info_2,
868 cells_prefix_sum_1, cells_prefix_sum_2,
869 cluster_info_1, cluster_info_2,
870 matched_clusters, unmatched_clusters);
871
872 for (int testc = 0; testc < cluster_info_2.number; ++testc)
873 {
874 for (int refc = 0; refc < cluster_info_1.number; ++refc)
875 {
876 if (match_possibilities[testc * cluster_info_1.number + refc] > 0)
877 {
878 sch.r2t_table[refc] = testc;
879 sch.t2r_table[testc] = refc;
880 }
881 }
882 }
883
884 for (int refc = 0; refc < cluster_info_1.number; ++refc)
885 {
886 if (sch.r2t_table[refc] < 0)
887 {
888 sch.unmatched_ref_list.push_back(refc);
889 }
890 }
891
892 for (int testc = 0; testc < cluster_info_2.number; ++testc)
893 {
894 if (sch.t2r_table[testc] < 0)
895 {
896 sch.unmatched_test_list.push_back(testc);
897 }
898 }
899
900 {
901 char message_buffer[256];
902 snprintf(message_buffer, 256,
903 "%2d: %5d / %5d || %5d / %5d || %3d || %5d | %5d || %5d",
904 0,
905 int(sch.r2t_table.size()) - int(sch.unmatched_ref_list.size()), int(sch.r2t_table.size()),
906 int(sch.t2r_table.size()) - int(sch.unmatched_test_list.size()), int(sch.t2r_table.size()),
907 int(sch.r2t_table.size()) - int(sch.t2r_table.size()),
908 int(sch.unmatched_ref_list.size()),
909 int(sch.unmatched_test_list.size()),
910 int(sch.unmatched_ref_list.size()) - int(sch.unmatched_test_list.size())
911 );
912 ATH_MSG_INFO(message_buffer);
913 }
914
915 return StatusCode::SUCCESS;
916
917}
918
919namespace
920{
921
923 {
924#define CALORECGPU_BASIC_CLUSTER_PROPERTY(NAME, ...) \
925 struct clusters_ ## NAME \
926 { \
927 static std::string name() \
928 { \
929 return # NAME; \
930 } \
931 static double get_property([[maybe_unused]] const ConstantDataHolder & constant_data, \
932 [[maybe_unused]] const CaloRecGPU::CellInfoArr & cell_info, \
933 [[maybe_unused]] const CaloRecGPU::ClusterInfoArr & cluster_info, \
934 [[maybe_unused]] const std::vector<int> & cells_prefix_sum, \
935 [[maybe_unused]] const int cluster_index ) \
936 { \
937 __VA_ARGS__ \
938 } \
939 };
940
941 CALORECGPU_BASIC_CLUSTER_PROPERTY(index, return cluster_index;)
942
943 CALORECGPU_BASIC_CLUSTER_PROPERTY(E, return cluster_info.clusterEnergy[cluster_index] / CLHEP::MeV;)
944
945 CALORECGPU_BASIC_CLUSTER_PROPERTY(abs_E, return std::abs(cluster_info.clusterEnergy[cluster_index]) / CLHEP::MeV;)
946
947 CALORECGPU_BASIC_CLUSTER_PROPERTY(Et, return cluster_info.clusterEt[cluster_index] / CLHEP::MeV;)
948
949 CALORECGPU_BASIC_CLUSTER_PROPERTY(eta, return cluster_info.clusterEta[cluster_index];)
950
951 CALORECGPU_BASIC_CLUSTER_PROPERTY(phi, return cluster_info.clusterPhi[cluster_index];)
952
953 CALORECGPU_BASIC_CLUSTER_PROPERTY(number_cells, return cluster_info.cellsPrefixSum[cluster_index + 1] - cluster_info.cellsPrefixSum[cluster_index];)
954
955 //CALORECGPU_BASIC_CLUSTER_PROPERTY(time, return cluster_moments.time[cluster_index] / CLHEP::us;)
956
957#define CALORECGPU_CLUSTER_MOMENT(...) CALORECGPU_CLUSTER_MOMENT_INNER(__VA_ARGS__, 1, 1)
958#define CALORECGPU_CLUSTER_MOMENT_INNER(NAME, PROPERTY, UNIT, ...) CALORECGPU_BASIC_CLUSTER_PROPERTY(moments_ ## NAME, return cluster_info.moments. PROPERTY [cluster_index] / UNIT;)
959
960 CALORECGPU_CLUSTER_MOMENT(time, time, CLHEP::us)
961 CALORECGPU_CLUSTER_MOMENT(FIRST_PHI, firstPhi)
962 CALORECGPU_CLUSTER_MOMENT(FIRST_ETA, firstEta)
963 CALORECGPU_CLUSTER_MOMENT(SECOND_R, secondR)
964 CALORECGPU_CLUSTER_MOMENT(SECOND_LAMBDA, secondLambda)
966 CALORECGPU_CLUSTER_MOMENT(DELTA_THETA, deltaTheta)
967 CALORECGPU_CLUSTER_MOMENT(DELTA_ALPHA, deltaAlpha)
968 CALORECGPU_CLUSTER_MOMENT(CENTER_X, centerX)
969 CALORECGPU_CLUSTER_MOMENT(CENTER_Y, centerY)
970 CALORECGPU_CLUSTER_MOMENT(CENTER_Z, centerZ)
971 CALORECGPU_CLUSTER_MOMENT(CENTER_MAG, centerMag)
972 CALORECGPU_CLUSTER_MOMENT(CENTER_LAMBDA, centerLambda)
973 CALORECGPU_CLUSTER_MOMENT(LATERAL, lateral)
974 CALORECGPU_CLUSTER_MOMENT(LONGITUDINAL, longitudinal)
975 CALORECGPU_CLUSTER_MOMENT(ENG_FRAC_EM, engFracEM)
976 CALORECGPU_CLUSTER_MOMENT(ENG_FRAC_MAX, engFracMax)
977 CALORECGPU_CLUSTER_MOMENT(ENG_FRAC_CORE, engFracCore)
978 CALORECGPU_CLUSTER_MOMENT(FIRST_ENG_DENS, firstEngDens)
979 CALORECGPU_CLUSTER_MOMENT(SECOND_ENG_DENS, secondEngDens)
980 CALORECGPU_CLUSTER_MOMENT(ISOLATION, isolation)
981 CALORECGPU_CLUSTER_MOMENT(ENG_BAD_CELLS, engBadCells)
982 CALORECGPU_CLUSTER_MOMENT(N_BAD_CELLS, nBadCells)
983 CALORECGPU_CLUSTER_MOMENT(N_BAD_CELLS_CORR, nBadCellsCorr)
984 CALORECGPU_CLUSTER_MOMENT(BAD_CELLS_CORR_E, badCellsCorrE)
985 CALORECGPU_CLUSTER_MOMENT(BADLARQ_FRAC, badLArQFrac)
986 CALORECGPU_CLUSTER_MOMENT(ENG_POS, engPos)
987 CALORECGPU_CLUSTER_MOMENT(SIGNIFICANCE, significance)
988 CALORECGPU_CLUSTER_MOMENT(CELL_SIGNIFICANCE, cellSignificance)
989 CALORECGPU_CLUSTER_MOMENT(CELL_SIG_SAMPLING, cellSigSampling)
990 CALORECGPU_CLUSTER_MOMENT(AVG_LAR_Q, avgLArQ)
991 CALORECGPU_CLUSTER_MOMENT(AVG_TILE_Q, avgTileQ)
992 CALORECGPU_CLUSTER_MOMENT(ENG_BAD_HV_CELLS, engBadHVCells)
993 CALORECGPU_CLUSTER_MOMENT(N_BAD_HV_CELLS, nBadHVCells)
995 CALORECGPU_CLUSTER_MOMENT(MASS, mass)
996 CALORECGPU_CLUSTER_MOMENT(EM_PROBABILITY, EMProbability)
997 CALORECGPU_CLUSTER_MOMENT(HAD_WEIGHT, hadWeight)
998 CALORECGPU_CLUSTER_MOMENT(OOC_WEIGHT, OOCweight)
999 CALORECGPU_CLUSTER_MOMENT(DM_WEIGHT, DMweight)
1000 CALORECGPU_CLUSTER_MOMENT(TILE_CONFIDENCE_LEVEL, tileConfidenceLevel)
1001 CALORECGPU_CLUSTER_MOMENT(SECOND_TIME, secondTime)
1002 CALORECGPU_CLUSTER_MOMENT(VERTEX_FRACTION, vertexFraction)
1003 CALORECGPU_CLUSTER_MOMENT(NVERTEX_FRACTION, nVertexFraction)
1004 CALORECGPU_CLUSTER_MOMENT(ETACALOFRAME, etaCaloFrame)
1005 CALORECGPU_CLUSTER_MOMENT(PHICALOFRAME, phiCaloFrame)
1006 CALORECGPU_CLUSTER_MOMENT(ETA1CALOFRAME, eta1CaloFrame)
1007 CALORECGPU_CLUSTER_MOMENT(PHI1CALOFRAME, phi1CaloFrame)
1008 CALORECGPU_CLUSTER_MOMENT(ETA2CALOFRAME, eta2CaloFrame)
1009 CALORECGPU_CLUSTER_MOMENT(PHI2CALOFRAME, phi2CaloFrame)
1010 CALORECGPU_CLUSTER_MOMENT(ENG_CALIB_TOT, engCalibTot)
1011 CALORECGPU_CLUSTER_MOMENT(ENG_CALIB_OUT_L, engCalibOutL)
1012 CALORECGPU_CLUSTER_MOMENT(ENG_CALIB_OUT_M, engCalibOutM)
1013 CALORECGPU_CLUSTER_MOMENT(ENG_CALIB_OUT_T, engCalibOutT)
1014 CALORECGPU_CLUSTER_MOMENT(ENG_CALIB_DEAD_L, engCalibDeadL)
1015 CALORECGPU_CLUSTER_MOMENT(ENG_CALIB_DEAD_M, engCalibDeadM)
1016 CALORECGPU_CLUSTER_MOMENT(ENG_CALIB_DEAD_T, engCalibDeadT)
1017 CALORECGPU_CLUSTER_MOMENT(ENG_CALIB_EMB0, engCalibEMB0)
1018 CALORECGPU_CLUSTER_MOMENT(ENG_CALIB_EME0, engCalibEME0)
1019 CALORECGPU_CLUSTER_MOMENT(ENG_CALIB_TILEG3, engCalibTileG3)
1020 CALORECGPU_CLUSTER_MOMENT(ENG_CALIB_DEAD_TOT, engCalibDeadTot)
1021 CALORECGPU_CLUSTER_MOMENT(ENG_CALIB_DEAD_EMB0, engCalibDeadEMB0)
1022 CALORECGPU_CLUSTER_MOMENT(ENG_CALIB_DEAD_TILE0, engCalibDeadTile0)
1023 CALORECGPU_CLUSTER_MOMENT(ENG_CALIB_DEAD_TILEG3, engCalibDeadTileG3)
1024 CALORECGPU_CLUSTER_MOMENT(ENG_CALIB_DEAD_EME0, engCalibDeadEME0)
1025 CALORECGPU_CLUSTER_MOMENT(ENG_CALIB_DEAD_HEC0, engCalibDeadHEC0)
1026 CALORECGPU_CLUSTER_MOMENT(ENG_CALIB_DEAD_FCAL, engCalibDeadFCAL)
1027 CALORECGPU_CLUSTER_MOMENT(ENG_CALIB_DEAD_LEAKAGE, engCalibDeadLeakage)
1028 CALORECGPU_CLUSTER_MOMENT(ENG_CALIB_DEAD_UNCLASS, engCalibDeadUnclass)
1029 CALORECGPU_CLUSTER_MOMENT(ENG_CALIB_FRAC_EM, engCalibFracEM)
1030 CALORECGPU_CLUSTER_MOMENT(ENG_CALIB_FRAC_HAD, engCalibFracHad)
1031 CALORECGPU_CLUSTER_MOMENT(ENG_CALIB_FRAC_REST, engCalibFracRest)
1032
1033 using BasicClusterProperties = multi_class_holder <
1034
1035 clusters_index,
1036 clusters_E,
1037 clusters_abs_E,
1038 clusters_Et,
1039 clusters_eta,
1040 clusters_phi,
1041 clusters_number_cells,
1042 clusters_moments_time,
1043 clusters_moments_FIRST_PHI,
1044 clusters_moments_FIRST_ETA,
1045 clusters_moments_SECOND_R,
1046 clusters_moments_SECOND_LAMBDA,
1047 clusters_moments_DELTA_PHI,
1048 clusters_moments_DELTA_THETA,
1049 clusters_moments_DELTA_ALPHA,
1050 clusters_moments_CENTER_X,
1051 clusters_moments_CENTER_Y,
1052 clusters_moments_CENTER_Z,
1053 clusters_moments_CENTER_MAG,
1054 clusters_moments_CENTER_LAMBDA,
1055 clusters_moments_LATERAL,
1056 clusters_moments_LONGITUDINAL,
1057 clusters_moments_ENG_FRAC_EM,
1058 clusters_moments_ENG_FRAC_MAX,
1059 clusters_moments_ENG_FRAC_CORE,
1060 clusters_moments_FIRST_ENG_DENS,
1061 clusters_moments_SECOND_ENG_DENS,
1062 clusters_moments_ISOLATION,
1063 clusters_moments_ENG_BAD_CELLS,
1064 clusters_moments_N_BAD_CELLS,
1065 clusters_moments_N_BAD_CELLS_CORR,
1066 clusters_moments_BAD_CELLS_CORR_E,
1067 clusters_moments_BADLARQ_FRAC,
1068 clusters_moments_ENG_POS,
1069 clusters_moments_SIGNIFICANCE,
1070 clusters_moments_CELL_SIGNIFICANCE,
1071 clusters_moments_CELL_SIG_SAMPLING,
1072 clusters_moments_AVG_LAR_Q,
1073 clusters_moments_AVG_TILE_Q,
1074 clusters_moments_ENG_BAD_HV_CELLS,
1075 clusters_moments_N_BAD_HV_CELLS,
1076 clusters_moments_PTD,
1077 clusters_moments_MASS,
1078 clusters_moments_EM_PROBABILITY,
1079 clusters_moments_HAD_WEIGHT,
1080 clusters_moments_OOC_WEIGHT,
1081 clusters_moments_DM_WEIGHT,
1082 clusters_moments_TILE_CONFIDENCE_LEVEL,
1083 clusters_moments_SECOND_TIME,
1084 clusters_moments_VERTEX_FRACTION,
1085 clusters_moments_NVERTEX_FRACTION,
1086 clusters_moments_ETACALOFRAME,
1087 clusters_moments_PHICALOFRAME,
1088 clusters_moments_ETA1CALOFRAME,
1089 clusters_moments_PHI1CALOFRAME,
1090 clusters_moments_ETA2CALOFRAME,
1091 clusters_moments_PHI2CALOFRAME,
1092 clusters_moments_ENG_CALIB_TOT,
1093 clusters_moments_ENG_CALIB_OUT_L,
1094 clusters_moments_ENG_CALIB_OUT_M,
1095 clusters_moments_ENG_CALIB_OUT_T,
1096 clusters_moments_ENG_CALIB_DEAD_L,
1097 clusters_moments_ENG_CALIB_DEAD_M,
1098 clusters_moments_ENG_CALIB_DEAD_T,
1099 clusters_moments_ENG_CALIB_EMB0,
1100 clusters_moments_ENG_CALIB_EME0,
1101 clusters_moments_ENG_CALIB_TILEG3,
1102 clusters_moments_ENG_CALIB_DEAD_TOT,
1103 clusters_moments_ENG_CALIB_DEAD_EMB0,
1104 clusters_moments_ENG_CALIB_DEAD_TILE0,
1105 clusters_moments_ENG_CALIB_DEAD_TILEG3,
1106 clusters_moments_ENG_CALIB_DEAD_EME0,
1107 clusters_moments_ENG_CALIB_DEAD_HEC0,
1108 clusters_moments_ENG_CALIB_DEAD_FCAL,
1109 clusters_moments_ENG_CALIB_DEAD_LEAKAGE,
1110 clusters_moments_ENG_CALIB_DEAD_UNCLASS,
1111 clusters_moments_ENG_CALIB_FRAC_EM,
1112 clusters_moments_ENG_CALIB_FRAC_HAD,
1113 clusters_moments_ENG_CALIB_FRAC_REST
1114
1115 >;
1116
1117 }
1118
1119 using ClusterProperties::BasicClusterProperties;
1120
1122 {
1123#define CALORECGPU_COMPARED_CLUSTER_PROPERTY(NAME, ...) \
1124 struct clusters_ ## NAME \
1125 { \
1126 static std::string name() \
1127 { \
1128 return # NAME; \
1129 } \
1130 static double get_property([[maybe_unused]] const ConstantDataHolder & constant_data, \
1131 [[maybe_unused]] const CaloRecGPU::CellInfoArr & cell_info_1, \
1132 [[maybe_unused]] const CaloRecGPU::ClusterInfoArr & cluster_info_1, \
1133 [[maybe_unused]] const std::vector<int> & cells_prefix_sum_1, \
1134 [[maybe_unused]] const int cluster_index_1, \
1135 [[maybe_unused]] const CaloRecGPU::CellInfoArr & cell_info_2, \
1136 [[maybe_unused]] const CaloRecGPU::ClusterInfoArr & cluster_info_2, \
1137 [[maybe_unused]] const std::vector<int> & cells_prefix_sum_2, \
1138 [[maybe_unused]] const int cluster_index_2) \
1139 { \
1140 __VA_ARGS__ \
1141 } \
1142 };
1143
1144 CALORECGPU_COMPARED_CLUSTER_PROPERTY(delta_phi_in_range,
1145 return Helpers::regularize_angle( Helpers::regularize_angle(cluster_info_2.clusterPhi[cluster_index_2]) -
1146 Helpers::regularize_angle(cluster_info_1.clusterPhi[cluster_index_1]) );
1147 )
1148
1150 const double delta_eta = cluster_info_2.clusterEta[cluster_index_2] - cluster_info_1.clusterEta[cluster_index_1];
1151 const double delta_phi = Helpers::regularize_angle( Helpers::regularize_angle(cluster_info_2.clusterPhi[cluster_index_2]) -
1152 Helpers::regularize_angle(cluster_info_1.clusterPhi[cluster_index_1]) );
1153 return std::sqrt(delta_eta * delta_eta + delta_phi * delta_phi);
1154
1155 )
1156
1157
1158 using ComparedClusterProperties = multi_class_holder <
1159
1160 clusters_delta_phi_in_range,
1161 clusters_delta_R
1162
1163 >;
1164
1165 }
1166
1167 using ExtraClusterComparisons::ComparedClusterProperties;
1168
1170 {
1171#define CALORECGPU_BASIC_CELL_PROPERTY(NAME, ...) \
1172 struct cells_ ## NAME \
1173 { \
1174 static std::string name() \
1175 { \
1176 return # NAME; \
1177 } \
1178 static double get_property([[maybe_unused]] const ConstantDataHolder & constant_data, \
1179 [[maybe_unused]] const CaloRecGPU::CellInfoArr & cell_info, \
1180 [[maybe_unused]] const CaloRecGPU::ClusterInfoArr & cluster_info, \
1181 [[maybe_unused]] const std::vector<int> & cells_prefix_sum, \
1182 [[maybe_unused]] const int cell ) \
1183 { \
1184 __VA_ARGS__ \
1185 } \
1186 };
1187
1188 CALORECGPU_BASIC_CELL_PROPERTY(E, return cell_info.energy[cell] / CLHEP::MeV;)
1189 CALORECGPU_BASIC_CELL_PROPERTY(abs_E, return std::abs(cell_info.energy[cell]) / CLHEP::MeV; )
1190
1191 CALORECGPU_BASIC_CELL_PROPERTY(gain, return cell_info.gain[cell];)
1192
1193 CALORECGPU_BASIC_CELL_PROPERTY(noise, return constant_data.m_cell_noise->get_noise(cell_info.get_hash_ID(cell), cell_info.gain[cell]);)
1194
1195 CALORECGPU_BASIC_CELL_PROPERTY(SNR, return cell_info.energy[cell] /
1196 protect_from_zero(constant_data.m_cell_noise->get_noise(cell_info.get_hash_ID(cell), cell_info.gain[cell]));
1197 )
1198
1199 CALORECGPU_BASIC_CELL_PROPERTY(abs_SNR, return std::abs(cell_info.energy[cell] /
1200 protect_from_zero(constant_data.m_cell_noise->get_noise(cell_info.get_hash_ID(cell), cell_info.gain[cell])));)
1201
1202 CALORECGPU_BASIC_CELL_PROPERTY(time, return cell_info.time[cell] / CLHEP::us;)
1203
1205
1206 CALORECGPU_BASIC_CELL_PROPERTY(hash_ID, return cell_info.get_hash_ID(cell);)
1207
1208 CALORECGPU_BASIC_CELL_PROPERTY(sampling, return constant_data.m_geometry->sampling(cell_info.get_hash_ID(cell));)
1209
1210
1211 CALORECGPU_BASIC_CELL_PROPERTY(x, return constant_data.m_geometry->x[cell_info.get_hash_ID(cell)] / CLHEP::cm; )
1212 CALORECGPU_BASIC_CELL_PROPERTY(y, return constant_data.m_geometry->y[cell_info.get_hash_ID(cell)] / CLHEP::cm; )
1213 CALORECGPU_BASIC_CELL_PROPERTY(z, return constant_data.m_geometry->z[cell_info.get_hash_ID(cell)] / CLHEP::cm; )
1214
1215 CALORECGPU_BASIC_CELL_PROPERTY(phi, return constant_data.m_geometry->phi[cell_info.get_hash_ID(cell)];)
1216
1217 CALORECGPU_BASIC_CELL_PROPERTY(eta, return constant_data.m_geometry->eta[cell_info.get_hash_ID(cell)];)
1218
1219 CALORECGPU_BASIC_CELL_PROPERTY(number_of_clusters, return (cells_prefix_sum[cell + 1] - cells_prefix_sum[cell]);)
1220
1221 CALORECGPU_BASIC_CELL_PROPERTY(primary_cluster_index,
1222 {
1223 float max_weight = 0.f;
1224 int max_index = 0;
1225 for (int i = cells_prefix_sum[cell]; i < cells_prefix_sum[cell + 1]; ++i)
1226 {
1227 const float this_weight = cluster_info.cellWeights[i];
1228 const int this_index = cluster_info.clusterIndices[i];
1229 if (this_weight > max_weight || (this_weight == max_weight && this_index > max_index))
1230 {
1231 max_weight = this_weight;
1232 max_index = this_index;
1233 }
1234 }
1235 return max_index;
1236 }
1237 )
1238
1239 CALORECGPU_BASIC_CELL_PROPERTY(secondary_cluster_index,
1240 {
1241 float max_weight = 0.f, second_max_weight = 0.f;
1242 int max_index = 0, second_max_index = 0;
1243 for (int i = cells_prefix_sum[cell]; i < cells_prefix_sum[cell + 1]; ++i)
1244 {
1245 const float this_weight = cluster_info.cellWeights[i];
1246 const int this_index = cluster_info.clusterIndices[i];
1247 if (this_weight > max_weight || (this_weight == max_weight && this_index > max_index))
1248 {
1249 second_max_weight = max_weight;
1250 second_max_index = max_index;
1251 max_weight = this_weight;
1252 max_index = this_index;
1253 }
1254 else if (this_weight > second_max_weight || (this_weight == second_max_weight && this_index > second_max_index))
1255 {
1256 second_max_weight = this_weight;
1257 second_max_index = this_index;
1258 }
1259 }
1260 return second_max_index;
1261 }
1262 )
1263
1264 CALORECGPU_BASIC_CELL_PROPERTY(primary_weight,
1265 {
1266 float max_weight = 0.f;
1267 int max_index = 0;
1268 for (int i = cells_prefix_sum[cell]; i < cells_prefix_sum[cell + 1]; ++i)
1269 {
1270 const float this_weight = cluster_info.cellWeights[i];
1271 const int this_index = cluster_info.clusterIndices[i];
1272 if (this_weight > max_weight || (this_weight == max_weight && this_index > max_index))
1273 {
1274 max_weight = this_weight;
1275 max_index = this_index;
1276 }
1277 }
1278 return max_weight;
1279 }
1280 )
1281
1282
1283 CALORECGPU_BASIC_CELL_PROPERTY(secondary_weight,
1284 {
1285 float max_weight = 0.f, second_max_weight = 0.f;
1286 int max_index = 0, second_max_index = 0;
1287 for (int i = cells_prefix_sum[cell]; i < cells_prefix_sum[cell + 1]; ++i)
1288 {
1289 const float this_weight = cluster_info.cellWeights[i];
1290 const int this_index = cluster_info.clusterIndices[i];
1291 if (this_weight > max_weight || (this_weight == max_weight && this_index > max_index))
1292 {
1293 second_max_weight = max_weight;
1294 second_max_index = max_index;
1295 max_weight = this_weight;
1296 max_index = this_index;
1297 }
1298 else if (this_weight > second_max_weight || (this_weight == second_max_weight && this_index > second_max_index))
1299 {
1300 second_max_weight = this_weight;
1301 second_max_index = this_index;
1302 }
1303 }
1304 return second_max_weight;
1305 }
1306 )
1307
1308 using BasicCellProperties = multi_class_holder <
1309
1310 cells_E,
1311 cells_abs_E,
1312 cells_gain,
1313 cells_noise,
1314 cells_SNR,
1315 cells_abs_SNR,
1316 cells_time,
1317 cells_index,
1318 cells_hash_ID,
1319 cells_sampling,
1320 cells_x,
1321 cells_y,
1322 cells_z,
1323 cells_phi,
1324 cells_eta,
1325 cells_number_of_clusters,
1326 cells_primary_cluster_index,
1327 cells_secondary_cluster_index,
1328 cells_primary_weight,
1329 cells_secondary_weight
1330
1331 >;
1332
1333 }
1334
1335 using CellProperties::BasicCellProperties;
1336
1337 namespace CellTypes
1338 {
1339#define CALORECGPU_BASIC_CELL_TYPE(NAME, ...) \
1340 struct cell_type_ ## NAME \
1341 { \
1342 static std::string name() \
1343 { \
1344 return # NAME; \
1345 } \
1346 static bool is_type([[maybe_unused]] const ConstantDataHolder & constant_data, \
1347 [[maybe_unused]] const CaloRecGPU::CellInfoArr & cell_info, \
1348 [[maybe_unused]] const CaloRecGPU::ClusterInfoArr & cluster_info, \
1349 [[maybe_unused]] const std::vector<int> & cells_prefix_sum, \
1350 [[maybe_unused]] const int cell ) \
1351 { \
1352 __VA_ARGS__ \
1353 } \
1354 };
1355
1356 CALORECGPU_BASIC_CELL_TYPE(intracluster, return (cells_prefix_sum[cell + 1] > cells_prefix_sum[cell]);)
1357
1358 CALORECGPU_BASIC_CELL_TYPE(extracluster, return (cells_prefix_sum[cell + 1] == cells_prefix_sum[cell]);)
1359
1360 CALORECGPU_BASIC_CELL_TYPE(shared, return (cells_prefix_sum[cell + 1] > cells_prefix_sum[cell] + 1);)
1361
1362 using BasicCellTypes = multi_class_holder <
1363
1364 cell_type_intracluster,
1365 cell_type_extracluster,
1366 cell_type_shared
1367
1368 >;
1369
1370 }
1371
1372 using CellTypes::BasicCellTypes;
1373
1374
1375 enum ExtraThingsToCalculate
1376 {
1377 ClusterSize = 0,
1378 ClusterComparedSize,
1379 DiffCells,
1380 SameECells,
1381 SameECellsCombined,
1382 SameSNRCells,
1383 SameSNRCellsCombined,
1384 ExtraThingsSize
1385 };
1386}
1387
1389{
1390 const std::vector<std::string> histo_strings = m_moniTool->histogramService()->getHists();
1391 //Small problem: other histograms with matching names.
1392 //Mitigated by the fact that we use cell_<property> and cluster_<property>...
1393
1394 m_clusterPropertiesToDo.resize(BasicClusterProperties::size(), false);
1395 m_comparedClusterPropertiesToDo.resize(BasicClusterProperties::size(), false);
1396 m_extraComparedClusterPropertiesToDo.resize(ComparedClusterProperties::size(), false);
1397 m_cellPropertiesToDo.resize(BasicCellProperties::size(), false);
1398 m_comparedCellPropertiesToDo.resize(BasicCellProperties::size(), false);
1399 m_cellTypesToDo.resize(BasicCellTypes::size(), false);
1400 m_comparedCellTypesToDo.resize(BasicCellTypes::size(), false);
1401 m_extraThingsToDo.resize(ExtraThingsSize, false);
1402
1403 auto string_contains = [](std::string_view container, std::string_view contained) -> bool
1404 {
1405 return container.find(contained) != std::string::npos;
1406 };
1407
1408 auto search_lambda = [&](const auto & prop, const size_t count, bool & check,
1409 const std::string & str, std::vector<bool> & to_do,
1410 std::string_view prefix = "", std::string_view suffix = "")
1411 {
1412 if (string_contains(str, std::string(prefix) + prop.name() + std::string(suffix)))
1413 {
1414 to_do[count] = true;
1415 check = true;
1416 }
1417 };
1418
1419 for (const auto & str : histo_strings)
1420 {
1421 bool found = false;
1422
1423 apply_to_multi_class(search_lambda, BasicCellProperties{}, found, str, m_cellPropertiesToDo, "_cell_");
1424 apply_to_multi_class(search_lambda, BasicCellTypes{}, found, str, m_cellTypesToDo, "_", "_cells");
1425
1426 if (found)
1427 {
1428 m_doCells = true;
1429 }
1430
1431 found = false;
1432
1433 apply_to_multi_class(search_lambda, BasicClusterProperties{}, found, str, m_clusterPropertiesToDo, "_cluster_");
1434
1435 if (found)
1436 {
1437 m_doClusters = true;
1438 }
1439
1440 found = false;
1441
1442 apply_to_multi_class(search_lambda, BasicCellProperties{}, found, str, m_comparedCellPropertiesToDo, "_cell_delta_");
1443 apply_to_multi_class(search_lambda, BasicCellProperties{}, found, str, m_comparedCellPropertiesToDo, "_cell_", "_ref");
1444 apply_to_multi_class(search_lambda, BasicCellProperties{}, found, str, m_comparedCellPropertiesToDo, "_cell_", "_test");
1445 apply_to_multi_class(search_lambda, BasicCellTypes{}, found, str, m_comparedCellTypesToDo, "num_ref_", "_cells");
1446 apply_to_multi_class(search_lambda, BasicCellTypes{}, found, str, m_comparedCellTypesToDo, "num_test_", "_cells");
1447 apply_to_multi_class(search_lambda, BasicCellTypes{}, found, str, m_comparedCellTypesToDo, "delta_", "_cells");
1448
1449 if (found)
1450 {
1451 m_doCombinedCells = true;
1452 }
1453
1454 found = false;
1455
1456 apply_to_multi_class(search_lambda, BasicClusterProperties{}, found, str, m_comparedClusterPropertiesToDo, "_cluster_delta_", "");
1457 apply_to_multi_class(search_lambda, BasicClusterProperties{}, found, str, m_comparedClusterPropertiesToDo, "_cluster_", "_ref");
1458 apply_to_multi_class(search_lambda, BasicClusterProperties{}, found, str, m_comparedClusterPropertiesToDo, "_cluster_", "_test");
1459 apply_to_multi_class(search_lambda, ComparedClusterProperties{}, found, str, m_extraComparedClusterPropertiesToDo);
1460
1461 if (found)
1462 {
1463 m_doCombinedClusters = true;
1464 }
1465
1466 if ( string_contains(str, "cluster_size_ref") ||
1467 string_contains(str, "cluster_size_test") ||
1468 string_contains(str, "cluster_delta_size") ||
1469 string_contains(str, "cluster_weighted_size_ref") ||
1470 string_contains(str, "cluster_weighted_size_test") ||
1471 string_contains(str, "cluster_delta_weighted_size") )
1472 {
1473 m_extraThingsToDo[ClusterComparedSize] = true;
1474 m_doCombinedCells = true;
1475 m_doCombinedClusters = true;
1476 }
1477 else if ( string_contains(str, "cluster_size") ||
1478 string_contains(str, "cluster_weighted_size") )
1479 {
1480 m_extraThingsToDo[ClusterSize] = true;
1481 m_doCells = true;
1482 m_doClusters = true;
1483 }
1484
1485 if (string_contains(str, "cluster_diff_cells"))
1486 {
1487 m_extraThingsToDo[DiffCells] = true;
1488 m_doCombinedCells = true;
1489 m_doCombinedClusters = true;
1490 }
1491
1492 if ( string_contains(str, "_num_same_E_cells_ref") ||
1493 string_contains(str, "_num_same_E_cells_test") ||
1494 string_contains(str, "delta_num_same_E_cells") ||
1495 string_contains(str, "_num_same_abs_E_cells_ref") ||
1496 string_contains(str, "_num_same_abs_E_cells_test") ||
1497 string_contains(str, "delta_num_same_abs_E_cells") )
1498 {
1499 m_extraThingsToDo[SameECellsCombined] = true;
1500 m_doCombinedCells = true;
1501 }
1502 else if ( string_contains(str, "_num_same_E_cells") ||
1503 string_contains(str, "_num_same_abs_E_cells") )
1504 {
1505 m_extraThingsToDo[SameECells] = true;
1506 m_doCells = true;
1507 }
1508
1509 if ( string_contains(str, "_num_same_SNR_cells_ref") ||
1510 string_contains(str, "_num_same_SNR_cells_test") ||
1511 string_contains(str, "delta_num_same_SNR_cells") ||
1512 string_contains(str, "_num_same_abs_SNR_cells_ref") ||
1513 string_contains(str, "_num_same_abs_SNR_cells_test") ||
1514 string_contains(str, "delta_num_same_abs_SNR_cells") )
1515 {
1516 m_extraThingsToDo[SameSNRCellsCombined] = true;
1517 m_doCombinedCells = true;
1518 }
1519 else if ( string_contains(str, "_num_same_SNR_cells") ||
1520 string_contains(str, "_num_same_abs_SNR_cells") )
1521 {
1522 m_extraThingsToDo[SameSNRCells] = true;
1523 m_doCells = true;
1524 }
1525 }
1526
1527 return StatusCode::SUCCESS;
1528
1529}
1530
1531
1532StatusCode CaloGPUClusterAndCellDataMonitor::add_data(const EventContext & /*ctx*/,
1533 const ConstantDataHolder & constant_data,
1534 const CaloRecGPU::CellInfoArr * cell_info,
1535 const CaloRecGPU::ClusterInfoArr * clusters,
1536 const std::vector<int> & cells_prefix_sum,
1537 const std::string & tool_name) const
1538{
1539 m_numClustersPerTool[tool_name].fetch_add(clusters->number);
1540
1541 const std::string prefix = m_toolToIdMap.at(tool_name);
1542
1543 const int index = m_toolsToCheckFor.at(tool_name);
1544
1545 if (index >= 0 && m_numToolsToKeep > 0)
1546 {
1547 std::vector<per_tool_storage> & store_vec = m_storageHolder.get_for_thread();
1548 store_vec[index].cell_info = *cell_info;
1549 store_vec[index].clusters = *clusters;
1550 store_vec[index].cells_prefix_sum = cells_prefix_sum;
1551 }
1552
1553 if (prefix != "")
1554 //Tools that are not meant to be plotted individually
1555 //have the empty string as a prefix.
1556 {
1557 std::unordered_map<std::string, std::vector<double>> cluster_properties, cell_properties;
1558
1559 std::unordered_map<std::string, long long int> cell_counts;
1560
1561 cluster_properties["size"].resize(clusters->number, 0.);
1562 cluster_properties["weighted_size"].resize(clusters->number, 0.);
1563
1564 long long int same_energy = 0, same_abs_energy = 0, same_snr = 0, same_abs_snr = 0;
1565
1566 std::set<double> energies, snrs;
1567
1568 if (m_doCells)
1569 {
1570
1571 for (int cell = 0; cell < cell_info->number; ++cell)
1572 {
1573 if (!cell_info->is_valid(cell_info->hashID[cell]))
1574 {
1575 continue;
1576 }
1577
1578 apply_to_multi_class([&](const auto & prop, const size_t i)
1579 {
1580 if (m_cellPropertiesToDo[i])
1581 {
1582 cell_properties[prop.name()].push_back(prop.get_property(constant_data, *cell_info, *clusters, cells_prefix_sum, cell));
1583 }
1584 }, BasicCellProperties{});
1585
1586 apply_to_multi_class([&](const auto & prop, const size_t i)
1587 {
1588 if (m_cellTypesToDo[i])
1589 {
1590 cell_counts[prop.name()] += prop.is_type(constant_data, *cell_info, *clusters, cells_prefix_sum, cell);
1591 }
1592 }, BasicCellTypes{});
1593
1594 const float this_energy = cell_info->energy[cell];
1595
1596 if (m_extraThingsToDo[SameECells])
1597 {
1598
1599 if (energies.count(this_energy))
1600 {
1601 ++same_energy;
1602 ++same_abs_energy;
1603 }
1604 else if (energies.count(-this_energy))
1605 {
1606 ++same_abs_energy;
1607 }
1608 energies.insert(this_energy);
1609 }
1610
1611 if (m_extraThingsToDo[SameSNRCells])
1612 {
1613
1614 const float this_snr = this_energy / protect_from_zero(constant_data.m_cell_noise->get_noise(cell_info->get_hash_ID(cell), cell_info->gain[cell]));
1615
1616 if (snrs.count(this_snr))
1617 {
1618 ++same_snr;
1619 ++same_abs_snr;
1620 }
1621 else if (snrs.count(-this_snr))
1622 {
1623 ++same_abs_snr;
1624 }
1625 snrs.insert(this_snr);
1626 }
1627 }
1628
1629 if (m_extraThingsToDo[ClusterSize])
1630 {
1631 for (int i = 0; i < clusters->number_cells; ++i)
1632 {
1633 const int this_cluster = clusters->clusterIndices[i];
1634 const float this_weight = clusters->cellWeights[i];
1635
1636 cluster_properties["size"][this_cluster] += 1;
1637 cluster_properties["weighted_size"][this_cluster] += this_weight;
1638 }
1639 }
1640 }
1641
1642 if (m_doClusters)
1643 {
1644 for (int cluster = 0; cluster < clusters->number; ++cluster)
1645 {
1646 apply_to_multi_class([&](const auto & prop, const size_t i)
1647 {
1649 {
1650 cluster_properties[prop.name()].push_back(prop.get_property(constant_data, *cell_info, *clusters, cells_prefix_sum, cluster));
1651 }
1652 }, BasicClusterProperties{});
1653 }
1654 }
1655
1656 using coll_type = decltype(Monitored::Collection("", std::declval<std::vector<double> &>()));
1657 using scalar_type = decltype(Monitored::Scalar("", std::declval<long long int>()));
1658
1659 std::vector<coll_type> collections;
1660 std::vector<scalar_type> count_scalars;
1661 std::vector<std::reference_wrapper<Monitored::IMonitoredVariable>> cluster_group, cell_group, counts_group;
1662
1663 collections.reserve(cluster_properties.size() + cell_properties.size());
1664 count_scalars.reserve(cell_counts.size());
1665 cluster_group.reserve(cluster_properties.size());
1666 cell_group.reserve(cell_properties.size());
1667 counts_group.reserve(cell_counts.size() + 5);
1668
1669 auto mon_clus_num = Monitored::Scalar(prefix + "_num_clusters", clusters->number);
1670 auto mon_same_energy = Monitored::Scalar(prefix + "_num_same_E_cells", same_energy);
1671 auto mon_same_abs_energy = Monitored::Scalar(prefix + "_num_same_abs_E_cells", same_abs_energy);
1672 auto mon_same_snr = Monitored::Scalar(prefix + "_num_same_SNR_cells", same_snr);
1673 auto mon_same_abs_snr = Monitored::Scalar(prefix + "_num_same_abs_SNR_cells", same_abs_snr);
1674
1675 counts_group.push_back(std::ref(mon_clus_num));
1676 counts_group.push_back(std::ref(mon_same_energy));
1677 counts_group.push_back(std::ref(mon_same_abs_energy));
1678 counts_group.push_back(std::ref(mon_same_snr));
1679 counts_group.push_back(std::ref(mon_same_abs_snr));
1680
1681 //If we're not doing these plots,
1682 //we're still saving,
1683 //which is slightly inefficient, but.. let's not complicate.
1684
1685 for (const auto & k_v : cluster_properties)
1686 {
1687 collections.emplace_back(Monitored::Collection(prefix + "_cluster_" + k_v.first, k_v.second));
1688 cluster_group.push_back(std::ref(collections.back()));
1689 }
1690
1691 for (const auto & k_v : cell_properties)
1692 {
1693 collections.emplace_back(Monitored::Collection(prefix + "_cell_" + k_v.first, k_v.second));
1694 cell_group.push_back(std::ref(collections.back()));
1695 }
1696
1697 for (const auto & k_v : cell_counts)
1698 {
1699 count_scalars.emplace_back(Monitored::Scalar(prefix + "_num_" + k_v.first + "_cells", k_v.second));
1700 counts_group.push_back(std::ref(count_scalars.back()));
1701 }
1702
1703 // Taking a std::ref of the back() iterator above is safe because the vector
1704 // has been reserved with the correct number of elements.
1705 // cppcheck-suppress invalidContainer
1706 auto monitor_clusters = Monitored::Group(m_moniTool, cluster_group);
1707 auto monitor_cells = Monitored::Group(m_moniTool, cell_group);
1708 auto monitor_counts = Monitored::Group(m_moniTool, counts_group);
1709
1710 }
1711 return StatusCode::SUCCESS;
1712}
1713
1714
1715StatusCode CaloGPUClusterAndCellDataMonitor::add_combination(const EventContext & /*ctx*/,
1716 const CaloRecGPU::ConstantDataHolder & constant_data,
1717 const int index_1,
1718 const int index_2,
1719 const std::string & prefix,
1720 const bool match_in_energy,
1721 const bool match_without_shared,
1722 const bool match_perfectly) const
1723{
1724
1725 //Note: Part of the work here is superfluous in the case
1726 // where we are monitoring the tools individually too,
1727 // but in the most generic case that is not guaranteed.
1728 // Partially wasted work, but it's cleaner than the alternative...
1729
1730 std::vector<per_tool_storage> & store_vec = m_storageHolder.get_for_thread();
1731
1732 const CaloRecGPU::CellInfoArr & cell_info_1 = store_vec[index_1].cell_info;
1733 const CaloRecGPU::ClusterInfoArr & clusters_1 = store_vec[index_1].clusters;
1734 const std::vector<int> & cells_prefix_sum_1 = store_vec[index_1].cells_prefix_sum;
1735
1736 const CaloRecGPU::CellInfoArr & cell_info_2 = store_vec[index_2].cell_info;
1737 const CaloRecGPU::ClusterInfoArr & clusters_2 = store_vec[index_2].clusters;
1738 const std::vector<int> & cells_prefix_sum_2 = store_vec[index_2].cells_prefix_sum;
1739
1741
1742 if (match_perfectly)
1743 {
1744 ATH_CHECK( match_clusters_perfectly(sch, constant_data,
1745 cell_info_1, cell_info_2,
1746 cells_prefix_sum_1, cells_prefix_sum_2,
1747 clusters_1, clusters_2,
1748 match_without_shared) );
1749 }
1750 else
1751 {
1752 ATH_CHECK( match_clusters(sch, constant_data,
1753 cell_info_1, cell_info_2,
1754 cells_prefix_sum_1, cells_prefix_sum_2,
1755 clusters_1, clusters_2,
1756 match_in_energy, match_without_shared) );
1757 }
1758
1759 std::unordered_map<std::string, std::vector<double>> cluster_properties, cell_properties;
1760
1761 std::unordered_map<std::string, long long int> cell_counts;
1762
1763 std::vector<double> ref_size_vec(clusters_1.number, 0.), test_size_vec(clusters_2.number, 0.),
1764 ref_weighted_size_vec(clusters_1.number, 0.), test_weighted_size_vec(clusters_2.number, 0.),
1765 ref_diff_cells(clusters_1.number, 0.), test_diff_cells(clusters_2.number, 0.),
1766 ref_diff_cells_weight(clusters_1.number, 0.), test_diff_cells_weight(clusters_2.number, 0.);
1767 //We can store integers up to 2^53 on a double...
1768
1769 long long int same_energy_1 = 0, same_energy_2 = 0,
1770 same_abs_energy_1 = 0, same_abs_energy_2 = 0,
1771 same_snr_1 = 0, same_snr_2 = 0,
1772 same_abs_snr_1 = 0, same_abs_snr_2 = 0,
1773 same_cluster_cells_count = 0, diff_cluster_cells_count = 0;
1774
1775 std::set<double> energies_1, energies_2, snrs_1, snrs_2;
1776
1778 {
1779 for (int cell = 0; cell < NCaloCells; ++cell)
1780 //The way the validity is checked means we will
1781 //simply continue for all cells beyond cell_info_N->number.
1782 {
1783 if ( cell >= cell_info_1.number ||
1784 cell >= cell_info_2.number ||
1785 !cell_info_1.is_valid(cell_info_1.hashID[cell]) ||
1786 !cell_info_2.is_valid(cell_info_2.hashID[cell]) )
1787 {
1788 continue;
1789 }
1790
1791 apply_to_multi_class([&](const auto & prop, const size_t i)
1792 {
1794 {
1795 const auto prop_1 = prop.get_property(constant_data, cell_info_1, clusters_1, cells_prefix_sum_1, cell);
1796 const auto prop_2 = prop.get_property(constant_data, cell_info_2, clusters_2, cells_prefix_sum_2, cell);
1797
1798 cell_properties[prop.name() + "_ref"].push_back(prop_1);
1799 cell_properties[prop.name() + "_test"].push_back(prop_2);
1800
1801 cell_properties["delta_" + prop.name()].push_back(prop_2 - prop_1);
1802 cell_properties["delta_" + prop.name() + "_rel_ref"].push_back((prop_2 - prop_1) / protect_from_zero(std::abs(prop_1)));
1803 cell_properties["delta_" + prop.name() + "_rel_test"].push_back((prop_2 - prop_1) / protect_from_zero(std::abs(prop_2)));
1804 }
1805 }, BasicCellProperties{});
1806
1807 apply_to_multi_class([&](const auto & prop, const size_t i)
1808 {
1810 {
1811 const auto is_1 = prop.is_type(constant_data, cell_info_1, clusters_1, cells_prefix_sum_1, cell);
1812 const auto is_2 = prop.is_type(constant_data, cell_info_2, clusters_2, cells_prefix_sum_2, cell);
1813
1814 cell_counts["num_" + prop.name() + "_cells_ref"] += is_1;
1815 cell_counts["num_" + prop.name() + "_cells_test"] += is_2;
1816 cell_counts["delta_num_" + prop.name() + "_cells"] += is_2 - is_1;
1817 }
1818 }, BasicCellTypes{});
1819
1820 const float this_energy_1 = cell_info_1.energy[cell];
1821 const float this_energy_2 = cell_info_2.energy[cell];
1822
1823 if (m_extraThingsToDo[SameECellsCombined])
1824 {
1825 if (energies_1.count(this_energy_1))
1826 {
1827 ++same_energy_1;
1828 ++same_abs_energy_1;
1829 }
1830 else if (energies_1.count(-this_energy_1))
1831 {
1832 ++same_abs_energy_1;
1833 }
1834 energies_1.insert(this_energy_1);
1835
1836 if (energies_2.count(this_energy_2))
1837 {
1838 ++same_energy_2;
1839 ++same_abs_energy_2;
1840 }
1841 else if (energies_2.count(-this_energy_2))
1842 {
1843 ++same_abs_energy_2;
1844 }
1845 energies_2.insert(this_energy_2);
1846 }
1847
1848 if (m_extraThingsToDo[SameSNRCellsCombined])
1849 {
1850 const float this_snr_1 = this_energy_1 / protect_from_zero(constant_data.m_cell_noise->get_noise(cell_info_1.get_hash_ID(cell), cell_info_1.gain[cell]));
1851
1852 if (snrs_1.count(this_snr_1))
1853 {
1854 ++same_snr_1;
1855 ++same_abs_snr_1;
1856 }
1857 else if (snrs_1.count(-this_snr_1))
1858 {
1859 ++same_abs_snr_1;
1860 }
1861 snrs_1.insert(this_snr_1);
1862
1863
1864 const float this_snr_2 = this_energy_2 / protect_from_zero(constant_data.m_cell_noise->get_noise(cell_info_2.get_hash_ID(cell), cell_info_2.gain[cell]));
1865
1866 if (snrs_2.count(this_snr_2))
1867 {
1868 ++same_snr_2;
1869 ++same_abs_snr_2;
1870 }
1871 else if (snrs_2.count(-this_snr_2))
1872 {
1873 ++same_abs_snr_2;
1874 }
1875 snrs_2.insert(this_snr_2);
1876 }
1877
1878 if (m_extraThingsToDo[DiffCells] || m_extraThingsToDo[ClusterComparedSize])
1879 {
1880 bool cell_is_diff = false;
1881
1882 for (int i = cells_prefix_sum_1[cell]; i < cells_prefix_sum_1[cell + 1] && i < cell_info_1.number; ++i)
1883 {
1884 const int this_index = clusters_1.clusterIndices[i];
1885 const float this_weight = clusters_1.cellWeights[i];
1886 bool found_match = false;
1887 for (int j = cells_prefix_sum_2[cell]; j < cells_prefix_sum_2[cell + 1] && j < cell_info_2.number; ++j)
1888 {
1889 if (this_index == sch.t2r(clusters_2.clusterIndices[j]))
1890 {
1891 found_match = true;
1892 break;
1893 }
1894 }
1895 ref_size_vec[this_index] += 1;
1896 ref_weighted_size_vec[this_index] += this_weight;
1897 if (!found_match)
1898 {
1899 ref_diff_cells[this_index] += 1;
1900 ref_diff_cells_weight[this_index] += this_weight;
1901 cell_is_diff = true;
1902 }
1903 }
1904
1905 for (int i = cells_prefix_sum_2[cell]; i < cells_prefix_sum_2[cell + 1] && i < cell_info_2.number; ++i)
1906 {
1907 const int this_index = clusters_2.clusterIndices[i];
1908 const float this_weight = clusters_2.cellWeights[i];
1909 bool found_match = false;
1910 for (int j = cells_prefix_sum_1[cell]; j < cells_prefix_sum_1[cell + 1] && j < cell_info_1.number; ++j)
1911 {
1912 if (this_index == sch.r2t(clusters_1.clusterIndices[j]))
1913 {
1914 found_match = true;
1915 break;
1916 }
1917 }
1918 test_size_vec[this_index] += 1;
1919 test_weighted_size_vec[this_index] += this_weight;
1920 if (!found_match)
1921 {
1922 test_diff_cells[this_index] += 1;
1923 test_diff_cells_weight[this_index] += this_weight;
1924 cell_is_diff = true;
1925 }
1926 }
1927
1928 if (cell_is_diff)
1929 {
1930#if CALORECGPU_DATA_MONITOR_EXTRA_PRINTOUTS
1931 msg(MSG::INFO) << "Diff: " << cell << " |";
1932 for (int i = cells_prefix_sum_1[cell]; i < cells_prefix_sum_1[cell + 1] && i < cell_info_1.number; ++i)
1933 {
1934 msg() << " {" << clusters_1.cellWeights[i] << ", " << clusters_1.clusterIndices[i] << " (" << sch.r2t(clusters_1.clusterIndices[i]) << ")}";
1935 }
1936 msg() << " |";
1937 for (int i = cells_prefix_sum_2[cell]; i < cells_prefix_sum_2[cell + 1] && i < cell_info_2.number; ++i)
1938 {
1939 msg() << " {" << clusters_2.cellWeights[i] << ", " << clusters_2.clusterIndices[i] << " (" << sch.t2r(clusters_2.clusterIndices[i]) << ")}";
1940 }
1941 msg() << endmsg;
1942#endif
1943
1944 ++diff_cluster_cells_count;
1945 }
1946 else if ((cells_prefix_sum_1[cell + 1] > cells_prefix_sum_1[cell]) || (cells_prefix_sum_2[cell + 1] > cells_prefix_sum_2[cell]))
1947 {
1948 ++same_cluster_cells_count;
1949 }
1950 }
1951 }
1952 }
1953
1955 {
1956
1957 for (int cluster = 0; cluster < clusters_1.number; ++cluster)
1958 {
1959 const int match = sch.r2t(cluster);
1960 if (match < 0)
1961 //The cluster isn't matched.
1962 {
1963 continue;
1964 }
1965
1966 apply_to_multi_class([&](const auto & prop, const size_t i)
1967 {
1969 {
1970 const auto prop_1 = prop.get_property(constant_data, cell_info_1, clusters_1, cells_prefix_sum_1, cluster);
1971 const auto prop_2 = prop.get_property(constant_data, cell_info_2, clusters_2, cells_prefix_sum_2, match);
1972
1973 cluster_properties[prop.name() + "_ref"].push_back(prop_1);
1974 cluster_properties[prop.name() + "_test"].push_back(prop_2);
1975
1976 cluster_properties["delta_" + prop.name()].push_back(prop_2 - prop_1);
1977 cluster_properties["delta_" + prop.name() + "_rel_ref"].push_back((prop_2 - prop_1) / protect_from_zero(std::abs(prop_1)));
1978 cluster_properties["delta_" + prop.name() + "_rel_test"].push_back((prop_2 - prop_1) / protect_from_zero(std::abs(prop_2)));
1979 }
1980 }, BasicClusterProperties{});
1981
1982 apply_to_multi_class([&](const auto & prop, const size_t i)
1983 {
1985 {
1986 cluster_properties[prop.name()].push_back(prop.get_property(constant_data, cell_info_1, clusters_1, cells_prefix_sum_1, cluster,
1987 cell_info_2, clusters_2, cells_prefix_sum_2, match));
1988 }
1989 }, ComparedClusterProperties{});
1990
1991 if (m_extraThingsToDo[ClusterComparedSize])
1992 {
1993 cluster_properties["size_ref"].push_back(ref_size_vec[cluster]);
1994 cluster_properties["size_test"].push_back(test_size_vec[match]);
1995 cluster_properties["delta_size"].push_back(ref_size_vec[cluster] - test_size_vec[match]);
1996 cluster_properties["delta_size_rel_ref"].push_back((ref_size_vec[cluster] - test_size_vec[match]) / protect_from_zero(ref_size_vec[cluster]));
1997 cluster_properties["delta_size_rel_test"].push_back((ref_size_vec[cluster] - test_size_vec[match]) / protect_from_zero(test_size_vec[match]));
1998
1999 cluster_properties["weighted_size_ref"].push_back(ref_weighted_size_vec[cluster]);
2000 cluster_properties["weighted_size_test"].push_back(test_weighted_size_vec[match]);
2001 cluster_properties["delta_weighted_size"].push_back(ref_weighted_size_vec[cluster] - test_weighted_size_vec[match]);
2002 cluster_properties["delta_weighted_size_rel_ref"].push_back((ref_weighted_size_vec[cluster] - test_weighted_size_vec[match]) / protect_from_zero(ref_weighted_size_vec[cluster]));
2003 cluster_properties["delta_weighted_size_rel_test"].push_back((ref_weighted_size_vec[cluster] - test_weighted_size_vec[match]) / protect_from_zero(test_weighted_size_vec[match]));
2004 }
2005
2006 if (m_extraThingsToDo[DiffCells])
2007 {
2008 cluster_properties["diff_cells_ref"].push_back(ref_diff_cells[cluster]);
2009 cluster_properties["diff_cells_ref_rel_size"].push_back(ref_diff_cells[cluster] / protect_from_zero(ref_size_vec[cluster]));
2010 cluster_properties["diff_cells_test"].push_back(test_diff_cells[match]);
2011 cluster_properties["diff_cells_test_rel_size"].push_back(test_diff_cells[match] / protect_from_zero(test_size_vec[match]));
2012 cluster_properties["diff_cells"].push_back(ref_diff_cells[cluster] + test_diff_cells[match]);
2013
2014 cluster_properties["weighted_diff_cells_ref"].push_back(ref_diff_cells_weight[cluster]);
2015 cluster_properties["weighted_diff_cells_ref_rel_size"].push_back(ref_diff_cells_weight[cluster] / protect_from_zero(ref_weighted_size_vec[cluster]));
2016 cluster_properties["weighted_diff_cells_test"].push_back(test_diff_cells_weight[match]);
2017 cluster_properties["weighted_diff_cells_test_rel_size"].push_back(test_diff_cells_weight[match] / protect_from_zero(test_weighted_size_vec[match]));
2018 cluster_properties["weighted_diff_cells"].push_back(ref_diff_cells_weight[cluster] + test_diff_cells_weight[match]);
2019 }
2020 }
2021 }
2022
2023 using coll_type = decltype(Monitored::Collection("", std::declval<std::vector<double> &>()));
2024 using scalar_type = decltype(Monitored::Scalar("", std::declval<long long int>()));
2025
2026 std::vector<coll_type> collections;
2027 std::vector<scalar_type> count_scalars;
2028 std::vector<std::reference_wrapper<Monitored::IMonitoredVariable>> cluster_group, cell_group, counts_group;
2029
2030 collections.reserve(cluster_properties.size() + cell_properties.size());
2031 count_scalars.reserve(cell_counts.size() + 6 * 3);
2032 cluster_group.reserve(cluster_properties.size());
2033 cell_group.reserve(cell_properties.size());
2034 counts_group.reserve(cell_counts.size() + 3 + 6 * 3);
2035
2036 auto add_count_vars = [&](const std::string & name, const long long int ref_num, const long long int test_num)
2037 {
2038 count_scalars.emplace_back(Monitored::Scalar(prefix + "_" + name + "_ref", ref_num));
2039 counts_group.push_back(std::ref(count_scalars.back()));
2040
2041 count_scalars.emplace_back(Monitored::Scalar(prefix + "_" + name + "_test", test_num));
2042 counts_group.push_back(std::ref(count_scalars.back())); // cppcheck-suppress invalidContainer; reserve used
2043
2044 count_scalars.emplace_back(Monitored::Scalar(prefix + "_delta_" + name, test_num - ref_num));
2045 counts_group.push_back(std::ref(count_scalars.back())); // cppcheck-suppress invalidContainer; reserve used
2046 };
2047
2048 add_count_vars("num_clusters", clusters_1.number, clusters_2.number);
2049 add_count_vars("num_unmatched_clusters", sch.ref_unmatched(), sch.test_unmatched());
2050
2051 add_count_vars("num_same_E_cells", same_energy_1, same_energy_2);
2052 add_count_vars("num_same_abs_E_cells", same_abs_energy_1, same_abs_energy_2);
2053 add_count_vars("num_same_SNR_cells", same_snr_1, same_snr_2);
2054 add_count_vars("num_same_abs_SNR_cells", same_abs_snr_1, same_abs_snr_2);
2055
2056 auto mon_total_unmatched = Monitored::Scalar(prefix + "_num_unmatched_clusters", sch.ref_unmatched() + sch.test_unmatched());
2057 auto mon_same_cluster_cell = Monitored::Scalar(prefix + "_same_cluster_cells", same_cluster_cells_count);
2058 auto mon_diff_cluster_cell = Monitored::Scalar(prefix + "_diff_cluster_cells", diff_cluster_cells_count);
2059
2060 if(m_extraThingsToDo[DiffCells])
2061 {
2062 ATH_MSG_INFO("Different cells: " << diff_cluster_cells_count);
2063 }
2064
2065 counts_group.push_back(std::ref(mon_total_unmatched));
2066 counts_group.push_back(std::ref(mon_same_cluster_cell));
2067 counts_group.push_back(std::ref(mon_diff_cluster_cell));
2068
2069 for (const auto & k_v : cluster_properties)
2070 {
2071 collections.emplace_back(Monitored::Collection(prefix + "_cluster_" + k_v.first, k_v.second));
2072 cluster_group.push_back(std::ref(collections.back()));
2073 }
2074
2075 for (const auto & k_v : cell_properties)
2076 {
2077 collections.emplace_back(Monitored::Collection(prefix + "_cell_" + k_v.first, k_v.second));
2078 cell_group.push_back(std::ref(collections.back()));
2079 }
2080
2081 for (const auto & k_v : cell_counts)
2082 {
2083 count_scalars.emplace_back(Monitored::Scalar(prefix + "_" + k_v.first, k_v.second));
2084 counts_group.push_back(std::ref(count_scalars.back()));
2085 }
2086
2087 // Taking a std::ref of the back() iterator above is safe because the vector
2088 // has been reserved with the correct number of elements.
2089 // cppcheck-suppress invalidContainer
2090 auto monitor_clusters = Monitored::Group(m_moniTool, cluster_group);
2091 auto monitor_cells = Monitored::Group(m_moniTool, cell_group);
2092 auto monitor_counts = Monitored::Group(m_moniTool, counts_group);
2093
2094 return StatusCode::SUCCESS;
2095}
Scalar eta() const
pseudorapidity method
Scalar deltaPhi(const MatrixBase< Derived > &vec) const
Scalar phi() const
phi method
#define endmsg
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_INFO(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
Base class for cluster processing tools called from CaloClusterMaker.
static void build_similarity_map_helper(const CaloRecGPU::CellInfoArr &, const CaloRecGPU::CellInfoArr &, const std::vector< int > &cells_prefix_sum_1, const std::vector< int > &cells_prefix_sum_2, const CaloRecGPU::ClusterInfoArr &cluster_info_1, const CaloRecGPU::ClusterInfoArr &cluster_info_2, WeighMatch match, WeighNotMatch not_match)
#define CALORECGPU_BASIC_CLUSTER_PROPERTY(NAME,...)
#define CALORECGPU_BASIC_CELL_PROPERTY(NAME,...)
#define CALORECGPU_CLUSTER_MOMENT(...)
#define CALORECGPU_BASIC_CELL_TYPE(NAME,...)
#define CALORECGPU_COMPARED_CLUSTER_PROPERTY(NAME,...)
defines an "iterator" over instances of a given type in StoreGateSvc
static Double_t a
static Double_t tc
static Double_t rc
if(febId1==febId2)
Header file to be included by clients of the Monitored infrastructure.
#define y
#define x
#define z
Container class for CaloCell.
Base class for GPU-accelerated cluster processing tools to be called from CaloGPUHybridClusterProcess...
Gaudi::Property< float > m_seedThreshold
Seed threshold to use for cluster matching.
Gaudi::Property< std::vector< SimpleSingleTool > > m_toolsToPlot
Tools to plot individually.
Gaudi::Property< std::vector< SimpleToolPair > > m_pairsToPlot
Pairs of tools to compare.
std::atomic< bool > m_plottedVariablesInitialized
A flag to signal that the variables to be monitored have been detected based on the booked histograms...
StatusCode add_data(const EventContext &ctx, const CaloRecGPU::ConstantDataHolder &constant_data, const CaloRecGPU::CellInfoArr *cell_info, const CaloRecGPU::ClusterInfoArr *clusters, const std::vector< int > &cells_prefix_sum, const std::string &tool_name) const
virtual StatusCode update_plots_start(const EventContext &ctx, const CaloRecGPU::ConstantDataHolder &constant_data, const xAOD::CaloClusterContainer *cluster_collection_ptr) const override
Gaudi::Property< float > m_termThreshold
Cell (terminal) threshold to use for cluster matching.
virtual StatusCode update_plots_end(const EventContext &ctx, const CaloRecGPU::ConstantDataHolder &constant_data, const xAOD::CaloClusterContainer *cluster_collection_ptr) const override
std::vector< bool > m_clusterPropertiesToDo
Control which properties will actually be calculated and stored.
bool m_doCells
If no properties are asked for, skip the relevant loops entirely...
ToolHandle< GenericMonitoringTool > m_moniTool
Monitoring tool.
int m_numToolsToKeep
The number of tools that will actually need to be kept in memory for combined plotting.
StatusCode add_combination(const EventContext &ctx, const CaloRecGPU::ConstantDataHolder &constant_data, const int index_1, const int index_2, const std::string &prefix, const bool match_in_energy, const bool match_without_shared, const bool match_perfectly) const
std::map< std::string, std::atomic< size_t > > m_numClustersPerTool ATLAS_THREAD_SAFE
Counts the total number of clusters per tool.
std::map< std::string, std::string > m_toolToIdMap
Maps tools to their respective identifying prefix for variables.
Gaudi::Property< float > m_growThreshold
Neighbor (growing) threshold to use for cluster matching.
Gaudi::Property< MatchingOptions > m_matchingOptions
Option for adjusting the parameters for the cluster matching algorithm.
Gaudi::Property< std::vector< int > > m_missingCellsToFill
Cell indices to fill as disabled cells (useful if the cell vector is always missing the same cells).
SG::ReadHandleKey< CaloCellContainer > m_cellsKey
vector of names of the cell containers to use as input.
std::map< std::string, int > m_toolsToCheckFor
Map of the strings corresponding to all the tools that will be relevant for plotting (individually or...
StatusCode match_clusters(sample_comparisons_holder &sch, const CaloRecGPU::ConstantDataHolder &constant_data, const CaloRecGPU::CellInfoArr &cell_info_1, const CaloRecGPU::CellInfoArr &cell_info_2, const std::vector< int > &cells_prefix_sum_1, const std::vector< int > &cells_prefix_sum_2, const CaloRecGPU::ClusterInfoArr &cluster_info_1, const CaloRecGPU::ClusterInfoArr &cluster_info_2, const bool match_in_energy, const bool match_without_shared) const
size_t m_numEvents
Counts the number of events.
bool filter_tool_by_name(const std::string &tool_name) const
Returns true if this tool should be plotted for.
const CaloCell_ID * m_calo_id
Pointer to Calo ID Helper.
double m_min_similarity
Parameters for the cluster matching algorithm, for easier access.
virtual StatusCode update_plots(const EventContext &ctx, const CaloRecGPU::ConstantDataHolder &constant_data, const xAOD::CaloClusterContainer *cluster_collection_ptr, const CaloClusterCollectionProcessor *tool) const override
CaloGPUClusterAndCellDataMonitor(const std::string &type, const std::string &name, const IInterface *parent)
StatusCode update_cell_representation(const EventContext &ctx, const CaloRecGPU::ConstantDataHolder &constant_data, const CaloRecGPU::CellInfoArr *cell_info, CaloRecGPU::ClusterInfoArr *clusters, std::vector< int > &cells_prefix_sum) const
Update the cell representation so the cells-in-clusters are ordered by index and have a prefix sum.
std::mutex m_mutex
This mutex is locked to ensure only one thread detects the monotired variables.
StatusCode match_clusters_perfectly(sample_comparisons_holder &sch, const CaloRecGPU::ConstantDataHolder &constant_data, const CaloRecGPU::CellInfoArr &cell_info_1, const CaloRecGPU::CellInfoArr &cell_info_2, const std::vector< int > &cells_prefix_sum_1, const std::vector< int > &cells_prefix_sum_2, const CaloRecGPU::ClusterInfoArr &cluster_info_1, const CaloRecGPU::ClusterInfoArr &cluster_info_2, const bool match_without_shared) const
virtual StatusCode finalize_plots() const override
Holds CPU and GPU versions of the geometry and cell noise information, which are assumed to be consta...
Definition DataHolders.h:27
CaloRecGPU::Helpers::CPU_object< CaloRecGPU::CellNoiseArr > m_cell_noise
Definition DataHolders.h:34
Holds the mutable per-event information (clusters and cells) and provides utilities to convert betwee...
Definition DataHolders.h:73
CaloRecGPU::Helpers::CUDA_pinned_CPU_object< CaloRecGPU::CellInfoArr > m_cell_info
CaloRecGPU::Helpers::CUDA_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
Base class for tools that convert event information from the Athena structures to the GPU-friendly fo...
Base class for tools that convert event information from the GPU-friendly format used in CaloGPUHybri...
Group of local monitoring quantities and retain correlation when filling histograms
Declare a monitored scalar variable.
STL class.
STL class.
int count(std::string s, const std::string &regx)
count how many occurances of a regx are in a string
Definition hcg.cxx:146
bool match(std::string s1, std::string s2)
match the individual directories of two strings
Definition hcg.cxx:357
static CUDA_HOS_DEV float regularize_angle(const float b, const float a=0.f)
SimpleHolder< T, MemoryContext::CPU, true > CPU_object
Holds an object of type T in CPU memory.
Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration.
double protect_from_zero(const double x)
constexpr int NCaloCells
void apply_to_multi_class(F &&f, multi_class_holder< Types... >, Args &... args)
float float_unhack(const unsigned int bits)
ValuesCollection< T > Collection(std::string name, const T &collection)
Declare a monitored (double-convertible) collection.
float j(const xAOD::IParticle &, const xAOD::TrackMeasurementValidation &hit, const Eigen::Matrix3d &jab_inv)
void * ptr(T *p)
Definition SGImplSvc.cxx:74
Definition index.py:1
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
CaloClusterContainer_v1 CaloClusterContainer
Define the latest version of the calorimeter cluster container.
int test_unmatched() const
Returns the number of unmatched clusters in the test (second) tool.
int ref_unmatched() const
Returns the number of unmatched clusters in the reference (first) tool.
int t2r(const int i) const
Converts a cluster index from the test tool (second) to the reference tool (first).
int r2t(const int i) const
Converts a cluster index from the reference tool (first) to the test tool (second).
Contains the per-event cell information: energy, timing, gain, quality and provenance.
constexpr int get_hash_ID(const int cell, const bool is_complete=false) const
constexpr int get_cell_with_hash_ID(const int index, const bool is_complete=false) const
constexpr bool is_bad(const int cell, const bool treat_L1_predicted_as_good=false, const bool is_complete=false) const
GPU version of CaloBadCellHelper::isBad.
unsigned char gain[NCaloCells]
constexpr bool is_valid(const int hash_ID, const bool is_complete=false, const bool all_cells_are_valid=false) const
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 MomentsOptionsArray all()
A convenient way to handle a compile-time list of types, useful for several metaprogramming technique...
MsgStream & msg
Definition testRead.cxx:32