ATLAS Offline Software
Loading...
Searching...
No Matches
CaloRingsBuilder.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
5// =================================================================================
6#include "CaloRingsBuilder.h"
7
9
10// Cell includes:
12#include "CaloGeoHelpers/CaloSampling.h"
14
15// RingSet includes:
18
19// CaloRings includes:
22
23// Ringer Conf include:
25
26// Other xAOD includes:
27#include "xAODBase/IParticle.h"
29
30// STL
31#include <cmath>
32#include <vector>
33#include <span>
34#include <sstream>
35#include <stdexcept>
36
37namespace Ringer
38{
39
40 // =================================================================================
42 const std::string &name,
43 const ::IInterface *parent)
44 : ::AthAlgTool(type, name, parent),
45 m_rsCont(nullptr),
46 m_crCont(nullptr),
48 {
49 declareInterface<ICaloRingsBuilder>(this);
50 }
51
52 // =====================================================================================
54
55 // =====================================================================================
57 {
58 ATH_MSG_DEBUG("Initializing " << name());
59
60 m_nRingSets = m_nRings.size();
61
62 // Build RingSets configuration:
63 size_t offset = 0;
64
65 // Build RingSets configuration:
66 for (size_t rsConfIdx = 0; rsConfIdx < m_nRingSets; ++rsConfIdx)
67 {
68 const auto rsNLayers = m_nLayers[rsConfIdx];
69
70 std::vector<CaloSampling::CaloSample> rsLayers;
71 rsLayers.reserve(rsNLayers);
72
73 for (unsigned int s : std::span(m_layers.value().data() + offset, rsNLayers))
74 {
75 rsLayers.push_back(static_cast<CaloSampling::CaloSample>(s));
76 }
77
78 offset += rsNLayers;
79
81 m_nRings[rsConfIdx],
82 rsLayers,
83 m_etaWidth[rsConfIdx], m_phiWidth[rsConfIdx],
87
88 // Build our raw configuration structure:
89 m_rsRawConfCol.push_back(std::move(rawConf));
90 }
91
92 // We have finished filling the main raw configuration properties, now we add
93 // it bounderies:
94 try
95 {
97 }
98 catch (const std::runtime_error &e)
99 {
100 ATH_MSG_ERROR("Could not add collection bounderies due to: " << e.what());
101 ATH_MSG_ERROR("RawConfCollection is: ");
102 std::ostringstream str;
104 ATH_MSG_ERROR(str.str());
105 return StatusCode::FAILURE;
106 }
107
108 // Print our collection
109 if (msgLevel() <= MSG::DEBUG)
110 {
111 std::ostringstream str;
113 ATH_MSG_DEBUG(str.str());
114 }
115
116 // This will check that the properties were initialized properly
117 // by job configuration.
118 ATH_CHECK(m_crContName.initialize());
119 ATH_CHECK(m_rsContName.initialize());
120 ATH_CHECK(m_cellsContName.initialize());
121 ATH_CHECK(m_caloMgrKey.initialize());
122
123 return StatusCode::SUCCESS;
124 }
125
126 // =====================================================================================
128 {
129 return StatusCode::SUCCESS;
130 }
131
132 // =====================================================================================
133 StatusCode CaloRingsBuilder::preExecute(xAOD::CaloRingsContainer *crCont, xAOD::RingSetContainer *rsCont, std::size_t nReserve)
134 {
135 if (crCont && rsCont)
136 {
137 m_crCont = crCont;
138 m_rsCont = rsCont;
139 }
140 else
141 {
142 ATH_MSG_ERROR("Attempted to set CaloRingsContainer and/or RingSetContainer to invalid pointers");
143 return StatusCode::FAILURE;
144 }
145 // Reserve container space if required:
146 if (nReserve)
147 {
148 // Reserve one CaloRings per particle
149 m_crCont->reserve(nReserve);
150 // We need to reserve more space for the RingSet container, there will be
151 // the number of RawConfig available in our raw configuration collection.
152 m_rsCont->reserve(nReserve * m_nRingSets);
153 }
154
155 return StatusCode::SUCCESS;
156 }
157
158 // =====================================================================================
161 {
162 double et(0.);
163 const double eta2 = std::fabs(cluster.etaBE(2));
164 const double energy = cluster.e();
165 if (eta2 < 999.)
166 {
167 const double cosheta = std::cosh(eta2);
168 et = (cosheta != 0.) ? energy / cosheta : 0.;
169 }
170 if (et > m_minEnergy)
171 {
172 return executeTemp(cluster, clRings);
173 }
174 else
175 {
176 ATH_MSG_DEBUG("Skipping cluster with low energy (" << et << " MeV) .");
177 return StatusCode::SUCCESS;
178 }
179 }
180
181 // =====================================================================================
183 const xAOD::IParticle &particle,
185 {
186 double et = particle.pt();
187 if (et > m_minEnergy)
188 {
189 return executeTemp(particle, clRings);
190 }
191 else
192 {
193 ATH_MSG_DEBUG("Skipping particle with low energy (" << et << " MeV) .");
194 return StatusCode::SUCCESS;
195 }
196 }
197
198 // =====================================================================================
199 // Local execute
200 // =====================================================================================
201 template <typename T>
203 const T &input,
205 {
206
207 ATH_MSG_DEBUG("Entering " << name() << " execute.");
208
209 // Create structure to hold rings:
210 xAOD::CaloRings *clRings = new xAOD::CaloRings();
211
212 // Add the CaloRings to the container:
213 m_crCont->push_back(clRings);
214
215 // Set elementLink reference to created CaloRings:
216 clRingsLink.toContainedElement(*m_crCont, clRings);
217
218 // If not using shower barycenter, we need to reset last valid seed to avoid
219 // any possible issue:
221 {
222 m_lastValidSeed = AtlasGeoPoint(input.eta(), input.phi());
223 }
224
225 // Build this CaloRings RingSets:
226 for (const auto &rawConf : m_rsRawConfCol)
227 {
228 // Create new RingSet and add it to the container:
229 m_rsCont->push_back(std::make_unique<xAOD::RingSet>(rawConf.nRings));
230 xAOD::RingSet *rs = m_rsCont->back();
231
232 // Get RingSet seed:
233 AtlasGeoPoint seed;
234 CHECK(getRingSetSeed(rawConf, input, seed));
235
236 // Build it:
237 CHECK(buildRingSet(rawConf, seed, rs));
238
239 // Get the ElementLink and add it to our RingSet holder:
241 clRings->addRingSetEL(rsEL);
242 }
243
244 // Print CaloRings with DEBUG level:
245 if (msgLevel() <= MSG::DEBUG)
246 {
247 std::ostringstream str;
248 clRings->print(str);
249 ATH_MSG_DEBUG(str.str());
250 }
251
252 return StatusCode::SUCCESS;
253 }
254
255 // =================================================================================
258 const xAOD::CaloCluster &cluster,
259 AtlasGeoPoint &seed)
260 {
262 {
263
264 seed.setEta(cluster.eta());
265 seed.setPhi(cluster.phi());
266
267 return StatusCode::SUCCESS;
268 }
269 else
270 {
271
272 bool foundValid = false, foundMultipleValid = false;
273
274 for (const auto layer : rawConf.layers)
275 {
276
277 AtlasGeoPoint seedCandidate(
278 cluster.etaSample(layer),
279 cluster.phiSample(layer));
280
281 ATH_MSG_DEBUG("This layer (" << CaloSampling::getSamplingName(layer) << ") seedCandidate is: (" << seedCandidate.eta() << "," << seedCandidate.phi() << ")");
282
283 if (seedCandidate.isValid())
284 {
285 m_lastValidSeed = seedCandidate;
286 if (foundValid)
287 foundMultipleValid = true;
288 foundValid = true;
289 }
290 }
291
292 // If we get here, set it to the last valid seed:
293 seed = m_lastValidSeed;
294 if (foundMultipleValid)
295 {
296 ATH_MSG_WARNING("Found multiple valid seeds. Set to last valid candidate.");
297 }
298 return StatusCode::SUCCESS;
299 }
300 }
301
302 // =================================================================================
304 const xAOD::RingSetConf::RawConf & /*rawConf*/,
305 const xAOD::IParticle &part,
306 AtlasGeoPoint &seed)
307 {
308
309 seed.setEta(part.eta());
310 seed.setPhi(part.phi());
311
312 return StatusCode::SUCCESS;
313 }
314
317 const AtlasGeoPoint &seed,
319 {
320 // Get this RingSet size:
321 const auto nRings = rawConf.nRings;
322
323 // Retrieve CaloCells
325 // check is only used for serial running; remove when MT scheduler used
326 if (!cellsCont.isValid())
327 {
328 ATH_MSG_FATAL("Failed to retrieve " << m_cellsContName.key());
329 return StatusCode::FAILURE;
330 }
331
333 const CaloDetDescrManager *caloMgr = *caloMgrHandle;
334
335 CaloCellList cells(caloMgr, cellsCont.ptr());
336
337 // loop over cells
338 for (const int layer : rawConf.layers)
339 { // We use int here because the
340 // cells.select() method needs int as param
341 cells.select(seed.eta(), seed.phi(), m_cellMaxDEtaDist, m_cellMaxDPhiDist, layer);
342 for (const CaloCell *cell : cells)
343 {
344
345 unsigned int ringNumber(0);
346
347 // calculate the normalised difference in eta
348 const float deltaEta = std::fabs(
349 (cell->eta() - seed.eta())) /
350 rawConf.etaWidth;
351 // calculate the normalised difference in phi
352 const float deltaPhi = std::fabs(
353 CaloPhiRange::diff(cell->phi(), seed.phi())) /
354 rawConf.phiWidth;
355 // The biggest difference indicates the ring number (we are using
356 // squared-shape rings)
357 const float deltaGreater = std::max(deltaEta, deltaPhi);
358
359 // Round to nearest integer:
360 ringNumber = static_cast<unsigned int>(std::floor(deltaGreater + .5));
361 if (ringNumber < nRings)
362 {
364 {
365 rs->at(ringNumber) += cell->energy() / std::cosh(cell->eta());
366 }
367 else
368 {
369 rs->at(ringNumber) += cell->energy();
370 }
371 }
372 }
373 }
374
375 return StatusCode::SUCCESS;
376 }
377
378} // namespace Ringer
Scalar deltaPhi(const MatrixBase< Derived > &vec) const
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_FATAL(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
Helpers for checking error return status codes and reporting errors.
#define CHECK(...)
Evaluate an expression and check for errors.
float et(const xAOD::jFexSRJetRoI *j)
static Double_t rs
AthAlgTool(const std::string &type, const std::string &name, const IInterface *parent)
Constructor with parameters:
float eta() const
bool isValid() const
float phi() const
Data object for each calorimeter readout cell.
Definition CaloCell.h:57
This class provides the client interface for accessing the detector description information common to...
static double diff(double phi1, double phi2)
simple phi1 - phi2 calculation, but result is fixed to respect range.
static std::string getSamplingName(CaloSample theSample)
Returns a string (name) for each CaloSampling.
virtual StatusCode buildRingSet(const xAOD::RingSetConf::RawConf &rawConf, const AtlasGeoPoint &seed, xAOD::RingSet *rs)
Tool protected methods:
CaloRingsBuilder(const std::string &type, const std::string &name, const IInterface *parent)
Default constructor.
~CaloRingsBuilder()
Destructor.
SG::WriteHandleKey< xAOD::RingSetContainer > m_rsContName
Name of RingSetContainer on Event StoreGate.
const xAOD::RingSetConf::RawConfCollection & rawConf() override
Extra methods:
xAOD::RingSetConf::RawConfCollection m_rsRawConfCol
holds each RingSet configuration (filled at initialize)
virtual StatusCode execute(const xAOD::IParticle &particle, ElementLink< xAOD::CaloRingsContainer > &clRingsLink) override
build CaloRings for IParticle
StatusCode getRingSetSeed(const xAOD::RingSetConf::RawConf &conf, const xAOD::CaloCluster &cluster, AtlasGeoPoint &seed)
Fill RingSet seed for CaloCluster.
SG::WriteHandleKey< xAOD::CaloRingsContainer > m_crContName
Tool props (python configurables):
Gaudi::Property< float > m_minEnergy
Minimum particle energy to build rings (GeV).
size_t m_nRingSets
hold the number of RingSets we are building for each CaloRings
Gaudi::Property< std::vector< float > > m_etaWidth
Width of the ring in eta.
Gaudi::Property< bool > m_doTransverseEnergy
Switch to use raw cell energy instead ET.
StatusCode executeTemp(const T &input, ElementLink< xAOD::CaloRingsContainer > &crEL)
Tool private methods:
Gaudi::Property< std::vector< unsigned int > > m_nLayers
Number of calorimeter layers in each ringset.
Gaudi::Property< float > m_cellMaxDEtaDist
Maximum cell distance in eta to seed.
xAOD::RingSetContainer * m_rsCont
Tool props (non configurables):
SG::ReadCondHandleKey< CaloDetDescrManager > m_caloMgrKey
virtual StatusCode preExecute(xAOD::CaloRingsContainer *crCont, xAOD::RingSetContainer *rsCont, const std::size_t nReserve=0) override
method for working on containers
Gaudi::Property< std::vector< float > > m_phiWidth
Width of the ring in phi.
xAOD::CaloRingsContainer * m_crCont
Create and hold CaloRingsContainer for each event.
SG::ReadHandleKey< CaloCellContainer > m_cellsContName
Name of CaloCellContainer.
AtlasGeoPoint m_lastValidSeed
last valid RingSet seed
Gaudi::Property< std::vector< unsigned int > > m_nRings
Number of rings in a ringset.
Gaudi::Property< bool > m_useShowShapeBarycenter
Switch to use shower barycenter seed for each RingSets.
Gaudi::Property< std::vector< int > > m_layers
Calorimeter layers in each ringset.
virtual StatusCode finalize() override
finalize method
virtual StatusCode initialize() override
Tool main methods:
Gaudi::Property< float > m_cellMaxDPhiDist
Maximum cell distance in phi to seed.
const_pointer_type ptr()
Dereference the pointer.
virtual bool isValid() override final
Can the handle be successfully dereferenced?
float phiSample(const CaloSample sampling) const
Retrieve barycenter in a given sample.
virtual double eta() const
The pseudorapidity ( ) of the particle.
virtual double e() const
The total energy of the particle.
virtual double phi() const
The azimuthal angle ( ) of the particle.
float etaSample(const CaloSample sampling) const
Retrieve barycenter in a given sample.
float etaBE(const unsigned layer) const
Get the eta in one layer of the EM Calo.
void print(std::ostream &stream) const
Print-out methods:
void addRingSetEL(const ElementLink< RingSetContainer_v1 > &rsEL)
Add ElementLink to holden vector.
Class providing the definition of the 4-vector interface.
static Ringer::CalJointLayer whichLayer(const std::vector< CaloSampling::CaloSample > &layers)
static void print(const RawConf &raw, std::ostream &stream)
Prints rawConf.
static Ringer::CalJointSection whichSection(const std::vector< CaloSampling::CaloSample > &layers)
static void addRawConfColBounderies(RawConfCollection &clRingsConf)
Add to RawConfCollection its JointLayer/JointSection bounderies.
Namespace dedicated for Ringer utilities.
RingSet_v1 RingSet
Definition of the current "RingSet version".
Definition RingSet.h:15
CaloRings_v1 CaloRings
Definition of the current "CaloRings version".
CaloCluster_v1 CaloCluster
Define the latest version of the calorimeter cluster class.
RingSetContainer_v1 RingSetContainer
Definition of the current "RingSet container version".
CaloRingsContainer_v1 CaloRingsContainer
Definition of the current "CaloRings container version".
Extra patterns decribing particle interation process.