ATLAS Offline Software
CaloClusterDetails.h
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 #ifndef XAODCALOEVENT_CALOCLUSTERDETAILS_H
6 #define XAODCALOEVENT_CALOCLUSTERDETAILS_H
7 
9 #include <CaloGeoHelpers/CaloSampling.h>
10 #include <bit>
11 #include <cstdint>
12 #include <span>
13 
14 namespace xAOD
15 {
16  namespace CaloClusterDetails
17  {
38 
39 
41 
42 
48  constexpr float defaultErrorValue = -999;
49 
50 
52  [[nodiscard]] inline bool hasSampling(const CaloSample s, const std::uint32_t samplingPattern) {
53  return (samplingPattern & (0x1U<<(std::uint32_t)s));
54  }
55 
56 
57  [[nodiscard]] inline unsigned sampVarIdx(const CaloSample s, const std::uint32_t samplingPattern) {
58  //std::cout << "Pattern=" << std::hex << pattern << std::dec << ", Sampling=" << s << std::endl;
59  if ((samplingPattern & (0x1U << s)) == 0) {
60  return CaloSampling::Unknown;
61  }
62  if (s == 0) {
63  return 0;
64  } // shifting a 32-bit int by 32 bits is undefined behavior!
65  return std::popcount(samplingPattern << (32 - s));
66  // Explanation: Need to get the number of bit (=samples) before the sampling in question
67  // Shift to the left, so bits after the sampling in question fall off the 32bit integer
68  // Then use popcount to count the numbers of 1 in the rest
69  }
70 
71 
72  [[nodiscard]] inline float getSamplVar(const CaloSample sampling, const std::uint32_t samplingPattern, const std::span<const float> vec, const float errorvalue=defaultErrorValue) {
73  const unsigned idx=sampVarIdx(sampling, samplingPattern);
74  if (idx<vec.size() ) {
75  return vec[idx];
76  }
77 
78  //std::cout <<Sampling " << sampling << ", Pattern=" << std::hex <<m_samplingPattern << std::dec << ", index=" << idx << " size=" << vec.size() << std::endl;
79  return errorvalue;
80  }
81 
82 
87  [[nodiscard]] inline float energyBE(const unsigned sample, const std::uint32_t samplingPattern, const std::span<const float> e_sampl) {
88  if (sample>3) return defaultErrorValue;
91  double energy=0;
92  if (hasSampling(barrelSample, samplingPattern)) {
93  energy+=getSamplVar(barrelSample,samplingPattern,e_sampl); //Check for errorcode? Should not happen...
94  }
95  if (hasSampling(endcapSample, samplingPattern)) {
96  energy+=getSamplVar(endcapSample,samplingPattern,e_sampl);
97  }
98  return energy;
99  }
100 
101 
102 
107  [[nodiscard]] inline float etaBE(const unsigned sample, const std::uint32_t samplingPattern, const std::span<const float> e_sampl, const std::span<const float> eta_sampl) {
108  if (sample>3) {return defaultErrorValue;}
111  const bool haveBarrel=hasSampling(barrelSample, samplingPattern);
112  const bool haveEndcap=hasSampling(endcapSample, samplingPattern);
113  if (haveBarrel && haveEndcap) {
114  //cluster spans barren and endcap
115  float eBarrel=getSamplVar(barrelSample,samplingPattern,e_sampl); //Check for errorcode? Should not happen...
116  float eEndcap=getSamplVar(endcapSample,samplingPattern,e_sampl);
117 
118  float etaBarrel=getSamplVar(barrelSample,samplingPattern,eta_sampl);
119  float etaEndcap=getSamplVar(endcapSample,samplingPattern,eta_sampl);
120  float eSum=eBarrel + eEndcap;
121  if (eSum > 100 /*MeV*/) {
122  //E-weighted average ...
123  if ((eBarrel > 0 && eEndcap > 0) || (eBarrel < 0 && eEndcap < 0))
124  return (eBarrel * etaBarrel + eEndcap * etaEndcap) / eSum;
125  else if (eBarrel > 0)
126  return etaBarrel;
127  else
128  return etaEndcap;
129  }//else eSum==0 case, should never happen
130  return (0.5 * (etaBarrel + etaEndcap));
131  }
132  if (haveBarrel) {
133  return getSamplVar(barrelSample,samplingPattern,eta_sampl);
134  }
135  if (haveEndcap) {
136  return getSamplVar(endcapSample,samplingPattern,eta_sampl);
137  }
138 
139  //Should never reach this point ...
140  return defaultErrorValue;
141  }
142 
143 
144 
145  [[nodiscard]] inline float phiBE(const unsigned sample, const std::uint32_t samplingPattern, const std::span<const float> e_sampl, const std::span<const float> phi_sampl) {
146  if (sample>3) {return defaultErrorValue;}
149  const bool haveBarrel=hasSampling(barrelSample, samplingPattern);
150  const bool haveEndcap=hasSampling(endcapSample, samplingPattern);
151  if (haveBarrel && haveEndcap) {
152  //cluster spans barren and endcap
153  float eBarrel=getSamplVar(barrelSample, samplingPattern, e_sampl); //Check for errorcode? Should not happen...
154  float eEndcap=getSamplVar(endcapSample, samplingPattern, e_sampl);
155  float eSum=eBarrel+eEndcap;
156  float phiBarrel=getSamplVar(barrelSample, samplingPattern, phi_sampl);
157  float phiEndcap=getSamplVar(endcapSample, samplingPattern, phi_sampl);
158  if (eSum != 0.0) {
159  if ((eBarrel > 0 && eEndcap > 0) || (eBarrel < 0 && eEndcap < 0)) {
160  float phiSum = eSum * phiBarrel + eEndcap * CaloPhiRange::diff(phiEndcap, phiBarrel);
161  return CaloPhiRange::fix(phiSum / eSum);
162  } else if (eBarrel > 0)
163  return phiBarrel;
164  else
165  return phiEndcap;
166  }
167  // energy==0 case, should never happen
168  return CaloPhiRange::fix(0.5 * (phiBarrel + phiEndcap));
169  }
170  if (haveBarrel) {
171  return getSamplVar(barrelSample, samplingPattern, phi_sampl);
172  }
173  if (haveEndcap) {
174  return getSamplVar(endcapSample, samplingPattern, phi_sampl);
175  }
176 
177  //Should never reach this point ...
178  return defaultErrorValue;
179  }
180  }
181 }
182 
183 #endif
xAOD::CaloClusterDetails::hasSampling
bool hasSampling(const CaloSample s, const std::uint32_t samplingPattern)
Checks if certain smapling contributes to cluster.
Definition: CaloClusterDetails.h:52
GetLCDefs::Unknown
@ Unknown
Definition: GetLCDefs.h:21
xAOD::CaloClusterDetails::etaBE
float etaBE(const unsigned sample, const std::uint32_t samplingPattern, const std::span< const float > e_sampl, const std::span< const float > eta_sampl)
Get the eta in one layer of the EM Calo.
Definition: CaloClusterDetails.h:107
xAOD::uint32_t
setEventNumber uint32_t
Definition: EventInfo_v1.cxx:127
xAOD::CaloClusterDetails::CaloSample
CaloSampling::CaloSample CaloSample
Definition: CaloClusterDetails.h:40
xAOD
ICaloAffectedTool is abstract interface for tools checking if 4 mom is in calo affected region.
Definition: ICaloAffectedTool.h:24
vec
std::vector< size_t > vec
Definition: CombinationsGeneratorTest.cxx:9
xAOD::CaloClusterDetails::energyBE
float energyBE(const unsigned sample, const std::uint32_t samplingPattern, const std::span< const float > e_sampl)
Get the energy in one layer of the EM Calo.
Definition: CaloClusterDetails.h:87
xAOD::CaloClusterDetails::sampVarIdx
unsigned sampVarIdx(const CaloSample s, const std::uint32_t samplingPattern)
Definition: CaloClusterDetails.h:57
ParticleGun_FastCalo_ChargeFlip_Config.energy
energy
Definition: ParticleGun_FastCalo_ChargeFlip_Config.py:78
FullCPAlgorithmsTest_eljob.sample
sample
Definition: FullCPAlgorithmsTest_eljob.py:116
CaloSampling::CaloSample
CaloSample
Definition: Calorimeter/CaloGeoHelpers/CaloGeoHelpers/CaloSampling.h:22
CaloPhiRange.h
CaloPhiRange class declaration.
xAOD::CaloClusterDetails::getSamplVar
float getSamplVar(const CaloSample sampling, const std::uint32_t samplingPattern, const std::span< const float > vec, const float errorvalue=defaultErrorValue)
Definition: CaloClusterDetails.h:72
CaloPhiRange::fix
static double fix(double phi)
Definition: CaloPhiRange.cxx:14
xAOD::CaloClusterDetails::phiBE
float phiBE(const unsigned sample, const std::uint32_t samplingPattern, const std::span< const float > e_sampl, const std::span< const float > phi_sampl)
Definition: CaloClusterDetails.h:145
CaloCell_ID_FCS::PreSamplerE
@ PreSamplerE
Definition: FastCaloSim_CaloCell_ID.h:23
CaloCell_ID_FCS::PreSamplerB
@ PreSamplerB
Definition: FastCaloSim_CaloCell_ID.h:19
LArNewCalib_DelayDump_OFC_Cali.idx
idx
Definition: LArNewCalib_DelayDump_OFC_Cali.py:69
python.SystemOfUnits.s
float s
Definition: SystemOfUnits.py:147
xAOD::CaloClusterDetails::defaultErrorValue
constexpr float defaultErrorValue
the default error code to return in case of error
Definition: CaloClusterDetails.h:48
CaloPhiRange::diff
static double diff(double phi1, double phi2)
simple phi1 - phi2 calculation, but result is fixed to respect range.
Definition: CaloPhiRange.cxx:22