ATLAS Offline Software
TFCSPhiModulationCorrection.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 // Local includes
7 
12 
13 // External includes
14 #include <RtypesCore.h>
15 #include <TFile.h>
16 #include <TH2F.h>
17 #include <TMath.h>
18 #include <TParameter.h>
19 
20 // Standard includes
21 #include <fstream>
22 #include <tuple>
23 #include <vector>
24 
25 //=============================================
26 //======= TFCSPhiModulationCorrection =========
27 //=============================================
28 
30  const char *title)
32 
34 
36  std::string filename, long unsigned int layer_index, float eta_min,
37  float eta_max, float energy_shift) {
38  if (m_min_eta.size() <= layer_index) {
39  m_min_eta.resize(layer_index + 1);
40  }
41  if (m_min_phi.size() <= layer_index) {
42  m_min_phi.resize(layer_index + 1);
43  }
44  if (m_modulation.size() <= layer_index) {
45  m_modulation.resize(layer_index + 1);
46  }
47  if (m_energy_shift.size() <= layer_index) {
48  m_energy_shift.resize(layer_index + 1);
49  }
50  std::vector<float> &eta_mins = m_min_eta.at(layer_index);
51  std::vector<std::vector<float>> &phi_mins = m_min_phi.at(layer_index);
52  std::vector<std::vector<float>> &modulation = m_modulation.at(layer_index);
53  std::vector<float> &energy_shifts = m_energy_shift.at(layer_index);
54 
55  if (eta_mins.empty()) {
56  eta_mins.push_back(eta_min);
57  eta_mins.push_back(eta_max);
58  phi_mins.resize(2);
59  modulation.resize(2);
60  energy_shifts.push_back(-1.0);
61  energy_shifts.push_back(-1.0);
62  }
63 
64  if (eta_mins.at(0) > eta_min) {
65  eta_mins.insert(eta_mins.begin(), eta_min);
66  phi_mins.insert(phi_mins.begin(), std::vector<float>());
67  modulation.insert(modulation.begin(), std::vector<float>());
68  energy_shifts.insert(energy_shifts.begin(), -1.0);
69  }
70 
71  // Find the matching eta index
72  auto eta_it = std::upper_bound(m_min_eta.at(layer_index).begin(),
73  m_min_eta.at(layer_index).end(), eta_min);
74  long unsigned int eta_index =
75  std::distance(m_min_eta.at(layer_index).begin(), eta_it) - 1;
76 
77  // Check if we have to append further boundaries
78  if (eta_index >= eta_mins.size() - 1) {
79  if (eta_min > eta_mins.at(eta_mins.size() - 1)) {
80  eta_mins.push_back(eta_min);
81  phi_mins.push_back(std::vector<float>());
82  modulation.push_back(std::vector<float>());
83  energy_shifts.push_back(-1.0);
84  eta_index++;
85  }
86  eta_mins.push_back(eta_max);
87  phi_mins.push_back(std::vector<float>());
88  modulation.push_back(std::vector<float>());
89  energy_shifts.push_back(-1.0);
90  } else {
91  // Check if we need to insert a new eta_min
92  if (eta_mins.at(eta_index) < eta_min) {
93  eta_mins.insert(eta_mins.begin() + eta_index + 1, eta_min);
94  phi_mins.insert(phi_mins.begin() + eta_index + 1, std::vector<float>());
95  modulation.insert(modulation.begin() + eta_index + 1,
96  std::vector<float>());
97  energy_shifts.insert(energy_shifts.begin() + eta_index + 1, -1.0);
98  eta_index++;
99  }
100  // Check if we need to insert a new eta_max
101  if (eta_mins.at(eta_index + 1) > eta_max) {
102  eta_mins.insert(eta_mins.begin() + eta_index + 1, eta_max);
103  phi_mins.insert(phi_mins.begin() + eta_index + 1, std::vector<float>());
104  modulation.insert(modulation.begin() + eta_index + 1,
105  std::vector<float>());
106  energy_shifts.insert(energy_shifts.begin() + eta_index + 1, -1.0);
107  }
108  }
109 
110  energy_shifts.at(eta_index) = energy_shift;
111 
112  ATH_MSG_DEBUG("Loading phi modulation correction from " << filename);
113 
114  TFile *muon_corr = TFile::Open(filename.c_str());
115  TH2F *muon_corr_hist = (TH2F *)muon_corr->Get("hWt_Layer0");
116 
117  int n_bins = muon_corr_hist->GetNbinsX();
118 
119  for (int i = 1; i <= n_bins; i++) {
120  phi_mins.at(eta_index).push_back(
121  muon_corr_hist->GetXaxis()->GetBinLowEdge(i));
122  }
123  phi_mins.at(eta_index).push_back(
124  muon_corr_hist->GetXaxis()->GetBinUpEdge(n_bins));
125 
126  for (int i = 1; i <= n_bins; i++) {
127  modulation.at(eta_index).push_back(muon_corr_hist->GetBinContent(i));
128  }
129 
130  TParameter<double> *param =
131  (TParameter<double> *)muon_corr->Get("energy_shift");
132  if (param) {
133  energy_shifts.at(eta_index) = param->GetVal();
134  std::cout << "Energy shift: " << energy_shifts.at(eta_index) << std::endl;
135  }
136 
137  muon_corr->Close();
138 
139  return;
140 }
141 
142 // TODO: Use FCSReturnCode
143 std::tuple<int, long unsigned int, long unsigned int>
145  float phi, float eta, long unsigned int layer_index) const {
146 
147  float eta_abs = TMath::Abs(eta);
148 
149  auto eta_it = std::upper_bound(m_min_eta.at(layer_index).begin(),
150  m_min_eta.at(layer_index).end(), eta_abs);
151  long unsigned int eta_index =
152  std::distance(m_min_eta.at(layer_index).begin(), eta_it) - 1;
153 
154  if (eta_index >= m_min_eta.at(layer_index).size() - 1) {
155  ATH_MSG_ERROR("Found invalid eta index for phi modulation");
156  ATH_MSG_ERROR("Layer: " << layer_index);
157  ATH_MSG_ERROR("Eta: " << eta);
158  ATH_MSG_ERROR("Min eta:" << m_min_eta.at(layer_index).at(0) << " Max eta: "
159  << m_min_eta.at(layer_index).back());
160  ATH_MSG_ERROR("Eta index: " << eta_index);
161  ATH_MSG_ERROR("Number of eta bins: " << m_min_eta.at(layer_index).size());
162  ATH_MSG_ERROR("Eta bin boundaries: ");
163  for (const auto &eta_min : m_min_eta.at(layer_index)) {
164  ATH_MSG_ERROR(" " << eta_min);
165  }
166  return std::make_tuple(1, 0, 0); // Error code 1: Invalid eta index
167  }
168 
169  if (m_min_eta.at(layer_index).at(eta_index) > eta_abs ||
170  m_min_eta.at(layer_index).at(eta_index + 1) < eta_abs) {
172  "Found eta outside of the specified eta range for the phi modulation");
173  ATH_MSG_ERROR("Layer: " << layer_index);
174  ATH_MSG_ERROR("Eta: " << eta);
175  ATH_MSG_ERROR("Phi: " << phi);
176  ATH_MSG_ERROR("Eta min of bin: "
177  << m_min_eta.at(layer_index).at(eta_index)
178  << " Eta max of bin: "
179  << m_min_eta.at(layer_index).at(eta_index + 1));
180  return std::make_tuple(2, 0, 0); // Error code 2: Eta outside of range
181  }
182 
183  const CaloDetDescrElement *cellele = m_geo->getDDE(layer_index, eta, phi);
184 
185  float cell_phi = cellele->phi();
186 
187  float phi_within_cell = phi - cell_phi;
188 
189  float phi_cell_size = get_phi_cell_size(layer_index, eta);
190 
191  phi_within_cell = fmod(phi_within_cell, phi_cell_size);
192 
193  if (phi_within_cell < 0)
194  phi_within_cell += phi_cell_size;
195 
196  const std::vector<float> &phi_mins = m_min_phi.at(layer_index).at(eta_index);
197  const std::vector<float> &modulation =
198  m_modulation.at(layer_index).at(eta_index);
199 
200  if (phi_mins.size() == 0) {
201  return std::make_tuple(-1, 0, 0); // Empty phi boundaries -> nothing to do
202  }
203 
204  // Find the phi bin of the hit
205  auto phi_it =
206  std::upper_bound(phi_mins.begin(), phi_mins.end(), phi_within_cell);
207  long unsigned int phi_index = std::distance(phi_mins.begin(), phi_it) - 1;
208 
209  if (phi_index >= modulation.size()) {
210  ATH_MSG_ERROR("Found bin "
211  << phi_index
212  << " outside of the modulation correction vector");
213  ATH_MSG_ERROR("Phi: " << phi << " Cell phi: " << cell_phi
214  << " Phi within cell: " << phi_within_cell);
215  ATH_MSG_ERROR("Eta: " << eta);
216  ATH_MSG_ERROR("Phi cell size: " << phi_cell_size);
217  ATH_MSG_ERROR("Modulation correction size: " << modulation.size());
218  ATH_MSG_ERROR("Phi bin boundaries size: " << phi_mins.size());
219  ATH_MSG_ERROR("Last Phi bin boundary: " << phi_mins.back());
220 
221  return std::make_tuple(
222  3, 0, 0); // Error code 3: Phi index outside of modulation vector
223  }
224 
225  return std::make_tuple(0, eta_index, phi_index); // No error
226 }
227 
230  return add_phi_modulation(hit, calosample());
231 }
232 
235  long unsigned int layer_index) const {
236  if (layer_index >= m_min_eta.size()) {
237  return hit.E();
238  }
239 
240  if (m_min_eta.at(layer_index).size() == 0) {
241  return hit.E();
242  }
243 
245  return hit.E();
246  }
247 
248  float energy = hit.E();
249  float phi = hit.phi();
250  float eta = hit.eta();
251 
252  float reweighted_energy = add_phi_modulation(energy, phi, eta, layer_index);
253  hit.E() = reweighted_energy;
254 
255  return reweighted_energy;
256 }
257 
259  float energy, float phi, float eta, long unsigned int layer_index) const {
260 
261  if (layer_index >= m_min_eta.size()) {
262  return energy;
263  }
264 
265  if (m_min_eta.at(layer_index).size() == 0) {
266  return energy;
267  }
268 
270  return energy;
271  }
272 
273  long unsigned int eta_index;
274  long unsigned int phi_index;
275  int error_code;
276  std::tie(error_code, eta_index, phi_index) =
277  get_eta_and_phi_index(phi, eta, layer_index);
278 
279  if (error_code != 0) {
280  return energy; // Return original energy in case of error --- no modulation
281  // applied
282  }
283 
284  const std::vector<float> &modulation =
285  m_modulation.at(layer_index).at(eta_index);
286 
287  energy *= ((modulation.at(phi_index) - 1) * m_modulation_scale + 1);
288  energy *= m_energy_shift.at(layer_index).at(eta_index);
289 
290  return energy;
291 }
292 
295  return remove_phi_modulation(hit, calosample());
296 }
297 
300  long unsigned int layer_index) const {
301  if (layer_index >= m_min_eta.size()) {
302  return hit.E();
303  }
304 
305  if (m_min_eta.at(layer_index).size() == 0) {
306  return hit.E();
307  }
308 
310  return hit.E();
311  }
312 
313  float energy = hit.E();
314  float phi = hit.phi();
315  float eta = hit.eta();
316 
317  float reweighted_energy =
318  remove_phi_modulation(energy, phi, eta, layer_index);
319  hit.E() = reweighted_energy;
320 
321  return reweighted_energy;
322 }
323 
325  float energy, float phi, float eta, long unsigned int layer_index) const {
326 
327  if (layer_index >= m_min_eta.size()) {
328  return energy;
329  }
330 
331  if (m_min_eta.at(layer_index).size() == 0) {
332  return energy;
333  }
334 
336  return energy;
337  }
338 
339  long unsigned int eta_index;
340  long unsigned int phi_index;
341  int error_code;
342  std::tie(error_code, eta_index, phi_index) =
343  get_eta_and_phi_index(phi, eta, layer_index);
344 
345  if (error_code != 0) {
346  return energy; // Return original energy in case of error --- no modulation
347  // removed
348  }
349 
350  const std::vector<float> &modulation =
351  m_modulation.at(layer_index).at(eta_index);
352 
353  energy /= ((modulation.at(phi_index) - 1) * m_modulation_scale + 1);
354 
355  return energy;
356 }
357 
359  Hit &hit, TFCSSimulationState &simulstate, const TFCSTruthState *truth,
361 
362  // Extrapol unused, but needed for the interface
363  (void)extrapol;
364 
365  // Simulstate unused, but needed for the interface
366  (void)simulstate;
367 
368  // truth unused, but needed for the interface
369  (void)truth;
370 
371  add_phi_modulation(hit);
372 
373  return FCSSuccess;
374 }
FCSReturnCode
FCSReturnCode
Base class for all FastCaloSim parametrizations Functionality in derivde classes is provided through ...
Definition: TFCSParametrizationBase.h:41
TFCSLateralShapeParametrizationHitBase::Hit::phi
float & phi()
Definition: TFCSLateralShapeParametrizationHitBase.h:87
phi
Scalar phi() const
phi method
Definition: AmgMatrixBasePlugin.h:67
eta
Scalar eta() const
pseudorapidity method
Definition: AmgMatrixBasePlugin.h:83
CaloDetDescrElement
This class groups all DetDescr information related to a CaloCell. Provides a generic interface for al...
Definition: Calorimeter/CaloDetDescr/CaloDetDescr/CaloDetDescrElement.h:66
CaloClusterMLCalib::epsilon
constexpr float epsilon
Definition: CaloClusterMLGaussianMixture.h:16
TFCSPhiModulationCorrection::get_eta_and_phi_index
std::tuple< int, long unsigned int, long unsigned int > get_eta_and_phi_index(float phi, float eta, long unsigned int layer_index) const
Definition: TFCSPhiModulationCorrection.cxx:144
TFCSExtrapolationState
Definition: TFCSExtrapolationState.h:13
TFCSLateralShapeParametrizationHitBase::Hit
Definition: TFCSLateralShapeParametrizationHitBase.h:42
RunActsMaterialValidation.extrapol
extrapol
Definition: RunActsMaterialValidation.py:91
python.TrigEgammaMonitorHelper.TH2F
def TH2F(name, title, nxbins, bins_par2, bins_par3, bins_par4, bins_par5=None, bins_par6=None, path='', **kwargs)
Definition: TrigEgammaMonitorHelper.py:45
TFCSLateralShapeParametrizationHitBase
Definition: TFCSLateralShapeParametrizationHitBase.h:13
TFCSPhiModulationCorrection::m_modulation
std::vector< std::vector< std::vector< float > > > m_modulation
Definition: TFCSPhiModulationCorrection.h:110
TFCSLateralShapeParametrizationHitBase::Hit::E
float & E()
Definition: TFCSLateralShapeParametrizationHitBase.h:90
TFCSPhiModulationCorrection::TFCSPhiModulationCorrection
TFCSPhiModulationCorrection(const char *name=nullptr, const char *title=nullptr)
Definition: TFCSPhiModulationCorrection.cxx:29
TFCSPhiModulationCorrection::m_energy_shift
std::vector< std::vector< float > > m_energy_shift
Definition: TFCSPhiModulationCorrection.h:113
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
TFCSPhiModulationCorrection::remove_phi_modulation
float remove_phi_modulation(Hit &hit) const
Definition: TFCSPhiModulationCorrection.cxx:293
TFCSPhiModulationCorrection::add_phi_modulation
float add_phi_modulation(Hit &hit) const
Definition: TFCSPhiModulationCorrection.cxx:228
ParticleGun_FastCalo_ChargeFlip_Config.energy
energy
Definition: ParticleGun_FastCalo_ChargeFlip_Config.py:78
TFCSPhiModulationCorrection::m_min_eta
std::vector< std::vector< float > > m_min_eta
Definition: TFCSPhiModulationCorrection.h:112
lumiFormat.i
int i
Definition: lumiFormat.py:85
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
covarianceTool.title
title
Definition: covarianceTool.py:542
TFCSPhiModulationCorrection::simulate_hit
virtual FCSReturnCode simulate_hit(Hit &hit, TFCSSimulationState &simulstate, const TFCSTruthState *truth, const TFCSExtrapolationState *extrapol) override
simulated one hit position with some energy.
Definition: TFCSPhiModulationCorrection.cxx:358
createCablingJSON.eta_index
int eta_index
Definition: createCablingJSON.py:14
FCSSuccess
@ FCSSuccess
Definition: TFCSParametrizationBase.h:41
TFCSParametrization::eta_max
double eta_max() const override
Definition: TFCSParametrization.h:40
TFCSPhiModulationCorrection::get_phi_cell_size
static float get_phi_cell_size(long unsigned int layer, float eta)
Definition: TFCSPhiModulationCorrection.h:57
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:240
TFCSParametrization::eta_min
double eta_min() const override
Definition: TFCSParametrization.h:39
TFCSPhiModulationCorrection::load_phi_modulation
void load_phi_modulation(std::string filename, long unsigned int layer_index, float eta_min, float eta_max, float energy_shift=1.0)
Definition: TFCSPhiModulationCorrection.cxx:35
TFCSPhiModulationCorrection.h
TFCSPhiModulationCorrection::m_min_phi
std::vector< std::vector< std::vector< float > > > m_min_phi
Definition: TFCSPhiModulationCorrection.h:111
TFCSTruthState.h
TFCSLateralShapeParametrization::calosample
int calosample() const
Definition: TFCSLateralShapeParametrization.h:34
TFCSExtrapolationState.h
CaloCellTimeCorrFiller.filename
filename
Definition: CaloCellTimeCorrFiller.py:23
LArHVGainsPredictor.error_code
error_code
Definition: LArHVGainsPredictor.py:228
TFCSLateralShapeParametrizationHitBase::Hit::eta
float & eta()
Definition: TFCSLateralShapeParametrizationHitBase.h:86
CaloDetDescrElement::phi
float phi() const
cell phi
Definition: Calorimeter/CaloDetDescr/CaloDetDescr/CaloDetDescrElement.h:346
TFCSSimulationState.h
TFCSPhiModulationCorrection::m_modulation_scale
float m_modulation_scale
do not persistify
Definition: TFCSPhiModulationCorrection.h:109
ICaloGeometry::getDDE
virtual const CaloDetDescrElement * getDDE(Identifier identify) const =0
TFCSPhiModulationCorrection::~TFCSPhiModulationCorrection
virtual ~TFCSPhiModulationCorrection()
Definition: TFCSPhiModulationCorrection.cxx:33
ICaloGeometry.h
Amg::distance
float distance(const Amg::Vector3D &p1, const Amg::Vector3D &p2)
calculates the distance between two point in 3D space
Definition: GeoPrimitivesHelpers.h:54
TFCSTruthState
Definition: TFCSTruthState.h:13
TFCSSimulationState
Definition: TFCSSimulationState.h:32
xAOD::TrackingDetails::phi_index
@ phi_index
Definition: TrackingDetails.h:40
TFCSPhiModulationCorrection::m_geo
ICaloGeometry * m_geo
Definition: TFCSPhiModulationCorrection.h:105