ATLAS Offline Software
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 
7 #include "CaloCellsCounterCPU.h"
8 #include "CaloRecGPU/Helpers.h"
11 #include "StoreGate/DataHandle.h"
12 
13 #include <map>
14 #include <filesystem>
15 
16 using namespace CaloRecGPU;
17 
18 CaloCellsCounterCPU::CaloCellsCounterCPU(const std::string & type, const std::string & name, const IInterface * parent):
19  base_class(type, name, parent)
20 {
21 }
22 
23 
25 {
28  ATH_CHECK( detStore()->retrieve(m_calo_id, "CaloCell_ID") );
29  return StatusCode::SUCCESS;
30 }
31 
32 namespace {
33 
34 struct 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 
45 struct 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 
61 StatusCode CaloCellsCounterCPU::execute (const EventContext & ctx, xAOD::CaloClusterContainer * cluster_collection) const
62 {
63 
64  SG::ReadHandle<CaloCellContainer> cell_collection(m_cellsKey, ctx);
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 
python.PyKernel.retrieve
def retrieve(aClass, aKey=None)
Definition: PyKernel.py:110
StandaloneDataIO::build_filename
static std::string build_filename(const std::string &prefix, const std::string &text, const std::string &suffix, const std::string &ext)
Definition: StandaloneDataIO.h:273
CaloCellsCounterCPU::m_fileSuffix
Gaudi::Property< std::string > m_fileSuffix
The suffix of the saved files.
Definition: CaloCellsCounterCPU.h:59
DataModel_detail::const_iterator
Const iterator class for DataVector/DataList.
Definition: DVLIterator.h:82
ReadCellNoiseFromCool.cell
cell
Definition: ReadCellNoiseFromCool.py:53
athena.path
path
python interpreter configuration --------------------------------------—
Definition: athena.py:128
SG::ReadCondHandle
Definition: ReadCondHandle.h:44
SG::ReadHandle
Definition: StoreGate/StoreGate/ReadHandle.h:67
SG::VarHandleBase::name
const std::string & name() const
Return the StoreGate ID for the referenced object.
Definition: AthToolSupport/AsgDataHandles/Root/VarHandleBase.cxx:75
CaloCondBlobAlgs_fillNoiseFromASCII.gain
gain
Definition: CaloCondBlobAlgs_fillNoiseFromASCII.py:109
skel.it
it
Definition: skel.GENtoEVGEN.py:407
CaloCellsCounterCPU::m_cellThreshold
Gaudi::Property< float > m_cellThreshold
Value to consider for the seed threshold.
Definition: CaloCellsCounterCPU.h:89
CaloCellsCounterCPU::m_cellsKey
SG::ReadHandleKey< CaloCellContainer > m_cellsKey
vector of names of the cell containers to use as input.
Definition: CaloCellsCounterCPU.h:69
CaloNoise::getNoise
float getNoise(const IdentifierHash h, const int gain) const
Accessor by IdentifierHash and gain.
Definition: CaloNoise.h:34
DataHandle.h
python.CaloAddPedShiftConfig.type
type
Definition: CaloAddPedShiftConfig.py:42
dqt_zlumi_pandas.weight
int weight
Definition: dqt_zlumi_pandas.py:190
CaloCellsCounterCPU::m_seedThreshold
Gaudi::Property< float > m_seedThreshold
Value to consider for the seed threshold.
Definition: CaloCellsCounterCPU.h:79
CaloCellsCounterCPU::initialize
virtual StatusCode initialize() override
Definition: CaloCellsCounterCPU.cxx:24
python.setupRTTAlg.size
int size
Definition: setupRTTAlg.py:39
StandaloneDataIO::ErrorState::OK
@ OK
xAOD::CaloCluster_v1
Description of a calorimeter cluster.
Definition: CaloCluster_v1.h:62
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
ParticleGun_FastCalo_ChargeFlip_Config.energy
energy
Definition: ParticleGun_FastCalo_ChargeFlip_Config.py:78
Helpers.h
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
test_pyathena.parent
parent
Definition: test_pyathena.py:15
StandaloneDataIO.h
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
SG::VarHandleKey::initialize
StatusCode initialize(bool used=true)
If this object is used as a property, then this should be called during the initialize phase.
Definition: AthToolSupport/AsgDataHandles/Root/VarHandleKey.cxx:103
MuonEfficiencyCorrectionsCfg.out_file
out_file
Definition: MuonEfficiencyCorrectionsCfg.py:69
DataVector
Derived DataVector<T>.
Definition: DataVector.h:794
SG::ReadHandle::isValid
virtual bool isValid() override final
Can the handle be successfully dereferenced?
CaloNoise
Definition: CaloNoise.h:16
python.PyKernel.detStore
detStore
Definition: PyKernel.py:41
StandaloneDataIO::prepare_folder_for_output
static ErrorState prepare_folder_for_output(const std::filesystem::path &folder, const bool output_errors=true)
Definition: StandaloneDataIO.h:264
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:240
plotBeamSpotMon.b
b
Definition: plotBeamSpotMon.py:76
CaloCellsCounterCPU::m_savePath
Gaudi::Property< std::string > m_savePath
The path specifying the folder to which the files should be saved.
Definition: CaloCellsCounterCPU.h:49
operator<<
std::ostream & operator<<(std::ostream &lhs, const TestGaudiProperty &rhs)
Definition: TestGaudiProperty.cxx:69
SG::CondHandleKey::initialize
StatusCode initialize(bool used=true)
CaloCellsCounterCPU::m_calo_id
const CaloCell_ID * m_calo_id
Pointer to Calo ID Helper.
Definition: CaloCellsCounterCPU.h:96
DataVector::end
const_iterator end() const noexcept
Return a const_iterator pointing past the end of the collection.
python.PyAthena.v
v
Definition: PyAthena.py:154
a
TList * a
Definition: liststreamerinfos.cxx:10
CaloCell
Data object for each calorimeter readout cell.
Definition: CaloCell.h:57
CaloCellsCounterCPU.h
CaloCellsCounterCPU::m_numWidth
Gaudi::Property< unsigned int > m_numWidth
The number of digits to reserve for the events.
Definition: CaloCellsCounterCPU.h:64
CUDAFriendlyClasses.h
CaloCellsCounterCPU::CaloCellsCounterCPU
CaloCellsCounterCPU(const std::string &type, const std::string &name, const IInterface *parent)
Definition: CaloCellsCounterCPU.cxx:18
python.SystemOfUnits.s
float s
Definition: SystemOfUnits.py:147
CaloCellsCounterCPU::m_noiseCDOKey
SG::ReadCondHandleKey< CaloNoise > m_noiseCDOKey
Key of the CaloNoise Conditions data object.
Definition: CaloCellsCounterCPU.h:74
python.IoTestsLib.w
def w
Definition: IoTestsLib.py:198
CaloRecGPU
Definition: BaseDefinitions.h:11
CaloCellsCounterCPU::execute
virtual StatusCode execute(const EventContext &ctx, xAOD::CaloClusterContainer *cluster_collection) const override
Definition: CaloCellsCounterCPU.cxx:61
dq_make_web_display.cl
cl
print [x.__class__ for x in toList(dqregion.getSubRegions()) ]
Definition: dq_make_web_display.py:25
python.ParticleTypeUtil.info
def info
Definition: ParticleTypeUtil.py:87
DataVector::begin
const_iterator begin() const noexcept
Return a const_iterator pointing at the beginning of the collection.
CaloCellsCounterCPU::m_filePrefix
Gaudi::Property< std::string > m_filePrefix
The prefix of the saved files.
Definition: CaloCellsCounterCPU.h:54
CaloCellsCounterCPU::m_growThreshold
Gaudi::Property< float > m_growThreshold
Value to consider for the seed threshold.
Definition: CaloCellsCounterCPU.h:84