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