ATLAS Offline Software
Loading...
Searching...
No Matches
CaloCellsCounterCPU.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
12
13#include <map>
14#include <filesystem>
15
16using namespace CaloRecGPU;
17
18CaloCellsCounterCPU::CaloCellsCounterCPU(const std::string & type, const std::string & name, const IInterface * parent):
19 base_class(type, name, parent)
20{
21}
22
23
25{
26 ATH_CHECK( m_noiseCDOKey.initialize() );
27 ATH_CHECK( m_cellsKey.initialize() );
28 ATH_CHECK( detStore()->retrieve(m_calo_id, "CaloCell_ID") );
29 return StatusCode::SUCCESS;
30}
31
32namespace {
33
34struct size_struct
35{
36 unsigned int total = 0, seed = 0, grow = 0, term = 0, invalid = 0, shared = 0;
37 template <class Str>
38 friend Str & operator << (Str & s, const size_struct & sst)
39 {
40 s << sst.total << " " << sst.seed << " " << sst.grow << " " << sst.term << " " << sst.invalid << " " << sst.shared;
41 return s;
42 }
43};
44
45struct cluster_info_struct
46{
47 size_struct size;
48 float seed_snr = -9e99;
49 float seed_energy = -9e99;
50 int seed_index = -1;
51 template <class Str>
52 friend Str & operator << (Str & s, const cluster_info_struct & cis)
53 {
54 s << cis.seed_index << " " << cis.size << " (" << cis.seed_snr << " " << cis.seed_energy << ")";
55 return s;
56 }
57};
58
59} // anonymous namespace
60
61StatusCode CaloCellsCounterCPU::execute (const EventContext & ctx, xAOD::CaloClusterContainer * cluster_collection) const
62{
63
65 if ( !cell_collection.isValid() )
66 {
67 ATH_MSG_ERROR( " Cannot retrieve CaloCellContainer: " << cell_collection.name() );
68 return StatusCode::FAILURE;
69 }
70
71
73 const CaloNoise * noise_tool = *noise_handle;
74
75 unsigned int gain_counts[GainConversion::num_gain_values()] = {0};
76
77 size_struct global_counts, global_cluster_counts;
78
79 for (CaloCellContainer::const_iterator iCells = cell_collection->begin(); iCells != cell_collection->end(); ++iCells)
80 {
81 const CaloCell * cell = (*iCells);
82
83 const float energy = cell->energy();
84
85 float SNR = energy / noise_tool->getNoise(m_calo_id->calo_cell_hash(cell->ID()), cell->gain());
86
87 const unsigned int gain = GainConversion::from_standard_gain(cell->gain());
88
89 ++gain_counts[gain - GainConversion::min_gain_value()];
90
91 SNR = std::abs(SNR);
92
93 if (SNR > m_seedThreshold)
94 {
95 ++global_counts.seed;
96 }
97 else if (SNR > m_growThreshold)
98 {
99 ++global_counts.grow;
100 }
101 else if (SNR > m_cellThreshold)
102 {
103 ++global_counts.term;
104 }
105 else
106 {
107 ++global_counts.invalid;
108 }
109 }
110
111 struct cluster_cell_info
112 {
113 const xAOD::CaloCluster * cl_1 = nullptr, * cl_2 = nullptr;
114 double w_1 = -1, w_2 = -1, energy = -9e99, SNR = -9e99;
115 void add_cluster(const int cell_id, const xAOD::CaloCluster * cl, const double w)
116 {
117 if (cl_1 == nullptr)
118 {
119 cl_1 = cl;
120 w_1 = w;
121 }
122 else if (cl_2 == nullptr)
123 {
124 cl_2 = cl;
125 w_2 = w;
126 }
127 else
128 {
129 std::cout << "WARNING! Multiple shared cell: " << cell_id << " " << cl_1 << " " << cl_2 << " " << cl << std::endl;
130 }
131 }
132
133 bool is_shared() const
134 {
135 return cl_1 != nullptr && cl_2 != nullptr;
136 }
137
138 };
139
140 std::map<int, cluster_cell_info> cluster_cells;
141
142
143 for (const xAOD::CaloCluster * cluster : *cluster_collection)
144 {
145 //const xAOD::CaloCluster * cluster = (*cluster_iter);
146 const CaloClusterCellLink * cell_links = cluster->getCellLinks();
147 if (!cell_links)
148 {
149 ATH_MSG_ERROR("Can't get valid links to CaloCells (CaloClusterCellLink)!");
150 return StatusCode::FAILURE;
151 }
152
153 for (auto it = cell_links->begin(); it != cell_links->end(); ++it)
154 {
155 const CaloCell * cell = *it;
156 const float weight = it.weight();
157
158 const float this_energy = std::abs(cell->energy());
159
160 const float this_snr = std::abs(this_energy / noise_tool->getNoise(m_calo_id->calo_cell_hash(cell->ID()), cell->gain()));
161
162 const IdentifierHash this_hash = m_calo_id->calo_cell_hash(cell->ID());
163
164 auto & info = cluster_cells[this_hash];
165
166 info.energy = this_energy;
167 info.SNR = this_snr;
168
169 info.add_cluster(this_hash, cluster, weight);
170
171 }
172 }
173
174 std::unordered_map<const xAOD::CaloCluster *, cluster_info_struct> cluster_sizes;
175
176 auto update_clusters = [&](const cluster_cell_info & cci, const int cell)
177 {
178 auto update_one = [&](const xAOD::CaloCluster * cl)
179 {
180 if (cl)
181 {
182 auto & c_info = cluster_sizes[cl];
183 ++c_info.size.total;
184 if (cci.SNR > m_seedThreshold)
185 {
186 ++c_info.size.seed;
187 }
188 else if (cci.SNR > m_growThreshold)
189 {
190 ++c_info.size.grow;
191 }
192 else if (cci.SNR > m_cellThreshold)
193 {
194 ++c_info.size.term;
195 }
196 else
197 {
198 ++c_info.size.invalid;
199 }
200
201 if (cci.is_shared())
202 {
203 ++c_info.size.shared;
204 }
205 else
206 {
207 if (cci.SNR > c_info.seed_snr || (cci.SNR == c_info.seed_snr && cell > c_info.seed_index))
208 {
209 c_info.seed_index = cell;
210 c_info.seed_snr = cci.SNR;
211 c_info.seed_energy = cci.energy;
212 }
213 }
214 }
215 };
216
217 if (cci.cl_1 != nullptr || cci.cl_2 != nullptr)
218 {
219 ++global_cluster_counts.total;
220 if (cci.SNR > m_seedThreshold)
221 {
222 ++global_cluster_counts.seed;
223 }
224 else if (cci.SNR > m_growThreshold)
225 {
226 ++global_cluster_counts.grow;
227 }
228 else if (cci.SNR > m_cellThreshold)
229 {
230 ++global_cluster_counts.term;
231 }
232 else
233 {
234 ++global_cluster_counts.invalid;
235 }
236 if (cci.is_shared())
237 {
238 ++global_cluster_counts.shared;
239 }
240 }
241
242 update_one(cci.cl_1);
243 update_one(cci.cl_2);
244 };
245
246 for (auto & it : cluster_cells)
247 {
248 update_clusters(it.second, it.first);
249 }
250
251 std::vector<cluster_info_struct> sorted_info;
252
253 sorted_info.reserve(cluster_sizes.size());
254
255 for (auto & v : cluster_sizes)
256 {
257 sorted_info.push_back(v.second);
258 }
259
260 std::sort(sorted_info.begin(), sorted_info.end(),
261 [](const auto & a, const auto & b)
262 {
263 return a.seed_index < b.seed_index;
264 });
265
266
267 const auto err1 = StandaloneDataIO::prepare_folder_for_output(std::string(m_savePath));
269 {
270 return StatusCode::FAILURE;
271 }
272
273 const std::filesystem::path save_file = m_savePath + "/" + StandaloneDataIO::build_filename((m_filePrefix.size() > 0 ? m_filePrefix + "_counts" : "counts"),
274 ctx.evt(), m_fileSuffix, "txt", m_numWidth);
275
276 std::ofstream out_file(save_file);
277
278 if (!out_file.is_open())
279 {
280 return StatusCode::FAILURE;
281 }
282
283 out_file << "Cell counts: " << global_counts << "\n\n";
284
285 out_file << "Cells in clusters count: " << global_cluster_counts << "\n\n";
286 out_file << "Clusters:\n\n";
287
288 for (const auto & info : sorted_info)
289 {
290 out_file << info << "\n";
291 }
292
293 out_file << std::endl;
294
295 if (!out_file.good())
296 {
297 return StatusCode::FAILURE;
298 }
299
300 out_file.close();
301
302 return StatusCode::SUCCESS;
303
304}
305
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
defines an "iterator" over instances of a given type in StoreGateSvc
static Double_t a
std::ostream & operator<<(std::ostream &lhs, const TestGaudiProperty &rhs)
Data object for each calorimeter readout cell.
Definition CaloCell.h:57
SG::ReadHandleKey< CaloCellContainer > m_cellsKey
vector of names of the cell containers to use as input.
Gaudi::Property< float > m_growThreshold
Value to consider for the seed threshold.
Gaudi::Property< float > m_cellThreshold
Value to consider for the seed threshold.
SG::ReadCondHandleKey< CaloNoise > m_noiseCDOKey
Key of the CaloNoise Conditions data object.
virtual StatusCode initialize() override
Gaudi::Property< unsigned int > m_numWidth
The number of digits to reserve for the events.
virtual StatusCode execute(const EventContext &ctx, xAOD::CaloClusterContainer *cluster_collection) const override
const CaloCell_ID * m_calo_id
Pointer to Calo ID Helper.
Gaudi::Property< std::string > m_savePath
The path specifying the folder to which the files should be saved.
CaloCellsCounterCPU(const std::string &type, const std::string &name, const IInterface *parent)
Gaudi::Property< std::string > m_filePrefix
The prefix of the saved files.
Gaudi::Property< float > m_seedThreshold
Value to consider for the seed threshold.
Gaudi::Property< std::string > m_fileSuffix
The suffix of the saved files.
float getNoise(const IdentifierHash h, const int gain) const
Accessor by IdentifierHash and gain.
Definition CaloNoise.h:34
static constexpr GainType from_standard_gain(const int gain)
static constexpr GainType min_gain_value()
static constexpr GainType num_gain_values()
DataModel_detail::const_iterator< DataVector > const_iterator
Definition DataVector.h:838
This is a "hash" representation of an Identifier.
virtual bool isValid() override final
Can the handle be successfully dereferenced?
const std::string & name() const
Return the StoreGate ID for the referenced object.
Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration.
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
CaloCluster_v1 CaloCluster
Define the latest version of the calorimeter cluster class.
CaloClusterContainer_v1 CaloClusterContainer
Define the latest version of the calorimeter cluster container.
static std::string build_filename(const std::string &prefix, const std::string &text, const std::string &suffix, const std::string &ext)
static ErrorState prepare_folder_for_output(const std::filesystem::path &folder, const bool output_errors=true)