ATLAS Offline Software
Loading...
Searching...
No Matches
TFCSPhiModulationCorrection.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// Local includes
7
12
13// External includes
14#include <TFile.h>
15#include <TH2F.h>
16#include <TParameter.h>
17
18
19
20//=============================================
21//======= TFCSPhiModulationCorrection =========
22//=============================================
23
25 const char *title)
27
29
31 const std::string & filename, long unsigned int layer_index, float eta_min,
32 float eta_max, float energy_shift) {
33 if (m_min_eta.size() <= layer_index) {
34 m_min_eta.resize(layer_index + 1);
35 }
36 if (m_min_phi.size() <= layer_index) {
37 m_min_phi.resize(layer_index + 1);
38 }
39 if (m_modulation.size() <= layer_index) {
40 m_modulation.resize(layer_index + 1);
41 }
42 if (m_energy_shift.size() <= layer_index) {
43 m_energy_shift.resize(layer_index + 1);
44 }
45 std::vector<float> &eta_mins = m_min_eta.at(layer_index);
46 std::vector<std::vector<float>> &phi_mins = m_min_phi.at(layer_index);
47 std::vector<std::vector<float>> &modulation = m_modulation.at(layer_index);
48 std::vector<float> &energy_shifts = m_energy_shift.at(layer_index);
49
50 if (eta_mins.empty()) {
51 eta_mins.push_back(eta_min);
52 eta_mins.push_back(eta_max);
53 phi_mins.resize(2);
54 modulation.resize(2);
55 energy_shifts.push_back(-1.0);
56 energy_shifts.push_back(-1.0);
57 }
58
59 if (eta_mins.at(0) > eta_min) {
60 eta_mins.insert(eta_mins.begin(), eta_min);
61 phi_mins.insert(phi_mins.begin(), std::vector<float>());
62 modulation.insert(modulation.begin(), std::vector<float>());
63 energy_shifts.insert(energy_shifts.begin(), -1.0);
64 }
65
66 // Find the matching eta index
67 auto eta_it = std::upper_bound(m_min_eta.at(layer_index).begin(),
68 m_min_eta.at(layer_index).end(), eta_min);
69 long unsigned int eta_index =
70 std::distance(m_min_eta.at(layer_index).begin(), eta_it) - 1;
71
72 // Check if we have to append further boundaries
73 if (eta_index >= eta_mins.size() - 1) {
74 if (eta_min > eta_mins.at(eta_mins.size() - 1)) {
75 eta_mins.push_back(eta_min);
76 phi_mins.push_back(std::vector<float>());
77 modulation.push_back(std::vector<float>());
78 energy_shifts.push_back(-1.0);
79 eta_index++;
80 }
81 eta_mins.push_back(eta_max);
82 phi_mins.push_back(std::vector<float>());
83 modulation.push_back(std::vector<float>());
84 energy_shifts.push_back(-1.0);
85 } else {
86 // Check if we need to insert a new eta_min
87 if (eta_mins.at(eta_index) < eta_min) {
88 eta_mins.insert(eta_mins.begin() + eta_index + 1, eta_min);
89 phi_mins.insert(phi_mins.begin() + eta_index + 1, std::vector<float>());
90 modulation.insert(modulation.begin() + eta_index + 1,
91 std::vector<float>());
92 energy_shifts.insert(energy_shifts.begin() + eta_index + 1, -1.0);
93 eta_index++;
94 }
95 // Check if we need to insert a new eta_max
96 if (eta_mins.at(eta_index + 1) > eta_max) {
97 eta_mins.insert(eta_mins.begin() + eta_index + 1, eta_max);
98 phi_mins.insert(phi_mins.begin() + eta_index + 1, std::vector<float>());
99 modulation.insert(modulation.begin() + eta_index + 1,
100 std::vector<float>());
101 energy_shifts.insert(energy_shifts.begin() + eta_index + 1, -1.0);
102 }
103 }
104
105 energy_shifts.at(eta_index) = energy_shift;
106
107 ATH_MSG_DEBUG("Loading phi modulation correction from " << filename);
108
109 std::unique_ptr<TFile> muon_corr ( TFile::Open(filename.c_str()));
110 TH2F *muon_corr_hist = (TH2F *)muon_corr->Get("hWt_Layer0");
111
112 int n_bins = muon_corr_hist->GetNbinsX();
113
114 for (int i = 1; i <= n_bins; i++) {
115 phi_mins.at(eta_index).push_back(
116 muon_corr_hist->GetXaxis()->GetBinLowEdge(i));
117 }
118 phi_mins.at(eta_index).push_back(
119 muon_corr_hist->GetXaxis()->GetBinUpEdge(n_bins));
120
121 for (int i = 1; i <= n_bins; i++) {
122 modulation.at(eta_index).push_back(muon_corr_hist->GetBinContent(i));
123 }
124
125 TParameter<double> *param =
126 (TParameter<double> *)muon_corr->Get("energy_shift");
127 if (param) {
128 energy_shifts.at(eta_index) = param->GetVal();
129 std::cout << "Energy shift: " << energy_shifts.at(eta_index) << std::endl;
130 }
131
132 muon_corr->Close();
133
134 return;
135}
136
137// TODO: Use FCSReturnCode
138std::tuple<int, long unsigned int, long unsigned int>
140 float phi, float eta, long unsigned int layer_index) const {
141
142 float eta_abs = TMath::Abs(eta);
143
144 auto eta_it = std::upper_bound(m_min_eta.at(layer_index).begin(),
145 m_min_eta.at(layer_index).end(), eta_abs);
146 long unsigned int eta_index =
147 std::distance(m_min_eta.at(layer_index).begin(), eta_it) - 1;
148
149 if (eta_index >= m_min_eta.at(layer_index).size() - 1) {
150 ATH_MSG_ERROR("Found invalid eta index for phi modulation");
151 ATH_MSG_ERROR("Layer: " << layer_index);
152 ATH_MSG_ERROR("Eta: " << eta);
153 ATH_MSG_ERROR("Min eta:" << m_min_eta.at(layer_index).at(0) << " Max eta: "
154 << m_min_eta.at(layer_index).back());
155 ATH_MSG_ERROR("Eta index: " << eta_index);
156 ATH_MSG_ERROR("Number of eta bins: " << m_min_eta.at(layer_index).size());
157 ATH_MSG_ERROR("Eta bin boundaries: ");
158 for (const auto &eta_min : m_min_eta.at(layer_index)) {
159 ATH_MSG_ERROR(" " << eta_min);
160 }
161 return std::make_tuple(1, 0, 0); // Error code 1: Invalid eta index
162 }
163
164 if (m_min_eta.at(layer_index).at(eta_index) > eta_abs ||
165 m_min_eta.at(layer_index).at(eta_index + 1) < eta_abs) {
167 "Found eta outside of the specified eta range for the phi modulation");
168 ATH_MSG_ERROR("Layer: " << layer_index);
169 ATH_MSG_ERROR("Eta: " << eta);
170 ATH_MSG_ERROR("Phi: " << phi);
171 ATH_MSG_ERROR("Eta min of bin: "
172 << m_min_eta.at(layer_index).at(eta_index)
173 << " Eta max of bin: "
174 << m_min_eta.at(layer_index).at(eta_index + 1));
175 return std::make_tuple(2, 0, 0); // Error code 2: Eta outside of range
176 }
177
178 const CaloDetDescrElement *cellele = m_geo->getDDE(layer_index, eta, phi);
179
180 float cell_phi = cellele->phi();
181
182 float phi_within_cell = phi - cell_phi;
183
184 float phi_cell_size = get_phi_cell_size(layer_index, eta);
185
186 phi_within_cell = fmod(phi_within_cell, phi_cell_size);
187
188 if (phi_within_cell < 0)
189 phi_within_cell += phi_cell_size;
190
191 const std::vector<float> &phi_mins = m_min_phi.at(layer_index).at(eta_index);
192 const std::vector<float> &modulation =
193 m_modulation.at(layer_index).at(eta_index);
194
195 if (phi_mins.size() == 0) {
196 return std::make_tuple(-1, 0, 0); // Empty phi boundaries -> nothing to do
197 }
198
199 // Find the phi bin of the hit
200 auto phi_it =
201 std::upper_bound(phi_mins.begin(), phi_mins.end(), phi_within_cell);
202 long unsigned int phi_index = std::distance(phi_mins.begin(), phi_it) - 1;
203
204 if (phi_index >= modulation.size()) {
205 ATH_MSG_ERROR("Found bin "
206 << phi_index
207 << " outside of the modulation correction vector");
208 ATH_MSG_ERROR("Phi: " << phi << " Cell phi: " << cell_phi
209 << " Phi within cell: " << phi_within_cell);
210 ATH_MSG_ERROR("Eta: " << eta);
211 ATH_MSG_ERROR("Phi cell size: " << phi_cell_size);
212 ATH_MSG_ERROR("Modulation correction size: " << modulation.size());
213 ATH_MSG_ERROR("Phi bin boundaries size: " << phi_mins.size());
214 ATH_MSG_ERROR("Last Phi bin boundary: " << phi_mins.back());
215
216 return std::make_tuple(
217 3, 0, 0); // Error code 3: Phi index outside of modulation vector
218 }
219
220 return std::make_tuple(0, eta_index, phi_index); // No error
221}
222
227
230 long unsigned int layer_index) const {
231 if (layer_index >= m_min_eta.size()) {
232 return hit.E();
233 }
234
235 if (m_min_eta.at(layer_index).size() == 0) {
236 return hit.E();
237 }
238
239 if (m_modulation_scale < std::numeric_limits<float>::epsilon()) {
240 return hit.E();
241 }
242
243 float energy = hit.E();
244 float phi = hit.phi();
245 float eta = hit.eta();
246
247 float reweighted_energy = add_phi_modulation(energy, phi, eta, layer_index);
248 hit.E() = reweighted_energy;
249
250 return reweighted_energy;
251}
252
254 float energy, float phi, float eta, long unsigned int layer_index) const {
255
256 if (layer_index >= m_min_eta.size()) {
257 return energy;
258 }
259
260 if (m_min_eta.at(layer_index).size() == 0) {
261 return energy;
262 }
263
264 if (m_modulation_scale < std::numeric_limits<float>::epsilon()) {
265 return energy;
266 }
267
268 long unsigned int eta_index;
269 long unsigned int phi_index;
270 int error_code;
271 std::tie(error_code, eta_index, phi_index) =
272 get_eta_and_phi_index(phi, eta, layer_index);
273
274 if (error_code != 0) {
275 return energy; // Return original energy in case of error --- no modulation
276 // applied
277 }
278
279 const std::vector<float> &modulation =
280 m_modulation.at(layer_index).at(eta_index);
281
282 energy *= ((modulation.at(phi_index) - 1) * m_modulation_scale + 1);
283 energy *= m_energy_shift.at(layer_index).at(eta_index);
284
285 return energy;
286}
287
292
295 long unsigned int layer_index) const {
296 if (layer_index >= m_min_eta.size()) {
297 return hit.E();
298 }
299
300 if (m_min_eta.at(layer_index).size() == 0) {
301 return hit.E();
302 }
303
304 if (m_modulation_scale < std::numeric_limits<float>::epsilon()) {
305 return hit.E();
306 }
307
308 float energy = hit.E();
309 float phi = hit.phi();
310 float eta = hit.eta();
311
312 float reweighted_energy =
313 remove_phi_modulation(energy, phi, eta, layer_index);
314 hit.E() = reweighted_energy;
315
316 return reweighted_energy;
317}
318
320 float energy, float phi, float eta, long unsigned int layer_index) const {
321
322 if (layer_index >= m_min_eta.size()) {
323 return energy;
324 }
325
326 if (m_min_eta.at(layer_index).size() == 0) {
327 return energy;
328 }
329
330 if (m_modulation_scale < std::numeric_limits<float>::epsilon()) {
331 return energy;
332 }
333
334 long unsigned int eta_index;
335 long unsigned int phi_index;
336 int error_code;
337 std::tie(error_code, eta_index, phi_index) =
338 get_eta_and_phi_index(phi, eta, layer_index);
339
340 if (error_code != 0) {
341 return energy; // Return original energy in case of error --- no modulation
342 // removed
343 }
344
345 const std::vector<float> &modulation =
346 m_modulation.at(layer_index).at(eta_index);
347
348 energy /= ((modulation.at(phi_index) - 1) * m_modulation_scale + 1);
349
350 return energy;
351}
352
354 Hit &hit, TFCSSimulationState &simulstate, const TFCSTruthState *truth,
355 const TFCSExtrapolationState *extrapol) {
356
357 // Extrapol unused, but needed for the interface
358 (void)extrapol;
359
360 // Simulstate unused, but needed for the interface
361 (void)simulstate;
362
363 // truth unused, but needed for the interface
364 (void)truth;
365
367
368 return FCSSuccess;
369}
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(const 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