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