ATLAS Offline Software
Loading...
Searching...
No Matches
TopoAutomatonClustering.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
9
10
11#include <string>
12#include <climits> //For CHAR_BIT... though it's a slightly inefficient way of saying 8.
13
15
16#include "boost/chrono/chrono.hpp"
17#include "boost/chrono/thread_clock.hpp"
18
19#include "MacroHelpers.h"
20
21using namespace CaloRecGPU;
22using namespace TAGrowing;
23
24TopoAutomatonClustering::TopoAutomatonClustering(const std::string & type, const std::string & name, const IInterface * parent):
25 base_class(type, name, parent),
26 CaloGPUTimed(this)
27{
28}
29
31{
32
33 m_options.allocate();
34
35
36 using PackType = decltype(m_options.m_options->valid_sampling_seed);
37
38 static_assert(CaloCell_ID::getNumberOfSamplings() <= sizeof(PackType) * CHAR_BIT, "We are assuming that we have fewer samplings that bits per int!");
39
40 //Possibly more elegant alternative: compile-time packed bool vector (std::bitset?) with CUDA compat.
41 //Been there, done that, overkill since number of samplings shouldn't change unexpectedly overnight
42 //and it doesn't seem that likely to me that it'll reach anything that a 64-bit int wouldn't cover
43 //(at least without implying such a major overhaul that the code will need a deeper redesign anyway...)
44
45 auto get_sampling_from_string = [](const std::string & str, bool & failed)
46 {
47 failed = false;
48 //cppcheck-suppress syntaxError
51 PreSamplerB,
52 EMB1,
53 EMB2,
54 EMB3,
55 PreSamplerE,
56 EME1,
57 EME2,
58 EME3,
59 HEC0,
60 HEC1,
61 HEC2,
62 HEC3,
63 TileBar0,
64 TileBar1,
65 TileBar2,
66 TileGap1,
67 TileGap2,
68 TileGap3,
69 TileExt0,
70 TileExt1,
71 TileExt2,
72 FCAL0,
73 FCAL1,
74 FCAL2
75 )
76 )
77 else
78 {
79 failed = true;
80 return CaloCell_ID::Unknown;
81 }
82 };
83
84
85 PackType & seed_samplings = m_options.m_options->valid_sampling_seed;
86
87 seed_samplings = 0;
88
89 for (const std::string & samp_name : m_samplingNames)
90 {
91 bool failed = false;
92 const PackType sampling = (PackType) get_sampling_from_string(samp_name, failed);
93
94 if (failed)
95 {
96 ATH_MSG_ERROR( "Calorimeter sampling" << samp_name
97 << " is not a valid Calorimeter sampling name and will be ignored! "
98 << "Valid names are: "
99 << "PreSamplerB, EMB1, EMB2, EMB3, "
100 << "PreSamplerE, EME1, EME2, EME3, "
101 << "HEC0, HEC1, HEC2, HEC3, "
102 << "TileBar0, TileBar1, TileBar2, "
103 << "TileGap1, TileGap2, TileGap3, "
104 << "TileExt0, TileExt1, TileExt2, "
105 << "FCAL0, FCAL1, FCAL2." );
106 }
107 else
108 {
109 seed_samplings |= ((PackType) 1) << sampling;
110 }
111 }
112
113 auto get_calo_from_string = [](const std::string & str, bool & failed)
114 {
115 failed = false;
118 LAREM, LARHEC,
119 LARFCAL, TILE,
120 LARMINIFCAL
121 )
122 )
123 else
124 {
125 failed = true;
127 }
128 };
129
130
131 auto calo_to_sampling_mask = [](const CaloCell_ID::SUBCALO sc) -> PackType
132 {
133 switch (sc)
134 {
136 return 0xFFU;
137 //PreSamplerB=0, EMB1, EMB2, EMB3,
138 //PreSamplerE, EME1, EME2, EME3=7,
140 return 0xF00U;
141 //HEC0=8, HEC1, HEC2, HEC3=11,
143 return 0x1FF000U;
144 //TileBar0=12, TileBar1, TileBar2,
145 //TileGap1, TileGap2, TileGap3,
146 //TileExt0, TileExt1, TileExt2=20,
148 return 0xE00000U;
149 //FCAL0=21, FCAL1, FCAL2=23
151 return 0xF000000U;
152 //MINIFCAL0=24, MINIFCAL1, MINIFCAL2, MINIFCAL3=27,
153 default:
154 return 0;
155 }
156 };
157
158 PackType & calo_samplings = m_options.m_options->valid_calorimeter_by_sampling;
159
160 calo_samplings = 0;
161
162 for (const std::string & calo_name : m_caloNames)
163 {
164 bool failed = false;
165 const PackType sample_mask = calo_to_sampling_mask(get_calo_from_string(calo_name, failed));
166
167 if (failed)
168 {
169 ATH_MSG_ERROR( "Calorimeter " << calo_name
170 << " is not a valid Calorimeter name and will be ignored! "
171 << "Valid names are: LAREM, LARHEC, LARFCAL, and TILE." );
172 }
173 else
174 {
175 calo_samplings |= sample_mask;
176 }
177 }
178
179 auto get_neighbour_option_from_string = [](const std::string & str, bool & failed)
180 {
181 failed = false;
184 prevInPhi,
185 nextInPhi,
186 prevInEta,
187 nextInEta,
188 faces2D,
189 corners2D,
190 all2D,
191 prevInSamp,
192 nextInSamp,
193 upAndDown,
194 prevSubDet,
195 nextSubDet,
196 all3D,
197 corners3D,
198 all3DwithCorners,
199 prevSuperCalo,
200 nextSuperCalo,
201 super3D
202 )
203 )
204 else
205 {
206 failed = true;
208 }
209 };
210
211 bool neigh_failed = false;
212 m_options.m_options->neighbour_options = (unsigned int) get_neighbour_option_from_string(m_neighborOptionString, neigh_failed);
213
214 if (neigh_failed)
215 {
216 ATH_MSG_ERROR("Invalid Neighbour Option: " << m_neighborOptionString);
217 }
218
219 m_options.m_options->seed_threshold = m_seedThresholdOnEorAbsEinSigma;
220 m_options.m_options->grow_threshold = m_neighborThresholdOnEorAbsEinSigma;
221 m_options.m_options->terminal_threshold = m_cellThresholdOnEorAbsEinSigma;
222 m_options.m_options->abs_seed = m_seedCutsInAbsE;
223 m_options.m_options->abs_grow = m_neighborCutsInAbsE;
224 m_options.m_options->abs_terminal = m_cellCutsInAbsE;
225 m_options.m_options->use_two_gaussian = m_twoGaussianNoise;
226
227 m_options.m_options->treat_L1_predicted_as_good = m_treatL1PredictedCellsAsGood;
228 m_options.m_options->use_time_cut = m_cutCellsInTime;
229 m_options.m_options->keep_significant_cells = m_keepSignificantCells;
230 m_options.m_options->completely_exclude_cut_seeds = m_excludeCutSeedsFromClustering;
231 m_options.m_options->time_threshold = m_timeThreshold;
232 m_options.m_options->snr_threshold_for_keeping_cells = m_thresholdForKeeping;
233
234 m_options.m_options->limit_HECIW_and_FCal_neighs = m_restrictHECIWandFCalNeighbors;
235 m_options.m_options->limit_PS_neighs = m_restrictPSNeighbors;
236
237 m_options.m_options->use_crosstalk = m_xtalkEM2;
238 m_options.m_options->crosstalk_delta = m_xtalkDeltaT;
239
240 ATH_CHECK( m_kernelSizeOptimizer.retrieve() );
241
242 return StatusCode::SUCCESS;
243}
244
246{
247 m_options.sendToGPU();
249
250 return StatusCode::SUCCESS;
251}
252
253
254
255StatusCode TopoAutomatonClustering::execute(const EventContext & ctx, const ConstantDataHolder & constant_data,
256 EventDataHolder & event_data, void * /*temporary_buffer*/ ) const
257{
258
259 using clock_type = boost::chrono::thread_clock;
260 auto time_cast = [](const auto & before, const auto & after)
261 {
262 return boost::chrono::duration_cast<boost::chrono::microseconds>(after - before).count();
263 };
264
265 const auto start = clock_type::now();
266
267 const auto before_snr = clock_type::now();
268
269 signalToNoise(event_data, constant_data, m_options, *(m_kernelSizeOptimizer.get()), m_measureTimes);
270
271 const auto before_pairs = clock_type::now();
272
273 cellPairs(event_data, constant_data, m_options, *(m_kernelSizeOptimizer.get()), m_measureTimes);
274
275 const auto before_growing = clock_type::now();
276
277 clusterGrowing(event_data, constant_data, m_options, *(m_kernelSizeOptimizer.get()), m_measureTimes);
278
279 const auto end = clock_type::now();
280
281
282 if (m_measureTimes)
283 {
284 record_times(ctx.evt(),
285 time_cast(start, before_snr),
286 time_cast(before_snr, before_pairs),
287 time_cast(before_pairs, before_growing),
288 time_cast(before_growing, end)
289 );
290 }
291
292 return StatusCode::SUCCESS;
293
294
295}
296
297
299{
300 if (m_measureTimes)
301 {
302 print_times("Preprocessing Signal-to-Noise_Ratio Cell_Pair_Creation Cluster_Growing", 4);
303 }
304 return StatusCode::SUCCESS;
305}
306
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
static Double_t sc
Contains some helpful macros to help with repetitive code...
#define CRGPU_RECURSIVE_MACRO(...)
Expands recursive macros.
#define CRGPU_CHEAP_STRING_TO_ENUM(VAR, PREFIX, ONE,...)
Checks a string variable, VAR, for matching enum identifiers (ONE and the remaining variadic argument...
@ TILE
Definition RegSelEnums.h:30
Helper class for offline cell identifiers.
Definition CaloCell_ID.h:34
CaloCell_Base_ID::SUBCALO SUBCALO
Definition CaloCell_ID.h:50
Gaudi::Property< bool > m_measureTimes
If true, times are recorded to the file given by m_timeFileName.
CaloGPUTimed(T *ptr)
void print_times(const std::string &header, const size_t time_size) const
void record_times(const size_t event_num, const std::vector< size_t > &times) const
Holds CPU and GPU versions of the geometry and cell noise information, which are assumed to be consta...
Definition DataHolders.h:27
Holds the mutable per-event information (clusters and cells) and provides utilities to convert betwee...
Definition DataHolders.h:73
static constexpr unsigned int getNumberOfSamplings()
Get number of available samplings.
Gaudi::Property< bool > m_twoGaussianNoise
if set to true use 2-gaussian noise description for TileCal
Gaudi::Property< std::vector< std::string > > m_caloNames
vector of names of the calorimeters to consider.
Gaudi::Property< bool > m_restrictHECIWandFCalNeighbors
if set to true limit the neighbors in HEC IW and FCal2&3.
virtual StatusCode execute(const EventContext &ctx, const CaloRecGPU::ConstantDataHolder &constant_data, CaloRecGPU::EventDataHolder &event_data, void *temporary_buffer) const override
Gaudi::Property< bool > m_xtalkEM2
If set to true, the time window is softened in the EMB2 and EME2_OW due to crosstalk from direct neig...
Gaudi::Property< bool > m_cellCutsInAbsE
if set to true cell cuts are on and .
Gaudi::Property< float > m_timeThreshold
threshold used for timing cut on seed cells.
Gaudi::Property< float > m_xtalkDeltaT
Additional maximum delta t added to the upper limit time window in case crosstalk in EM2 should be ac...
TopoAutomatonClustering(const std::string &type, const std::string &name, const IInterface *parent)
TAGrowing::TACOptionsHolder m_options
Options for the algorithm, held in a GPU-friendly way.
Gaudi::Property< float > m_cellThresholdOnEorAbsEinSigma
all cells have to satisfy
Gaudi::Property< float > m_seedThresholdOnEorAbsEinSigma
cells with start a cluster
Gaudi::Property< bool > m_restrictPSNeighbors
if set to true limit the neighbors in presampler Barrel and Endcap.
Gaudi::Property< std::string > m_neighborOptionString
type of neighbor relations to use.
Gaudi::Property< bool > m_treatL1PredictedCellsAsGood
if set to true treat cells with a dead OTX which can be predicted by L1 trigger info as good instead ...
Gaudi::Property< bool > m_neighborCutsInAbsE
if set to true neighbor cuts are on and .
Gaudi::Property< float > m_neighborThresholdOnEorAbsEinSigma
cells with extend the cluster
Gaudi::Property< std::vector< std::string > > m_samplingNames
vector of names of the calorimeter samplings to consider for seeds.
Gaudi::Property< bool > m_excludeCutSeedsFromClustering
if set to true, seed cells failing the time cut are also excluded from cluster at all
Gaudi::Property< bool > m_cutCellsInTime
if set to true, time cut is applied to seed cells, no cut otherwise
virtual StatusCode finalize() override
Gaudi::Property< float > m_thresholdForKeeping
upper limit on the energy significance, for applying the cell time cut
virtual StatusCode initialize_CUDA() override
Initialization that invokes CUDA functions.
virtual StatusCode initialize_non_CUDA() override
Initialization that does not invoke CUDA functions.
ServiceHandle< IGPUKernelSizeOptimizerSvc > m_kernelSizeOptimizer
Handle to the CUDA kernel block and grid size optimization service.
Gaudi::Property< bool > m_keepSignificantCells
if set to true, the time cut is not applied on cell of large significance
Gaudi::Property< bool > m_seedCutsInAbsE
if set to true seed cuts are on and .
Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration.
void signalToNoise(CaloRecGPU::EventDataHolder &holder, const CaloRecGPU::ConstantDataHolder &instance_data, const TACOptionsHolder &options, const IGPUKernelSizeOptimizer &optimizer, const bool synchronize=false, CaloRecGPU::CUDA_Helpers::CUDAStreamPtrHolder stream_to_use={})
void register_kernels(IGPUKernelSizeOptimizer &optimizer)
void clusterGrowing(CaloRecGPU::EventDataHolder &holder, const CaloRecGPU::ConstantDataHolder &instance_data, const TACOptionsHolder &options, const IGPUKernelSizeOptimizer &optimizer, const bool synchronize=false, CaloRecGPU::CUDA_Helpers::CUDAStreamPtrHolder stream_to_use={})
void cellPairs(CaloRecGPU::EventDataHolder &holder, const CaloRecGPU::ConstantDataHolder &instance_data, const TACOptionsHolder &options, const IGPUKernelSizeOptimizer &optimizer, const bool synchronize=false, CaloRecGPU::CUDA_Helpers::CUDAStreamPtrHolder stream_to_use={})