ATLAS Offline Software
Loading...
Searching...
No Matches
CaloCalibClusterMomentsMaker2.h
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
5#ifndef CALOCALIBHITREC_CALOCALIBCLUSTERMOMENTSMAKER2_H
6#define CALOCALIBHITREC_CALOCALIBCLUSTERMOMENTSMAKER2_H
14
15class CaloCell_ID;
16class CaloDM_ID;
20
21#include "GaudiKernel/ToolHandle.h"
22
24#include "CaloGeoHelpers/CaloSampling.h"
31#include "CLHEP/Units/SystemOfUnits.h"
33
34#include <string>
35#include <vector>
36#include <set>
37#include <map>
38#include <atomic>
39#include <array>
40#include <cmath>
41
43{
44 public:
45
47 public:
49 };
50
51 class MyCellInfo : public std::vector<std::pair<int, double> > {
52 public:
53 MyCellInfo(int iClus, double w) { this->emplace_back(iClus, w); }
54 void Add(const MyCellInfo& other) { this->insert(this->end(), other.begin(), other.end()); }
55 };
56
57 typedef std::map<Identifier, MyCellInfo> CellInfoSet_t;
58
59 class MyClusInfo {
60 public:
62 public:
63 double engTot = 0.0;
64 std::array<double, CaloSampling::Unknown + 1> engSmp{};
65 void Add(double eng, int nsmp)
66 {
67 engTot += eng;
68 engSmp[nsmp] += eng;
69 }
70 };
71
72 void Add(double eng, int nsmp, int pid = 0)
73 {
74 engCalibIn.Add(eng, nsmp);
75 engCalibParticle[pid].Add(eng, nsmp);
76 }
77
79 double engCalibOut = 0.0;
80 double engCalibDead = 0.0;
81 std::array<double, CaloDmDescrArea::DMA_MAX> engCalibDeadInArea{};
82 std::map<int, ClusCalibEnergy> engCalibParticle{};
83 };
84 typedef std::vector<MyClusInfo> ClusInfo_t;
85 using ClusList = std::vector<std::vector<int> >;
86
87 typedef std::pair<std::string, xAOD::CaloCluster::MomentType> moment_name_pair;
88 typedef std::vector<moment_name_pair> moment_name_vector;
89 typedef std::set<moment_name_pair> moment_name_set;
90
91 CaloCalibClusterMomentsMaker2(const std::string& type, const std::string& name,
92 const IInterface* parent);
93
95 virtual StatusCode execute(const EventContext& ctx,
96 xAOD::CaloClusterContainer* theClusColl) const override;
97 virtual StatusCode initialize() override;
98
118 int n_phi_out,
119 int n_eta_out,
120 double out_phi_max,
121 double out_eta_max,
122 const double (&rmaxOut)[3],
123 std::array<std::vector<std::vector<CalibHitIPhiIEtaRange> >, 3>& i_phi_eta);
137 static void buildCellInfoMap(const xAOD::CaloClusterContainer& theClusColl,
138 CellInfoSet_t& cellInfo);
139
161
163 const xAOD::CaloClusterContainer& theClusColl,
164 const ClusInfo_t& clusInfoVec,
165 int n_phi_out,
166 int n_eta_out,
167 double out_phi_max,
168 double out_eta_max,
169 const std::array<std::vector<std::vector<CalibHitIPhiIEtaRange> >, 3>& i_phi_eta,
170 const std::array<bool, 3>& doOutOfCluster,
171 const std::array<ClusList*, 3>& clusLists);
172
173
198 template <class InvalidUniqueIdHandler>
200 const std::vector<const CaloCalibrationHitContainer*>& v_cchc,
201 const CellInfoSet_t& cellInfo,
202 const CaloCell_ID& calo_id,
203 ClusInfo_t& clusInfoVec,
204 unsigned int& nHitsTotal,
205 unsigned int& nHitsWithoutParticleUID,
206 bool useParticleID,
207 InvalidUniqueIdHandler&& invalidUniqueIdHandler)
208 {
209 for (const CaloCalibrationHitContainer* cchc : v_cchc) {
210 for (const CaloCalibrationHit* hit : *cchc) {
211 const Identifier myId = hit->cellID();
212 typename CellInfoSet_t::const_iterator pos = cellInfo.find(myId);
213
214 if (pos != cellInfo.end()) {
215 const CaloSampling::CaloSample nsmp =
217
218 for (const std::pair<int, double>& p : pos->second) {
219 const int iClus = p.first;
220 const double weight = p.second;
221
222 if (useParticleID) {
223 const int uniqueID = HepMC::uniqueID(hit);
224 if (uniqueID == HepMC::INVALID_PARTICLE_ID) {
225 invalidUniqueIdHandler();
226 break;
227 }
228 clusInfoVec[iClus].Add(weight * hit->energyTotal(),
229 nsmp,
230 static_cast<unsigned int>(uniqueID));
231 }
232 else {
233 clusInfoVec[iClus].Add(weight * hit->energyTotal(), nsmp);
234 }
235 }
236 }
237
238 if (useParticleID && HepMC::uniqueID(hit) == HepMC::UNDEFINED_ID) {
239 ++nHitsWithoutParticleUID;
240 }
241 ++nHitsTotal;
242 }
243 }
244 }
245
246 template <class AddOutOfClusterEnergy>
248 const std::vector<const CaloCalibrationHitContainer*>& v_cchc,
249 const CellInfoSet_t& cellInfo,
250 const CaloDetDescrManager& calo_dd_man,
251 const ClusInfo_t& clusInfoVec,
252 int n_phi_out,
253 int n_eta_out,
254 double out_phi_max,
255 double out_eta_max,
256 const std::array<bool, 3>& doOutOfCluster,
257 const std::array<const ClusList*, 3>& clusLists,
258 AddOutOfClusterEnergy&& addOutOfClusterEnergy)
259 {
260 for (const CaloCalibrationHitContainer* cchc : v_cchc) {
261 for (const CaloCalibrationHit* hit : *cchc) {
262 const Identifier myId = hit->cellID();
263 typename CellInfoSet_t::const_iterator pos = cellInfo.find(myId);
264 if (pos != cellInfo.end()) {
265 continue;
266 }
267
268 const CaloDetDescrElement* myCDDE = calo_dd_man.get_element(myId);
269 const int uniqueID = HepMC::uniqueID(hit);
270 if (!myCDDE) {
271 continue;
272 }
273
274 const int jeO = static_cast<int>(std::floor(n_eta_out * (myCDDE->eta() / out_eta_max)));
275 if (jeO < -n_eta_out || jeO >= n_eta_out) {
276 continue;
277 }
278
279 int jpO = static_cast<int>(std::floor(n_phi_out * (myCDDE->phi() / out_phi_max)));
280 if (jpO < -n_phi_out) jpO += 2 * n_phi_out;
281 if (jpO >= n_phi_out) jpO -= 2 * n_phi_out;
282
283 for (unsigned int ii = 0; ii < 3; ++ii) {
284 const ClusList* pClusList = clusLists[ii];
285 if (!doOutOfCluster[ii] || pClusList == nullptr) {
286 continue;
287 }
288
289 double hitClusNorm = 0.0;
290 std::vector<int> hitClusIndex;
291 std::vector<double> hitClusEffEnergy;
292 const std::vector<int>& matchingClusters =
293 (*pClusList)[(jpO + n_phi_out) * (2 * n_eta_out + 1) + jeO + n_eta_out];
294
295 for (int iClus : matchingClusters) {
296 const MyClusInfo& clusInfo = clusInfoVec[iClus];
297 auto partPos = clusInfo.engCalibParticle.find(uniqueID);
298 if (partPos == clusInfo.engCalibParticle.end()) {
299 continue;
300 }
301 hitClusNorm += partPos->second.engTot;
302 hitClusEffEnergy.push_back(partPos->second.engTot);
303 hitClusIndex.push_back(iClus);
304 }
305
306 if (hitClusNorm <= 0.0) {
307 continue;
308 }
309
310 const double inv_hitClusNorm = 1.0 / hitClusNorm;
311 for (std::size_t i = 0; i < hitClusIndex.size(); ++i) {
312 const int iClus = hitClusIndex[i];
313 const double w = hitClusEffEnergy[i] * inv_hitClusNorm;
314 addOutOfClusterEnergy(ii, iClus, uniqueID, w * hit->energyTotal());
315 }
316 }
317 }
318 }
319 }
320
321
322
323
324 private:
336 template <class AddDeadMaterialEnergy>
338 const std::vector<const CaloCalibrationHitContainer*>& v_dmcchc,
339 const xAOD::CaloClusterContainer& theClusColl,
340 const ClusInfo_t& clusInfoVec,
341 const ClusList& clusList,
342 bool useParticleID,
343 AddDeadMaterialEnergy&& addDeadMaterialEnergy) const
344 {
345 for (const CaloCalibrationHitContainer* dmcchc : v_dmcchc) {
346 for (const CaloCalibrationHit* hit : *dmcchc) {
347 const Identifier myId = hit->cellID();
348 if (!m_calo_id->is_lar_dm(myId) && !m_calo_id->is_tile_dm(myId)) {
349 continue;
350 }
351
352 const CaloDmDescrElement* myCDDE = m_caloDmDescrManager->get_element(myId);
353 if (!myCDDE) {
354 continue;
355 }
356
357 int uniqueID = HepMC::UNDEFINED_ID;
358 if (useParticleID) {
359 uniqueID = HepMC::uniqueID(hit);
360 }
361
362 const int jeO = static_cast<int>(std::floor(m_n_eta_out * (myCDDE->eta() / m_out_eta_max)));
363 if (jeO < -m_n_eta_out || jeO >= m_n_eta_out) {
364 continue;
365 }
366
367 int jpO = static_cast<int>(std::floor(m_n_phi_out * (myCDDE->phi() / m_out_phi_max)));
368 if (jpO < -m_n_phi_out) {
369 jpO += 2 * m_n_phi_out;
370 }
371 if (jpO >= m_n_phi_out) {
372 jpO -= 2 * m_n_phi_out;
373 }
374
375 const int nDmArea = m_caloDmDescrManager->get_dm_area(myId);
376 const CaloDmRegion* dmRegion = m_caloDmDescrManager->get_dm_region(myId);
377 if (!dmRegion) {
378 continue;
379 }
380
381 std::vector<int> hitClusIndex;
382 std::vector<double> hitClusEffEnergy;
383 hitClusIndex.reserve(theClusColl.size());
384 hitClusEffEnergy.reserve(theClusColl.size());
385 double hitClusNorm = 0.0;
386
387 const std::vector<int>& matchingClusters =
388 clusList[(jpO + m_n_phi_out) * (2 * m_n_eta_out + 1) + jeO + m_n_eta_out];
389
390 for (int iClus : matchingClusters) {
391 const xAOD::CaloCluster* theCluster = theClusColl.at(iClus);
392 const MyClusInfo& clusInfo = clusInfoVec[iClus];
393 auto pos = clusInfo.engCalibParticle.find(uniqueID);
394 if (pos == clusInfo.engCalibParticle.end()) {
395 continue;
396 }
397
398 const double engClusTruthUniqueIDCalib = pos->second.engTot;
399 if (engClusTruthUniqueIDCalib <= m_energyMinCalib || theCluster->e() <= m_energyMin) {
400 continue;
401 }
402
403 double sum_smp_energy = 0.0;
404 for (unsigned int i_smp = 0; i_smp < dmRegion->m_CaloSampleNeighbours.size(); ++i_smp) {
405 const CaloSampling::CaloSample nsmp =
406 static_cast<CaloSampling::CaloSample>(dmRegion->m_CaloSampleNeighbours[i_smp]);
407 if ((dmRegion->m_CaloSampleEtaMin[i_smp] - 0.5) <= theCluster->eta() &&
408 theCluster->eta() <= (dmRegion->m_CaloSampleEtaMax[i_smp] + 0.5)) {
409 sum_smp_energy += pos->second.engSmp[nsmp];
410 }
411 }
412 if (sum_smp_energy <= 0.0) {
413 continue;
414 }
415
416 double phi_diff = myCDDE->phi() - theCluster->phi();
417 if (phi_diff <= -M_PI) {
418 phi_diff += 2. * M_PI;
419 }
420 else if (phi_diff > M_PI) {
421 phi_diff -= 2. * M_PI;
422 }
423 const double eta_diff = myCDDE->eta() - theCluster->eta();
424 const float distance = std::sqrt(eta_diff * eta_diff + phi_diff * phi_diff);
425 const double effEner = std::pow(sum_smp_energy, m_apars_alpha) * std::exp(-distance / m_apars_r0);
426
427 hitClusIndex.push_back(iClus);
428 hitClusEffEnergy.push_back(effEner);
429 hitClusNorm += effEner;
430 }
431
432 if (hitClusNorm <= 0.0) {
433 continue;
434 }
435
436 const double inv_hitClusNorm = 1.0 / hitClusNorm;
437 for (std::size_t i = 0; i < hitClusIndex.size(); ++i) {
438 const int iClus = hitClusIndex[i];
439 const double dm_weight = hitClusEffEnergy[i] * inv_hitClusNorm;
440 addDeadMaterialEnergy(iClus, uniqueID, nDmArea, hit->energyTotal() * dm_weight);
441 }
442 }
443 }
444 }
445
446 std::vector<std::string> m_momentsNames;
449 std::vector<std::string> m_momentsNamesAOD;
450 std::set<xAOD::CaloCluster::MomentType> m_momentsAOD;
453 SG::ReadHandleKey<xAOD::TruthParticleContainer> m_truthParticleContainerKey{this,"TruthParticles","TruthParticles","ReadHandleKey for truth particle container"};
454 SG::ReadCondHandleKey<CaloDetDescrManager> m_caloDetDescrMgrKey{this,"CaloDetDescrManager", "CaloDetDescrManager"};
462 double m_rmaxOut[3]{};
463 std::array<std::vector<std::vector<CalibHitIPhiIEtaRange> >, 3> m_i_phi_eta;
464 mutable std::atomic<bool> m_foundAllContainers{};
471 bool m_doDeadL{};
472 bool m_doDeadM{};
473 bool m_doDeadT{};
476 float m_energyMin{};
479 float m_apars_r0{};
481
482 static double angle_mollier_factor(double x);
483};
484
485#endif // CALOCALIBCLUSTERMOMENTSMAKER2_H
#define M_PI
Base class for cluster processing tools called from CaloClusterMaker.
Definition of CaloDetDescrManager.
#define x
AthAlgTool(const std::string &type, const std::string &name, const IInterface *parent)
Constructor with parameters:
std::array< double, CaloDmDescrArea::DMA_MAX > engCalibDeadInArea
std::set< moment_name_pair > moment_name_set
std::vector< moment_name_pair > moment_name_vector
void accumulateDeadMaterialEnergy(const std::vector< const CaloCalibrationHitContainer * > &v_dmcchc, const xAOD::CaloClusterContainer &theClusColl, const ClusInfo_t &clusInfoVec, const ClusList &clusList, bool useParticleID, AddDeadMaterialEnergy &&addDeadMaterialEnergy) const
Accumulate dead-material calibration-hit energy assigned to clusters.
SG::ReadHandleKeyArray< CaloCalibrationHitContainer > m_DMCalibrationHitContainerNames
std::set< xAOD::CaloCluster::MomentType > m_momentsAOD
virtual StatusCode execute(const EventContext &ctx, xAOD::CaloClusterContainer *theClusColl) const override
Execute on an entire collection of clusters.
static void initializeOutOfClusterDistanceTables(int n_phi_out, int n_eta_out, double out_phi_max, double out_eta_max, const double(&rmaxOut)[3], std::array< std::vector< std::vector< CalibHitIPhiIEtaRange > >, 3 > &i_phi_eta)
Precompute eta/phi lookup tables for quick out-of-cluster hit association to clusters.
SG::ReadHandleKeyArray< CaloCalibrationHitContainer > m_CalibrationHitContainerNames
std::map< Identifier, MyCellInfo > CellInfoSet_t
static void accumulateClusterCalibHits(const std::vector< const CaloCalibrationHitContainer * > &v_cchc, const CellInfoSet_t &cellInfo, const CaloCell_ID &calo_id, ClusInfo_t &clusInfoVec, unsigned int &nHitsTotal, unsigned int &nHitsWithoutParticleUID, bool useParticleID, InvalidUniqueIdHandler &&invalidUniqueIdHandler)
Accumulate calibration-hit energy inside clusters.
SG::ReadHandleKey< xAOD::TruthParticleContainer > m_truthParticleContainerKey
static void buildOutOfClusterClusterLists(const xAOD::CaloClusterContainer &theClusColl, const ClusInfo_t &clusInfoVec, int n_phi_out, int n_eta_out, double out_phi_max, double out_eta_max, const std::array< std::vector< std::vector< CalibHitIPhiIEtaRange > >, 3 > &i_phi_eta, const std::array< bool, 3 > &doOutOfCluster, const std::array< ClusList *, 3 > &clusLists)
Build lookup lists of clusters for out-of-cluster energy sharing.
static void buildCellInfoMap(const xAOD::CaloClusterContainer &theClusColl, CellInfoSet_t &cellInfo)
Build a map of calorimeter cells contributing to clusters.
SG::ReadCondHandleKey< CaloDetDescrManager > m_caloDetDescrMgrKey
CaloCalibClusterMomentsMaker2(const std::string &type, const std::string &name, const IInterface *parent)
std::array< std::vector< std::vector< CalibHitIPhiIEtaRange > >, 3 > m_i_phi_eta
const CaloDmDescrManager * m_caloDmDescrManager
std::vector< std::vector< int > > ClusList
static void accumulateOutOfClusterEnergy(const std::vector< const CaloCalibrationHitContainer * > &v_cchc, const CellInfoSet_t &cellInfo, const CaloDetDescrManager &calo_dd_man, const ClusInfo_t &clusInfoVec, int n_phi_out, int n_eta_out, double out_phi_max, double out_eta_max, const std::array< bool, 3 > &doOutOfCluster, const std::array< const ClusList *, 3 > &clusLists, AddOutOfClusterEnergy &&addOutOfClusterEnergy)
std::pair< std::string, xAOD::CaloCluster::MomentType > moment_name_pair
Class to store calorimeter calibration hit.
int calo_sample(const Identifier id) const
returns an int taken from Sampling enum and describing the subCalo to which the Id belongs.
Helper class for offline cell identifiers.
Definition CaloCell_ID.h:34
virtual StatusCode execute(const EventContext &ctx, xAOD::CaloClusterContainer *collection) const =0
Execute on an entire collection of clusters.
Helper class for Calo Dead Material offline identifiers.
Definition CaloDM_ID.h:102
This class groups all DetDescr information related to a CaloCell.
const CaloDetDescrElement * get_element(const Identifier &cellId) const
get element by its identifier
This class provides the client interface for accessing the detector description information common to...
std::vector< short > m_CaloSampleNeighbours
std::vector< float > m_CaloSampleEtaMin
std::vector< float > m_CaloSampleEtaMax
const T * at(size_type n) const
Access an element, as an rvalue.
size_type size() const noexcept
Returns the number of elements in the collection.
This defines the McEventCollection, which is really just an ObjectVector of McEvent objectsFile: Gene...
Property holding a SG store/key/clid from which a ReadHandle is made.
virtual double eta() const
The pseudorapidity ( ) of the particle.
virtual double phi() const
The azimuthal angle ( ) of the particle.
constexpr int INVALID_PARTICLE_ID
int uniqueID(const T &p)
constexpr int UNDEFINED_ID
HandleKeyArray< ReadHandle< T >, ReadHandleKey< T >, Gaudi::DataHandle::Reader > ReadHandleKeyArray
CaloCluster_v1 CaloCluster
Define the latest version of the calorimeter cluster class.
CaloClusterContainer_v1 CaloClusterContainer
Define the latest version of the calorimeter cluster container.