ATLAS Offline Software
Loading...
Searching...
No Matches
TFCSVoxelHistoLateralCovarianceFluctuations.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#include <string>
6
7#include "CLHEP/Random/RandFlat.h"
8#include "CLHEP/Random/RandGauss.h"
9
16
17#include "TVector2.h"
18#include "TMath.h"
19#include "TFile.h"
20#include "TMatrixDSym.h"
21#include "TMatrixDSymEigen.h"
22#include "TH2.h"
23
24//=============================================
25//======= TFCSVoxelHistoLateralCovarianceFluctuations =========
26//=============================================
27
30 "PreSamplerB"_FCShash, "EMB1"_FCShash, "EMB2"_FCShash,
31 "EMB3"_FCShash, "PreSamplerE"_FCShash, "EME1"_FCShash,
32 "EME2"_FCShash, "EME3"_FCShash, "HEC0"_FCShash,
33 "HEC1"_FCShash, "HEC2"_FCShash, "HEC3"_FCShash,
34 "TileBar0"_FCShash, "TileBar1"_FCShash, "TileBar2"_FCShash,
35 "TileGap1"_FCShash, "TileGap2"_FCShash, "TileGap3"_FCShash,
36 "TileExt0"_FCShash, "TileExt1"_FCShash, "TileExt2"_FCShash,
37 "FCAL0"_FCShash, "FCAL1"_FCShash, "FCAL2"_FCShash};
38
39const std::uint32_t TFCSVoxelHistoLateralCovarianceFluctuations::
40 s_layer_hash_geo[CaloCell_ID_FCS::MaxSample] = {
41 "PreSamplerB_geo"_FCShash, "EMB1_geo"_FCShash,
42 "EMB2_geo"_FCShash, "EMB3_geo"_FCShash,
43 "PreSamplerE_geo"_FCShash, "EME1_geo"_FCShash,
44 "EME2_geo"_FCShash, "EME3_geo"_FCShash,
45 "HEC0_geo"_FCShash, "HEC1_geo"_FCShash,
46 "HEC2_geo"_FCShash, "HEC3_geo"_FCShash,
47 "TileBar0_geo"_FCShash, "TileBar1_geo"_FCShash,
48 "TileBar2_geo"_FCShash, "TileGap1_geo"_FCShash,
49 "TileGap2_geo"_FCShash, "TileGap3_geo"_FCShash,
50 "TileExt0_geo"_FCShash, "TileExt1_geo"_FCShash,
51 "TileExt2_geo"_FCShash, "FCAL0_geo"_FCShash,
52 "FCAL1_geo"_FCShash, "FCAL2_geo"_FCShash};
53
58
61
63 TFile *inputfile, const std::string &folder) {
64 // load m_eigenvariances and m_parMeans from input file
65 // load histograms for each cell from input file
66 // m_transform[i][j]=new TFCS1DFunctionInt16Int16Histogram(hist)
67 // where hist is the 1D histogram from which a CDF was calculated
68
69 inputfile->cd(folder.c_str());
70 // inputfile->ls();
71
72 int cs = calosample();
73 int bin = 1;
74
75 TH2 *temp = dynamic_cast<TH2 *>(
76 inputfile->Get(Form("voxel_template_cs%d_pca%d", cs, bin)));
77 if (!temp) {
78 ATH_MSG_ERROR("Template hist not found for cs " + std::to_string(cs));
79 return false;
80 }
81 m_voxel_template.push_back(temp);
82 m_nDim_x = m_voxel_template[0]->GetNbinsX();
83 m_nDim_y = m_voxel_template[0]->GetNbinsY();
84
85 while (inputfile->Get(Form("parMeans_cs%d_pca%d", cs, bin))) {
86 TVectorD parMeans;
87 TMatrixD EigenVectors;
88 TVectorD EigenValues;
89 std::vector<std::vector<TFCS1DFunction *>> transform;
90
91 std::string label = Form("_cs%d_pca%d", cs, bin);
92
93 TObject *obj = inputfile->Get(("parMeans" + label).c_str());
94 if (!obj) {
95 ATH_MSG_ERROR("parMeans" + label + " not found");
96 return false;
97 }
98 if (msgLvl(MSG::DEBUG)) {
99 ATH_MSG_DEBUG("parMeans");
100 obj->Print();
101 }
102 parMeans.ResizeTo(m_nDim_x * m_nDim_y);
103 parMeans = *dynamic_cast<TVectorT<double> *>(obj);
104 m_parMeans.push_back(parMeans);
105
106 obj = inputfile->Get(("covMatrix" + label).c_str());
107 if (!obj) {
108 ATH_MSG_ERROR("covMatrix" + label + " not found");
109 return false;
110 }
111 TMatrixTSym<double> covMatrix = *dynamic_cast<TMatrixTSym<double> *>(obj);
112 TMatrixDSymEigen eigenvariances = TMatrixDSymEigen(covMatrix);
113 EigenVectors.ResizeTo(eigenvariances.GetEigenVectors());
114 EigenVectors = eigenvariances.GetEigenVectors();
115 m_EigenVectors.push_back(EigenVectors);
116
117 EigenValues.ResizeTo(eigenvariances.GetEigenValues());
118 EigenValues = eigenvariances.GetEigenValues();
119 m_EigenValues.push_back(EigenValues);
120
121 if (msgLvl(MSG::DEBUG)) {
122 ATH_MSG_DEBUG("eigenvariances");
123 eigenvariances.GetEigenValues().Print();
124 eigenvariances.GetEigenVectors().Print();
125 }
126 if (msgLvl(MSG::DEBUG)) {
127 ATH_MSG_DEBUG("m_EigenValues");
128 EigenValues.Print();
129 ATH_MSG_DEBUG("m_EigenVectors");
130 EigenVectors.Print();
131 }
132
133 transform.resize(m_nDim_x);
134 for (int x = 0; x < m_nDim_x; ++x) {
135 transform[x].resize(m_nDim_y);
136 for (int y = 0; y < m_nDim_y; ++y) {
137 // Naming of hists is hist_xy where x, y are indices of cells
138 std::string histname = Form("hist_%d_%d%s", x, y, label.c_str());
139 TH1 *hist = (TH1 *)inputfile->Get(histname.c_str());
140 if (!hist) {
141 ATH_MSG_ERROR("Histogram " << histname << " not found");
142 return false;
143 }
146 func->Initialize(hist, false);
147 transform[x][y] = func;
148 }
149 }
150 m_transform.push_back(std::move(transform));
151 ++bin;
152 }
153
154 return true;
155}
156
157// Implementation of multivariate Gaussian with ROOT classes (from ROOT forum,
158// but validated)
160 TFCSSimulationState &simulstate, TVectorD &genPars) const {
161 int Ebin = simulstate.Ebin();
162
163 int nPars = m_parMeans[Ebin - 1].GetNrows();
164 genPars.ResizeTo(nPars);
165
166 TVectorD rotParMeans = m_EigenVectors[Ebin - 1] * m_parMeans[Ebin - 1];
167 for (int iPar = 0; iPar < nPars; iPar++) {
168 double variance = m_EigenValues[Ebin - 1][iPar];
169 // check for positive-definiteness of covMatrix
170 if (variance < 0) {
171 ATH_MSG_ERROR("Got a negative eigenvariance (" << variance
172 << ") on iPar = " << iPar);
173 variance = 0;
174 }
175 genPars[iPar] = CLHEP::RandGauss::shoot(simulstate.randomEngine(),
176 rotParMeans[iPar], sqrt(variance));
177 ATH_MSG_DEBUG("genPars[" << iPar << "]=" << genPars[iPar]
178 << " rotParMeans[iPar]=" << rotParMeans[iPar]
179 << " sqrt(variance)=" << sqrt(variance));
180 }
181 genPars = m_EigenVectors[Ebin - 1] * genPars;
182}
183
185 TFCSSimulationState &simulstate, const TFCSTruthState * /*truth*/,
186 const TFCSExtrapolationState * /*extrapol*/) const {
187 if (!simulstate.randomEngine()) {
188 return FCSFatal;
189 }
190
191 if (msgLvl(MSG::DEBUG)) {
192 ATH_MSG_DEBUG("simulstate before clearing AuxInfo");
193 simulstate.Print();
194 }
195
196 weight_t *weightvec;
197 TH2 *voxel_temp;
198
199 int Ebin = simulstate.Ebin();
200
201 for (int ilayer = 0; ilayer < CaloCell_ID_FCS::MaxSample; ++ilayer) {
202 if (simulstate.hasAuxInfo(s_layer_hash[ilayer])) {
203 weightvec = static_cast<weight_t *>(
204 simulstate.getAuxInfo<void *>(s_layer_hash[ilayer]));
205 if (weightvec) {
206 delete weightvec;
207 simulstate.setAuxInfo<void *>(s_layer_hash[ilayer], nullptr);
208 }
209 }
210 if (simulstate.hasAuxInfo(s_layer_hash_geo[ilayer])) {
211 voxel_temp = static_cast<TH2 *>(
212 simulstate.getAuxInfo<void *>(s_layer_hash_geo[ilayer]));
213 if (voxel_temp) {
214 delete voxel_temp;
215 simulstate.setAuxInfo<void *>(s_layer_hash_geo[ilayer], nullptr);
216 }
217 }
218 }
219
220 if (msgLvl(MSG::DEBUG)) {
221 ATH_MSG_DEBUG("simulstate after clearing AuxInfo");
222 simulstate.Print();
223 }
224 // if(m_parMeans[Ebin-1].GetNrows()<1) {
225 if (m_parMeans.empty() || Ebin <= 0) {
226 // not initialized, do nothing in case this instance is just used to clean
227 // up memory
228 return FCSSuccess;
229 }
230
231 // TODO: the following code should be executed for all relevant calo layers,
232 // possibly simulating correlated fluctuations between layers depending on the
233 // PCA bin
234 weightvec = new weight_t(m_nDim_x);
235 for (int x = 0; x < m_nDim_x; ++x)
236 (*weightvec)[x].resize(m_nDim_y);
237
238 TVectorD genPars(m_parMeans[Ebin - 1].GetNrows());
239
240 // Fill genPars with multivarate random Gauss
241 MultiGaus(simulstate, genPars);
242
243 // Loop through voxels
244 int count = 0;
245 for (int x = 0; x < m_nDim_x; ++x) {
246 for (int y = 0; y < m_nDim_y; ++y) {
247 // Get value of CDF corresponding to generated Gauss random
248 double cdf_val =
249 (TMath::Erf(genPars[count] * 2.0 / TMath::Pi()) + 1) / 2.0;
250
251 // Map that cdf value to input bin and value
252 double orig_val = m_transform[Ebin - 1][x][y]->rnd_to_fct(cdf_val);
253
254 // Fill hist, keep linear count
255 (*weightvec)[x][y] = orig_val;
256 ++count;
257
258 ATH_MSG_DEBUG("CELL x=" << x << " y=" << y << " : cdf_val=" << cdf_val
259 << " orig_val=" << orig_val);
260 }
261 }
262
263 voxel_temp = static_cast<TH2 *>(m_voxel_template[0]->Clone());
264
265 // For now simulating only the layer calosample()
266 simulstate.setAuxInfo<void *>(s_layer_hash[calosample()], weightvec);
267 simulstate.setAuxInfo<void *>(s_layer_hash_geo[calosample()], voxel_temp);
268
269 if (msgLvl(MSG::DEBUG)) {
270 ATH_MSG_DEBUG("simulstate after storing weight " << weightvec
271 << " in AuxInfo");
272 simulstate.Print();
273 }
274
275 return FCSSuccess;
276}
277
279 Hit &hit, TFCSSimulationState &simulstate, const TFCSTruthState * /*truth*/,
280 const TFCSExtrapolationState * /*extrapol*/) {
281 const double center_eta = hit.center_eta();
282 const double center_phi = hit.center_phi();
283 const double center_r = hit.center_r();
284 const double center_z = hit.center_z();
285
286 int cs = calosample();
287 weight_t *weightvec = nullptr;
288 if (simulstate.hasAuxInfo(s_layer_hash[cs]))
289 weightvec = static_cast<weight_t *>(
290 simulstate.getAuxInfo<void *>(s_layer_hash[cs]));
291
292 if (!weightvec) {
293 ATH_MSG_ERROR("Weights not stored in simulstate for calosample=" << cs);
294 return FCSFatal;
295 }
296
297 TH2 *voxel_template = nullptr;
298 if (simulstate.hasAuxInfo(s_layer_hash_geo[cs]))
299 voxel_template =
300 static_cast<TH2 *>(simulstate.getAuxInfo<void *>(s_layer_hash_geo[cs]));
301 if (!voxel_template) {
303 "Voxel geometry not stored in simulstate for calosample=" << cs);
304 return FCSFatal;
305 }
306
307 /* int nbinsx = 8;
308 float lowx = 0;
309 float highx = 2 * TMath::Pi();
310 int nbinsy = 9.;
311 float lowy = 0.;
312 float highy = 165.;
313 float coreSize = 5.;
314
315 std::vector<float> bins_x = {};
316 for(int bin = 0; bin <= nbinsx; ++bin){
317 bins_x.push_back(lowx+((highx-lowx)/nbinsx)*bin);
318 }
319
320 std::vector<float> bins_y = {lowy};
321 for(int bin = 0; bin <= nbinsy; ++bin){
322 float step = (highy-lowy)/nbinsy;
323 if(coreSize > 0){
324 if(bin ==0){lowy =lowy+coreSize;}
325 bins_y.push_back(lowy+bin*step);
326 }
327 else{
328 if(bin > 0){
329 bins_y.push_back(lowy+bin*step);
330 }
331 }
332 }
333
334 TH2F* voxel_template = new TH2F("", "", bins_x.size()-1, &bins_x[0],
335 bins_y.size()-1, &bins_y[0]); */
336
337 float deta_hit_minus_extrapol = hit.eta() - center_eta;
338 float dphi_hit_minus_extrapol = TVector2::Phi_mpi_pi(hit.phi() - center_phi);
339
340 // if(charge<0.)dphi_hit_minus_extrapol=-dphi_hit_minus_extrapol;
341 if (center_eta < 0.)
342 deta_hit_minus_extrapol = -deta_hit_minus_extrapol;
343
344 float phi_dist2r = 1.0;
345 float dist000 = TMath::Sqrt(center_r * center_r + center_z * center_z);
346 float eta_jakobi = TMath::Abs(2.0 * TMath::Exp(-hit.eta()) /
347 (1.0 + TMath::Exp(-2 * hit.eta())));
348
349 float deta_hit_minus_extrapol_mm =
350 deta_hit_minus_extrapol * eta_jakobi * dist000;
351 float dphi_hit_minus_extrapol_mm =
352 dphi_hit_minus_extrapol * center_r * phi_dist2r;
353
354 float alpha_mm =
355 TMath::ATan2(dphi_hit_minus_extrapol_mm, deta_hit_minus_extrapol_mm);
356 float radius_mm =
357 TMath::Sqrt(dphi_hit_minus_extrapol_mm * dphi_hit_minus_extrapol_mm +
358 deta_hit_minus_extrapol_mm * deta_hit_minus_extrapol_mm);
359
360 int ix;
361 int iy = voxel_template->GetYaxis()->FindBin(radius_mm) - 1;
362
363 // Treat core as one bin for simulation
364 if (iy == 0) {
365 ix = 0;
366 } else {
367 if (alpha_mm < 0)
368 ix = voxel_template->GetXaxis()->FindBin(2 * TMath::Pi() -
369 fabs(alpha_mm)) -
370 1;
371 else
372 ix = voxel_template->GetXaxis()->FindBin(alpha_mm) - 1;
373 }
374
375 const int sizex = (*weightvec).size();
376
377 float weight = 1;
378 if (ix >= 0 && ix < sizex) {
379 const int sizey = (*weightvec)[ix].size();
380 if (iy >= 0 && iy < sizey) {
381 weight = (*weightvec)[ix][iy];
382 }
383 }
384
385 hit.E() *= weight;
386
387 ATH_MSG_DEBUG("HIT: E=" << hit.E() << ", alpha = " << alpha_mm
388 << ", r = " << center_r << ", ix = " << ix
389 << ", iy = " << iy << ", weight = " << weight);
390
391 // delete voxel_template;
392 return FCSSuccess;
393}
#define ATH_MSG_ERROR(x)
#define ATH_MSG_DEBUG(x)
FCSReturnCode
Base class for all FastCaloSim parametrizations Functionality in derivde classes is provided through ...
#define y
#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
void Initialize(const TH1 *hist, bool doprint=true)
Initialize from root histogram.
TFCSLateralShapeParametrizationHitBase(const char *name=nullptr, const char *title=nullptr)
void Print(Option_t *option="") const
bool hasAuxInfo(std::uint32_t index) const
const T getAuxInfo(std::uint32_t index) const
void setAuxInfo(std::uint32_t index, const T &val)
CLHEP::HepRandomEngine * randomEngine()
virtual FCSReturnCode simulate(TFCSSimulationState &simulstate, const TFCSTruthState *truth, const TFCSExtrapolationState *extrapol) const override
create one fluctuated shape for a shower to be applied as scale factor to the average shape Store the...
std::vector< std::vector< std::vector< TFCS1DFunction * > > > m_transform
static const std::uint32_t s_layer_hash[CaloCell_ID_FCS::MaxSample]
do not persistify
void MultiGaus(TFCSSimulationState &simulstate, TVectorD &genPars) const
virtual FCSReturnCode simulate_hit(Hit &hit, TFCSSimulationState &simulstate, const TFCSTruthState *truth, const TFCSExtrapolationState *extrapol) override
weight the energy of one hit by the fluctuation calculated in simulate(...)
bool initialize(TFile *inputfile, const std::string &folder)
TFCSVoxelHistoLateralCovarianceFluctuations(const char *name=nullptr, const char *title=nullptr)
std::vector< std::vector< float > > weight_t
do not persistify
static const std::uint32_t s_layer_hash_geo[CaloCell_ID_FCS::MaxSample]
do not persistify
int count(std::string s, const std::string &regx)
count how many occurances of a regx are in a string
Definition hcg.cxx:146
std::string label(const std::string &format, int i)
Definition label.h:19