ATLAS Offline Software
Loading...
Searching...
No Matches
TopoAutomatonClustering.cxx
Go to the documentation of this file.
1//
2// Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3//
4// Dear emacs, this is -*- c++ -*-
5//
6
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;
50 PreSamplerB,
51 EMB1,
52 EMB2,
53 EMB3,
54 PreSamplerE,
55 EME1,
56 EME2,
57 EME3,
58 HEC0,
59 HEC1,
60 HEC2,
61 HEC3,
62 TileBar0,
63 TileBar1,
64 TileBar2,
65 TileGap1,
66 TileGap2,
67 TileGap3,
68 TileExt0,
69 TileExt1,
70 TileExt2,
71 FCAL0,
72 FCAL1,
73 FCAL2
74 )
75 )
76 else
77 {
78 failed = true;
79 return CaloCell_ID::Unknown;
80 }
81 };
82
83
84 PackType & seed_samplings = m_options.m_options->valid_sampling_seed;
85
86 seed_samplings = 0;
87
88 for (const std::string & samp_name : m_samplingNames)
89 {
90 bool failed = false;
91 const PackType sampling = (PackType) get_sampling_from_string(samp_name, failed);
92
93 if (failed)
94 {
95 ATH_MSG_ERROR( "Calorimeter sampling" << samp_name
96 << " is not a valid Calorimeter sampling name and will be ignored! "
97 << "Valid names are: "
98 << "PreSamplerB, EMB1, EMB2, EMB3, "
99 << "PreSamplerE, EME1, EME2, EME3, "
100 << "HEC0, HEC1, HEC2, HEC3, "
101 << "TileBar0, TileBar1, TileBar2, "
102 << "TileGap1, TileGap2, TileGap3, "
103 << "TileExt0, TileExt1, TileExt2, "
104 << "FCAL0, FCAL1, FCAL2." );
105 }
106 else
107 {
108 seed_samplings |= ((PackType) 1) << sampling;
109 }
110 }
111
112 auto get_calo_from_string = [](const std::string & str, bool & failed)
113 {
114 failed = false;
117 LAREM, LARHEC,
118 LARFCAL, TILE,
119 LARMINIFCAL
120 )
121 )
122 else
123 {
124 failed = true;
126 }
127 };
128
129
130 auto calo_to_sampling_mask = [](const CaloCell_ID::SUBCALO sc) -> PackType
131 {
132 switch (sc)
133 {
135 return 0xFFU;
136 //PreSamplerB=0, EMB1, EMB2, EMB3,
137 //PreSamplerE, EME1, EME2, EME3=7,
139 return 0xF00U;
140 //HEC0=8, HEC1, HEC2, HEC3=11,
142 return 0x1FF000U;
143 //TileBar0=12, TileBar1, TileBar2,
144 //TileGap1, TileGap2, TileGap3,
145 //TileExt0, TileExt1, TileExt2=20,
147 return 0xE00000U;
148 //FCAL0=21, FCAL1, FCAL2=23
150 return 0xF000000U;
151 //MINIFCAL0=24, MINIFCAL1, MINIFCAL2, MINIFCAL3=27,
152 default:
153 return 0;
154 }
155 };
156
157 PackType & calo_samplings = m_options.m_options->valid_calorimeter_by_sampling;
158
159 calo_samplings = 0;
160
161 for (const std::string & calo_name : m_caloNames)
162 {
163 bool failed = false;
164 const PackType sample_mask = calo_to_sampling_mask(get_calo_from_string(calo_name, failed));
165
166 if (failed)
167 {
168 ATH_MSG_ERROR( "Calorimeter " << calo_name
169 << " is not a valid Calorimeter name and will be ignored! "
170 << "Valid names are: LAREM, LARHEC, LARFCAL, and TILE." );
171 }
172 else
173 {
174 calo_samplings |= sample_mask;
175 }
176 }
177
178 auto get_neighbour_option_from_string = [](const std::string & str, bool & failed)
179 {
180 failed = false;
183 prevInPhi,
184 nextInPhi,
185 prevInEta,
186 nextInEta,
187 faces2D,
188 corners2D,
189 all2D,
190 prevInSamp,
191 nextInSamp,
192 upAndDown,
193 prevSubDet,
194 nextSubDet,
195 all3D,
196 corners3D,
197 all3DwithCorners,
198 prevSuperCalo,
199 nextSuperCalo,
200 super3D
201 )
202 )
203 else
204 {
205 failed = true;
207 }
208 };
209
210 bool neigh_failed = false;
211 m_options.m_options->neighbour_options = (unsigned int) get_neighbour_option_from_string(m_neighborOptionString, neigh_failed);
212
213 if (neigh_failed)
214 {
215 ATH_MSG_ERROR("Invalid Neighbour Option: " << m_neighborOptionString);
216 }
217
218 m_options.m_options->seed_threshold = m_seedThresholdOnEorAbsEinSigma;
219 m_options.m_options->grow_threshold = m_neighborThresholdOnEorAbsEinSigma;
220 m_options.m_options->terminal_threshold = m_cellThresholdOnEorAbsEinSigma;
221 m_options.m_options->abs_seed = m_seedCutsInAbsE;
222 m_options.m_options->abs_grow = m_neighborCutsInAbsE;
223 m_options.m_options->abs_terminal = m_cellCutsInAbsE;
224 m_options.m_options->use_two_gaussian = m_twoGaussianNoise;
225
226 m_options.m_options->treat_L1_predicted_as_good = m_treatL1PredictedCellsAsGood;
227 m_options.m_options->use_time_cut = m_cutCellsInTime;
228 m_options.m_options->keep_significant_cells = m_keepSignificantCells;
229 m_options.m_options->completely_exclude_cut_seeds = m_excludeCutSeedsFromClustering;
230 m_options.m_options->time_threshold = m_timeThreshold;
231 m_options.m_options->snr_threshold_for_keeping_cells = m_thresholdForKeeping;
232
233 m_options.m_options->limit_HECIW_and_FCal_neighs = m_restrictHECIWandFCalNeighbors;
234 m_options.m_options->limit_PS_neighs = m_restrictPSNeighbors;
235
236 m_options.m_options->use_crosstalk = m_xtalkEM2;
237 m_options.m_options->crosstalk_delta = m_xtalkDeltaT;
238
239 ATH_CHECK( m_kernelSizeOptimizer.retrieve() );
240
241 return StatusCode::SUCCESS;
242}
243
245{
246 m_options.sendToGPU();
248
249 return StatusCode::SUCCESS;
250}
251
252
253
254StatusCode TopoAutomatonClustering::execute(const EventContext & ctx, const ConstantDataHolder & constant_data,
255 EventDataHolder & event_data, void * /*temporary_buffer*/ ) const
256{
257
258 using clock_type = boost::chrono::thread_clock;
259 auto time_cast = [](const auto & before, const auto & after)
260 {
261 return boost::chrono::duration_cast<boost::chrono::microseconds>(after - before).count();
262 };
263
264 const auto start = clock_type::now();
265
266 const auto before_snr = clock_type::now();
267
268 signalToNoise(event_data, constant_data, m_options, *(m_kernelSizeOptimizer.get()), m_measureTimes);
269
270 const auto before_pairs = clock_type::now();
271
272 cellPairs(event_data, constant_data, m_options, *(m_kernelSizeOptimizer.get()), m_measureTimes);
273
274 const auto before_growing = clock_type::now();
275
276 clusterGrowing(event_data, constant_data, m_options, *(m_kernelSizeOptimizer.get()), m_measureTimes);
277
278 const auto end = clock_type::now();
279
280
281 if (m_measureTimes)
282 {
283 record_times(ctx.evt(),
284 time_cast(start, before_snr),
285 time_cast(before_snr, before_pairs),
286 time_cast(before_pairs, before_growing),
287 time_cast(before_growing, end)
288 );
289 }
290
291 return StatusCode::SUCCESS;
292
293
294}
295
296
298{
299 if (m_measureTimes)
300 {
301 print_times("Preprocessing Signal-to-Noise_Ratio Cell_Pair_Creation Cluster_Growing", 4);
302 }
303 return StatusCode::SUCCESS;
304}
305
#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={})