ATLAS Offline Software
Loading...
Searching...
No Matches
TFCSPCAEnergyParametrization.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
3*/
4
5#include "CLHEP/Random/RandGaussZiggurat.h"
6#include "CLHEP/Random/RandFlat.h"
7
10
13
14#include "TFile.h"
15#include "TKey.h"
16#include "TClass.h"
17#include "TMatrixD.h"
18#include "TMatrixDSymEigen.h"
19#include "TMath.h"
20#include "TH1.h"
21#include "CxxUtils/restrict.h"
22
23//=============================================
24//======= TFCSPCAEnergyParametrization =========
25//=============================================
26
28 const char *title)
29 : TFCSEnergyParametrization(name, title) {
31 do_rescale = 1;
32}
33
35 if (Ekin_bin >= 1 && Ekin_bin <= n_bins())
36 return true;
37 return false;
38}
39
41 for (unsigned int i = 0; i < m_RelevantLayers.size(); i++) {
42 if (m_RelevantLayers[i] == calosample)
43 return true;
44 }
45 return false;
46}
47
48void TFCSPCAEnergyParametrization::Print(Option_t *option) const {
49 TString opt(option);
50 bool shortprint = opt.Index("short") >= 0;
51 bool longprint = msgLvl(MSG::DEBUG) || (msgLvl(MSG::INFO) && !shortprint);
52 TString optprint = opt;
53 optprint.ReplaceAll("short", "");
55
56 if (longprint) {
57 ATH_MSG(INFO) << optprint << " #bins=" << m_numberpcabins
58 << ", Enorm=" << m_total_energy_normalization << ", layers=";
59 for (unsigned int i = 0; i < m_RelevantLayers.size(); i++) {
60 if (i > 0)
61 ATH_MSG(INFO) << ", ";
62 ATH_MSG(INFO) << m_RelevantLayers[i];
63 }
64 ATH_MSG(INFO) << END_MSG(INFO);
65 }
66}
67
68float interpolate_get_y(TH1 *hist, float x) {
69 float m = 0;
70 float n = 0;
71 float x1 = 1;
72 float x2 = 0;
73 float y1 = 0;
74 float y2 = 0;
75 if (x <= hist->GetBinCenter(1))
76 return hist->GetBinContent(1);
77 if (x >= hist->GetBinCenter(hist->GetNbinsX()))
78 return hist->GetBinContent(hist->GetNbinsX());
79
80 int bin = hist->FindBin(x);
81 // is x above the bin center -> interpolate with next bin
82 if (x > hist->GetBinCenter(bin)) {
83 x1 = hist->GetBinCenter(bin);
84 y1 = hist->GetBinContent(bin);
85 x2 = hist->GetBinCenter(bin + 1);
86 y2 = hist->GetBinContent(bin + 1);
87 }
88
89 // is x below bin center -> interpolate with previous bin
90 if (x <= hist->GetBinCenter(bin)) {
91 x1 = hist->GetBinCenter(bin - 1);
92 y1 = hist->GetBinContent(bin - 1);
93 x2 = hist->GetBinCenter(bin);
94 y2 = hist->GetBinContent(bin);
95 }
96
97 m = (y1 - y2) / (x1 - x2);
98 n = y2 - m * x2;
99 return m * x + n;
100}
101
103 TH1 *hist) {
104 if (Ekin_bin < 1)
105 return;
106 if (Ekin_bin - 1 >= (int)m_totalE_probability_ratio.size())
107 return;
108 m_totalE_probability_ratio[Ekin_bin - 1] = hist;
109}
110
112 int Ekin_bin) const {
113 if (Ekin_bin < 1)
114 return nullptr;
115 if (Ekin_bin - 1 >= (int)m_totalE_probability_ratio.size())
116 return nullptr;
117 return m_totalE_probability_ratio[Ekin_bin - 1];
118}
119
121 TFCSSimulationState &simulstate, const TFCSTruthState * /*truth*/,
122 const TFCSExtrapolationState * /*extrapol*/) const {
123
124 if (!simulstate.randomEngine()) {
125 return FCSFatal;
126 }
127
128 int pcabin = simulstate.Ebin();
129
130 if (pcabin == 0) {
131 simulstate.set_E(0);
132 for (int s = 0; s < CaloCell_ID_FCS::MaxSample; s++) {
133 simulstate.set_E(s, 0.0);
134 simulstate.set_Efrac(s, 0.0);
135 }
136 } else {
137
138 TMatrixD *EV = m_EV[pcabin - 1];
139 TVectorD *MeanValues = m_MeanValues[pcabin - 1];
140 TVectorD *SigmaValues = m_SigmaValues[pcabin - 1];
141 TVectorD *Gauss_means = m_Gauss_means[pcabin - 1];
142 TVectorD *Gauss_rms = m_Gauss_rms[pcabin - 1];
143 std::vector<TFCS1DFunction *> cumulative = m_cumulative[pcabin - 1];
144
145 const std::vector<int> &layerNr = m_RelevantLayers;
146
147 double *vals_gauss_means = (double *)Gauss_means->GetMatrixArray();
148 double *vals_gauss_rms = Gauss_rms->GetMatrixArray();
149
150 double *output_data = new double[layerNr.size() + 1];
151 double *input_data = new double[layerNr.size() + 1];
152
153 for (unsigned int l = 0; l <= layerNr.size(); l++) {
154 double mean = vals_gauss_means[l];
155 double rms = vals_gauss_rms[l];
156 double gauszz =
157 CLHEP::RandGaussZiggurat::shoot(simulstate.randomEngine(), mean, rms);
158 input_data[l] = gauszz;
159 }
160
161 P2X(SigmaValues, MeanValues, EV, layerNr.size() + 1, input_data,
162 output_data, layerNr.size() + 1);
163
164 double *simdata = new double[layerNr.size() + 1];
165 double sum_fraction = 0.0;
166 for (unsigned int l = 0; l <= layerNr.size(); l++) {
167 double simdata_uniform =
168 (TMath::Erf(output_data[l] / 1.414213562) + 1) / 2.f;
169
170 simdata[l] = cumulative[l]->rnd_to_fct(simdata_uniform);
171
172 if (l != layerNr.size()) // sum up the fractions, but not the totalE
173 sum_fraction += simdata[l];
174 }
175
176 double scalefactor = 1.0 / sum_fraction;
177 if (!do_rescale)
178 scalefactor = 1.0;
179
180 // Using signed int for better loop optimization and vectorization where
181 // possible
182 int layerNrsize = static_cast<int>(layerNr.size());
183 for (int l = 0; l < layerNrsize; l++) {
184 simdata[l] *= scalefactor;
185 }
186
187 // Apply hit-and-miss reweighting of total energy response
188 // This needs to run before simulstate is modified, otherwise a clean retry
189 // is not possible
190 TH1 *h_totalE_ratio = get_totalE_probability_ratio(pcabin);
191 if (h_totalE_ratio) {
192 float pass_probability = 0;
193 float Etot = simdata[layerNr.size()];
194 if (Etot > h_totalE_ratio->GetXaxis()->GetXmin() &&
195 Etot < h_totalE_ratio->GetXaxis()->GetXmax()) {
196 pass_probability = interpolate_get_y(h_totalE_ratio, Etot);
197 }
198 float random = CLHEP::RandFlat::shoot(simulstate.randomEngine());
199 if (random > pass_probability) {
200 delete[] output_data;
201 delete[] input_data;
202 delete[] simdata;
203
205 }
206 }
207
208 double total_energy =
209 simdata[layerNr.size()] * simulstate.E() / m_total_energy_normalization;
210 simulstate.set_E(total_energy);
211 ATH_MSG_DEBUG("set E to total_energy=" << total_energy);
212
213 for (int s = 0; s < CaloCell_ID_FCS::MaxSample; s++) {
214 double energyfrac = 0.0;
215 for (unsigned int l = 0; l < layerNr.size(); l++) {
216 if (layerNr[l] == s)
217 energyfrac = simdata[l];
218 }
219 simulstate.set_Efrac(s, energyfrac);
220 simulstate.set_E(s, energyfrac * total_energy);
221 simulstate.set_SF(scalefactor);
222 }
223
224 delete[] output_data;
225 delete[] input_data;
226 delete[] simdata;
227 }
228
229 return FCSSuccess;
230}
231
232void TFCSPCAEnergyParametrization::P2X(TVectorD *SigmaValues,
233 TVectorD *MeanValues, TMatrixD *EV,
234 int gNVariables, const double *p,
235 double *ATH_RESTRICT x, int nTest) {
236
237 const double *gSigmaValues = SigmaValues->GetMatrixArray();
238 const double *gMeanValues = MeanValues->GetMatrixArray();
239 const double *gEigenVectors = EV->GetMatrixArray();
240
241 for (int i = 0; i < gNVariables; i++) {
242 x[i] = gMeanValues[i];
243 for (int j = 0; j < nTest; j++) {
244 x[i] +=
245 p[j] * gSigmaValues[i] * (double)(gEigenVectors[i * gNVariables + j]);
246 }
247 }
248}
249
253
255 const std::string &folder) {
256
257 bool load_ok = 1;
258
259 int trynext = 1;
260 TString x;
261 if (folder.empty())
262 x = "bin";
263 else
264 x = folder + "/bin";
265 while (trynext) {
266 IntArray *test = (IntArray *)file->Get(
267 x + Form("%i/pca/RelevantLayers", m_numberpcabins));
268 if (test) {
270 delete test;
271 } else
272 trynext = 0;
273 }
274 m_numberpcabins -= 1;
275
276 file->cd(x + "1/pca");
277 IntArray *RelevantLayers = (IntArray *)gDirectory->Get("RelevantLayers");
278 if (RelevantLayers == nullptr) {
279 ATH_MSG_ERROR("TFCSPCAEnergyParametrization::m_RelevantLayers in first "
280 "pcabin is null!");
281 load_ok = false;
282 }
283
284 if (!load_ok)
285 return false;
286
287 m_RelevantLayers.reserve(RelevantLayers->GetSize());
288 for (int i = 0; i < RelevantLayers->GetSize(); i++)
289 m_RelevantLayers.push_back(RelevantLayers->GetAt(i));
290
291 for (int bin = 1; bin <= m_numberpcabins; bin++) {
292
293 file->cd(x + Form("%i/pca", bin));
294
295 TMatrixDSym *symCov = (TMatrixDSym *)gDirectory->Get("symCov");
296 TVectorD *MeanValues = (TVectorD *)gDirectory->Get("MeanValues");
297 TVectorD *SigmaValues = (TVectorD *)gDirectory->Get("SigmaValues");
298 TVectorD *Gauss_means = (TVectorD *)gDirectory->Get("Gauss_means");
299 TVectorD *Gauss_rms = (TVectorD *)gDirectory->Get("Gauss_rms");
300
301 if (symCov == nullptr) {
302 ATH_MSG_WARNING("TFCSPCAEnergyParametrization::symCov in pcabin "
303 << bin << " is null!");
304 load_ok = false;
305 }
306 if (MeanValues == nullptr) {
307 ATH_MSG_WARNING("TFCSPCAEnergyParametrization::MeanValues in pcabin "
308 << bin << " is null!");
309 load_ok = false;
310 }
311 if (SigmaValues == nullptr) {
312 ATH_MSG_WARNING("TFCSPCAEnergyParametrization::SigmaValues in pcabin "
313 << bin << " is null!");
314 load_ok = false;
315 }
316 if (Gauss_means == nullptr) {
317 ATH_MSG_WARNING("TFCSPCAEnergyParametrization::Gauss_means in pcabin "
318 << bin << " is null!");
319 load_ok = false;
320 }
321 if (Gauss_rms == nullptr) {
322 ATH_MSG_WARNING("TFCSPCAEnergyParametrization::Gause_rms in pcabin "
323 << bin << " is null!");
324 load_ok = false;
325 }
326
327 if (!load_ok)
328 return false;
329
330 TMatrixDSymEigen cov_eigen(*symCov);
331 TMatrixD *EV = new TMatrixD(cov_eigen.GetEigenVectors());
332 m_EV.push_back(EV);
333 m_MeanValues.push_back(MeanValues);
334 m_SigmaValues.push_back(SigmaValues);
335 m_Gauss_means.push_back(Gauss_means);
336 m_Gauss_rms.push_back(Gauss_rms);
337
338 std::vector<std::string> layer;
339 const std::vector<int> &layerNr = m_RelevantLayers;
340
341 for (unsigned int i = 0; i < layerNr.size(); i++) {
342 layer.emplace_back(Form("layer%i", layerNr[i]));
343 }
344 layer.emplace_back("totalE");
345
346 std::vector<TFCS1DFunction *> cumulative;
347 cumulative.reserve(layer.size());
348
349 for (unsigned int l = 0; l < layer.size(); l++) {
350 file->cd(Form("%s/bin%i/%s", folder.c_str(), bin, layer[l].c_str()));
351
352 TFCS1DFunction *fct;
353 fct = (TFCS1DFunction *)gDirectory->Get("TFCS1DFunctionRegression");
354 if (!fct)
355 fct = (TFCS1DFunction *)gDirectory->Get("TFCS1DFunctionRegressionTF");
356 if (!fct)
357 fct = (TFCS1DFunction *)gDirectory->Get("TFCS1DFunctionHistogram");
358 cumulative.push_back(fct);
359 }
360
361 m_cumulative.emplace_back(std::move(cumulative));
362 }
363 m_totalE_probability_ratio.resize(m_numberpcabins - 1, nullptr);
364
365 return true;
366}
367
369 for (unsigned int i = 0; i < m_EV.size(); i++)
370 delete m_EV[i];
371}
372
373void TFCSPCAEnergyParametrization::Streamer(TBuffer &R__b) {
374 // Stream an object of class TFCSPCAEnergyParametrization
375
376 if (R__b.IsReading()) {
377 UInt_t R__s, R__c;
378 Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
379 R__b.SetBufferOffset(R__s);
380
381 R__b.ReadClassBuffer(TFCSPCAEnergyParametrization::Class(), this);
382
383 if (R__v == 1) {
385 // Check if min and max range is a factor 2 within 1 MeV tolerance
386 // If yes, the nominal to log-avergage
387 if (TMath::Abs(Ekin_max() - 2 * Ekin_min()) < 1) {
388 set_Ekin_nominal(Ekin_max() / TMath::Sqrt(2));
389 }
390 }
391 if (R__v <= 2) {
392 m_totalE_probability_ratio.resize(m_numberpcabins - 1, nullptr);
393 }
394 } else {
395 R__b.WriteClassBuffer(TFCSPCAEnergyParametrization::Class(), this);
396 }
397}
#define ATH_MSG_ERROR(x)
#define ATH_MSG(lvl)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
#define END_MSG(lvl)
Definition MLogging.h:171
float interpolate_get_y(TH1 *hist, float x)
FCSReturnCode
Base class for all FastCaloSim parametrizations Functionality in derivde classes is provided through ...
#define x
bool msgLvl(const MSG::Level lvl) const
Check whether the logging system is active at the provided verbosity level.
Definition MLogging.h:222
TFCSEnergyParametrization(const char *name=nullptr, const char *title=nullptr)
virtual bool is_match_calosample(int calosample) const override
static void P2X(TVectorD *, TVectorD *, TMatrixD *, int, const double *, double *, int)
virtual int n_bins() const override
TH1 * get_totalE_probability_ratio(int Ekin_bin) const
void set_totalE_probability_ratio(int Ekin_bin, TH1 *hist)
void Print(Option_t *option="") const override
virtual FCSReturnCode simulate(TFCSSimulationState &simulstate, const TFCSTruthState *truth, const TFCSExtrapolationState *extrapol) const override
Method in all derived classes to do some simulation.
virtual bool is_match_Ekin_bin(int Ekin_bin) const override
std::vector< std::vector< TFCS1DFunction * > > m_cumulative
TFCSPCAEnergyParametrization(const char *name=nullptr, const char *title=nullptr)
void Print(Option_t *option="") const
Print object information.
double Ekin_nominal() const override
double Ekin_min() const override
double Ekin_max() const override
virtual void set_Ekin_nominal(double min)
void set_SF(double mysf)
void set_E(int sample, double Esample)
void set_Efrac(int sample, double Efracsample)
CLHEP::HepRandomEngine * randomEngine()
void mean(std::vector< double > &bins, std::vector< double > &values, const std::vector< std::string > &files, const std::string &histname, const std::string &tplotname, const std::string &label="")
Macro wrapping the nonstandard restrict keyword.
#define ATH_RESTRICT
Definition restrict.h:31
TFile * file