ATLAS Offline Software
Loading...
Searching...
No Matches
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
143std::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
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
244 if (m_modulation_scale < std::numeric_limits<float>::epsilon()) {
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
269 if (m_modulation_scale < std::numeric_limits<float>::epsilon()) {
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
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
309 if (m_modulation_scale < std::numeric_limits<float>::epsilon()) {
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
335 if (m_modulation_scale < std::numeric_limits<float>::epsilon()) {
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,
360 const TFCSExtrapolationState *extrapol) {
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
372
373 return FCSSuccess;
374}
Scalar eta() const
pseudorapidity method
Scalar phi() const
phi method
#define ATH_MSG_ERROR(x)
#define ATH_MSG_DEBUG(x)
FCSReturnCode
Base class for all FastCaloSim parametrizations Functionality in derivde classes is provided through ...
This class groups all DetDescr information related to a CaloCell.
TFCSLateralShapeParametrizationHitBase(const char *name=nullptr, const char *title=nullptr)
double eta_max() const override
double eta_min() const override
void load_phi_modulation(std::string filename, long unsigned int layer_index, float eta_min, float eta_max, float energy_shift=1.0)
std::vector< std::vector< std::vector< float > > > m_modulation
virtual FCSReturnCode simulate_hit(Hit &hit, TFCSSimulationState &simulstate, const TFCSTruthState *truth, const TFCSExtrapolationState *extrapol) override
simulated one hit position with some energy.
TFCSPhiModulationCorrection(const char *name=nullptr, const char *title=nullptr)
static float get_phi_cell_size(long unsigned int layer, float eta)
std::vector< std::vector< float > > m_energy_shift
std::tuple< int, long unsigned int, long unsigned int > get_eta_and_phi_index(float phi, float eta, long unsigned int layer_index) const
std::vector< std::vector< std::vector< float > > > m_min_phi
std::vector< std::vector< float > > m_min_eta