ATLAS Offline Software
TFCSBinnedShower.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3 */
4 
6 
7 #include <cmath>
8 #include <cstdlib>
9 
10 #include "HepPDT/ParticleData.hh"
19 
20 #if defined(__FastCaloSimStandAlone__)
21 #include "CLHEP/Random/TRandomEngine.h"
22 #else
23 #include <CLHEP/Random/RanluxEngine.h>
24 #endif
25 
26 #include <H5Cpp.h>
27 #include <TFile.h>
28 #include <TH2.h>
29 #include <TKey.h>
30 #include <TMatrixD.h>
31 
32 #include <algorithm>
33 #include <iostream>
34 #include <map>
35 #include <regex>
36 #include <string>
37 #include <vector>
38 
39 #include "CLHEP/Random/RandFlat.h"
41 #include "TBuffer.h"
42 #include "TClass.h"
43 
44 //=============================================
45 //======= TFCSBinnedShower =========
46 //=============================================
47 
48 // using namespace TFCSBinnedShowerEventTypes;
49 
52 
54 
56  long unsigned int event_index, long unsigned int layer_index,
57  const std::vector<unsigned int>& bin_index_vector,
58  const std::vector<float>& E_vector) {
59 
60  // Assert that the event index is valid
61  if (event_index >= m_eventlibrary.size()) {
62  m_eventlibrary.resize(event_index + 1);
63  }
64 
65  // Assert that the layer index is valid
66  if (layer_index >= m_eventlibrary.at(event_index).event_data.size()) {
67  m_eventlibrary.at(event_index).event_data.resize(layer_index + 1);
68  }
69 
70  // Set the layer energy
71  layer_t &layer = m_eventlibrary.at(event_index).event_data.at(layer_index);
72  layer.bin_index_vector = bin_index_vector;
73  layer.E_vector = E_vector;
74 }
75 
76 void TFCSBinnedShower::set_bin_boundaries(long unsigned int layer_index,
77  std::vector<float>& R_lower,
78  std::vector<float>& R_size,
79  std::vector<float>& alpha_lower,
80  std::vector<float>& alpha_size) {
81  if (layer_index >= m_coordinates.size()) {
82  m_coordinates.resize(layer_index + 1);
83  }
84  m_coordinates.at(layer_index).R_lower = R_lower;
85  m_coordinates.at(layer_index).R_size = R_size;
86  m_coordinates.at(layer_index).alpha_lower = alpha_lower;
87  m_coordinates.at(layer_index).alpha_size = alpha_size;
88 }
89 
91  long unsigned int event_index, long unsigned int reference_layer_index,
92  float eta_center, float phi_center) {
93 
94  // Compute phi_mod
96  reference_layer_index, eta_center);
97  float phi_cell =
98  m_geo->getDDE(reference_layer_index, eta_center, phi_center)->phi();
99  float phi_within_cell = fmod(phi_center - phi_cell, phi_cell_size);
100  if (phi_within_cell < 0) {
101  phi_within_cell += phi_cell_size;
102  }
103 
104  if (m_eventlibrary.size() <= event_index) {
105  m_eventlibrary.resize(event_index + 1);
106  }
107  if (m_eventlibrary.at(event_index).event_data.size() <=
108  reference_layer_index) {
109  m_eventlibrary.at(event_index).event_data.resize(reference_layer_index + 1);
110  }
111  m_eventlibrary.at(event_index).center_eta = eta_center;
112  m_eventlibrary.at(event_index).phi_mod = phi_within_cell;
113 }
114 
116  float eta_center, float phi_center, float e_init,
117  long unsigned int reference_layer_index, bool phi_mod_matching) const {
118 
119  float phi_cell_size, phi_within_cell;
120 
121  if (phi_mod_matching) {
122  const CaloDetDescrElement *cellele =
123  m_geo->getDDE(reference_layer_index, eta_center, phi_center);
125  reference_layer_index, eta_center);
126 
127  float phi_cell = cellele->phi();
128  phi_within_cell = phi_center - phi_cell;
129 
130  phi_within_cell = fmod(phi_within_cell, phi_cell_size);
131  if (phi_within_cell < 0)
132  phi_within_cell += phi_cell_size;
133  }
134 
135  // Find the event with the closest eta_center and phi_mod (L2 distance)
136  float best_distance = std::numeric_limits<float>::max();
137  long unsigned int best_match = m_eventlibrary.size() + 1;
138 
139  for (long unsigned int event_index = 0; event_index < m_eventlibrary.size();
140  ++event_index) {
141 
142  // Absolute eta difference. Normalized by the (usual) eta range of 0.05...
143  float eta_diff =
144  (m_eventlibrary.at(event_index).center_eta - eta_center) / 0.05;
145 
146  // Logarithmic energy difference. Use power of two (distance between usual
147  // energy points) as reasonable distance measure.
148  float e_diff =
149  std::log(m_eventlibrary.at(event_index).e_init / e_init) / std::log(2);
150 
151  // float dist2 = eta_diff * eta_diff;
152  float dist2 = eta_diff * eta_diff + e_diff * e_diff;
153 
154  if (phi_mod_matching) {
155  float phi_mod = m_eventlibrary.at(event_index).phi_mod;
156  float phi_diff = (phi_mod - phi_within_cell) / phi_cell_size;
157  dist2 = dist2 + phi_diff * phi_diff;
158  }
159  float distance = TMath::Sqrt(dist2);
160 
161  if (distance < best_distance) {
162  best_distance = distance;
163  best_match = event_index;
164  }
165  }
166 
167  if (best_match == m_eventlibrary.size() + 1) {
168  ATH_MSG_ERROR("No best match found");
169  } else {
170  ATH_MSG_INFO("Best match found for eta "
171  << eta_center << " / "
172  << m_eventlibrary.at(best_match).center_eta << " with energy "
173  << e_init << " / " << m_eventlibrary.at(best_match).e_init);
174  }
175 
176  return best_match;
177 }
178 
180  TFCSSimulationState &simulstate, float eta_center, float phi_center,
181  float e_init, long unsigned int reference_layer_index) const {
182 
183  if (m_eventlibrary.empty()) {
185  "No event library loaded. Please load an event libray for "
186  "TFCSBinnedShower::get_event.");
187  return;
188  }
189 
190  simulstate.setAuxInfo<float>("BSEinit"_FCShash, e_init);
191 
192  long unsigned int event_index;
193  if (simulstate.hasAuxInfo("EventNr"_FCShash) && m_use_event_matching) {
194  event_index = simulstate.getAuxInfo<int>("EventNr"_FCShash);
196  // dphi/deta
197  event_index =
198  find_best_match(eta_center, phi_center, e_init, reference_layer_index,
200 
201  if (event_index >= m_eventlibrary.size()) {
202  event_index = std::floor(CLHEP::RandFlat::shoot(
203  simulstate.randomEngine(), 0, m_eventlibrary.size()));
204  }
205 
206  } else {
207  event_index = std::floor(CLHEP::RandFlat::shoot(simulstate.randomEngine(),
208  0, m_eventlibrary.size()));
209  }
210 
211  ATH_MSG_DEBUG("Using event index " << event_index << " for eta " << eta_center
212  << " and phi " << phi_center);
213 
214  // Store a pointer to the event
215  event_t *event_ptr = new event_t(m_eventlibrary.at(event_index));
216  simulstate.setAuxInfo<void *>("BSEventData"_FCShash, event_ptr);
217 
218  compute_n_hits_and_elayer(simulstate);
219 }
220 
222  TFCSSimulationState &simulstate) const {
223 
224  event_t *event = static_cast<event_t *>(
225  simulstate.getAuxInfo<void *>("BSEventData"_FCShash));
226  float e_init = simulstate.getAuxInfo<float>("BSEinit"_FCShash);
227 
228  // Loop over all layers
229  long unsigned int n_layers = event->event_data.size();
230  std::vector<std::vector<long unsigned int>> hits_per_layer;
231  std::vector<float> elayer;
232  hits_per_layer.resize(n_layers);
233  elayer.resize(n_layers, 0.0f);
234 
235  for (long unsigned int layer_index = 0; layer_index < n_layers;
236  ++layer_index) {
237 
238  layer_t &layer = event->event_data.at(layer_index);
239 
240  // Loop over all voxels in the layer
241  long unsigned int n_hits = 0;
242  for (float e_voxel : layer.E_vector) {
243  long unsigned int hits_per_bin;
244  if (e_voxel > std::numeric_limits<float>::epsilon()) {
245  hits_per_bin =
246  std::min(std::max(int(e_voxel * e_init / m_default_hit_energy), 1),
248  elayer.at(layer_index) += e_voxel * e_init;
249 
250  } else {
251  hits_per_bin = 0;
252  }
253  n_hits += hits_per_bin;
254  hits_per_layer.at(layer_index).push_back(n_hits);
255  }
256  }
257  // Store the hits per layer vector
258  std::vector<std::vector<long unsigned int>> *hits_per_layer_ptr =
259  new std::vector<std::vector<long unsigned int>>(std::move(hits_per_layer));
260  simulstate.setAuxInfo<void *>("BSNHits"_FCShash, hits_per_layer_ptr);
261 
262  // Store the energy per layer
263  std::vector<float> *elayer_ptr = new std::vector<float>(std::move(elayer));
264  simulstate.setAuxInfo<void *>("BSELayer"_FCShash, elayer_ptr);
265 }
266 
268  TFCSSimulationState &simulstate, long unsigned int layer_index) const {
269 
270  std::vector<std::vector<long unsigned int>> *hits_per_layer_ptr =
271  static_cast<std::vector<std::vector<long unsigned int>> *>(
272  simulstate.getAuxInfo<void *>("BSNHits"_FCShash));
273 
274  if (!hits_per_layer_ptr) {
275  ATH_MSG_ERROR("Invalid hits per layer information");
276  return 0;
277  }
278 
279  return hits_per_layer_ptr->at(layer_index).back();
280 }
281 
283  long unsigned int layer_index) const {
284  std::vector<float> *elayer_ptr = static_cast<std::vector<float> *>(
285  simulstate.getAuxInfo<void *>("BSELayer"_FCShash));
286  if (!elayer_ptr) {
287  ATH_MSG_ERROR("Invalid layer energy information");
288  return 0.0f;
289  }
290  if (layer_index >= elayer_ptr->size()) {
291  return 0.0f;
292  }
293  return elayer_ptr->at(layer_index);
294 }
295 
297  TFCSSimulationState &simulstate, long unsigned int layer_index,
298  long unsigned int hit_index) const {
299  std::vector<std::vector<long unsigned int>> *hits_per_layer_ptr =
300  static_cast<std::vector<std::vector<long unsigned int>> *>(
301  simulstate.getAuxInfo<void *>("BSNHits"_FCShash));
302  if (!hits_per_layer_ptr) {
303  ATH_MSG_ERROR("Invalid hits per layer information");
304  return 0;
305  }
306 
307  if (layer_index >= hits_per_layer_ptr->size()) {
308  ATH_MSG_ERROR("Layer index out of bounds: " << layer_index << " >= "
309  << hits_per_layer_ptr->size());
310  return 0;
311  }
312 
313  // Find the hit index in the hit vector for the given layer
314  const std::vector<long unsigned int> &hits =
315  hits_per_layer_ptr->at(layer_index);
316  auto it = std::upper_bound(hits.begin(), hits.end(), hit_index);
317  long unsigned int energy_index = std::distance(hits.begin(), it);
318 
319  if (energy_index >= hits.size()) {
320  ATH_MSG_ERROR("Energy index out of bounds: " << energy_index
321  << " >= " << hits.size());
322  // Print full hits for debugging
323  ATH_MSG_ERROR("Hits per layer: ");
324  for (const auto &hit : hits) {
325  ATH_MSG_ERROR("Hit: " << hit);
326  }
327  return 0;
328  }
329 
330  return energy_index;
331 }
332 
333 std::tuple<float, float> TFCSBinnedShower::get_coordinates(
334  TFCSSimulationState &simulstate, long unsigned int layer_index,
335  int bin_index) const {
336  float R_min = m_coordinates.at(layer_index).R_lower.at(bin_index);
337  float R_max = m_coordinates.at(layer_index).R_size.at(bin_index) +
338  m_coordinates.at(layer_index).R_lower.at(bin_index);
339 
340  float alpha_min = m_coordinates.at(layer_index).alpha_lower.at(bin_index);
341  float alpha_max = m_coordinates.at(layer_index).alpha_size.at(bin_index) +
342  m_coordinates.at(layer_index).alpha_lower.at(bin_index);
343 
344  if (m_use_upscaling) {
345  upscale(simulstate, R_min, R_max, alpha_min, alpha_max, layer_index,
346  bin_index);
347  }
348  float R;
349  if (TMath::Abs(R_max - R_min) > std::numeric_limits<float>::epsilon()) {
350  R = CLHEP::RandFlat::shoot(simulstate.randomEngine(), R_min, R_max);
351  } else {
352  R = R_min; // If the range is too small, just use the minimum value
353  }
354  float alpha =
355  CLHEP::RandFlat::shoot(simulstate.randomEngine(), alpha_min, alpha_max);
356 
357  return std::make_tuple(R, alpha);
358 }
359 
360 void TFCSBinnedShower::upscale(TFCSSimulationState &simulstate, float &R_min,
361  float &R_max, float &alpha_min, float &alpha_max,
362  long unsigned int layer_index,
363  int bin_index) const {
364 
365  float p = CLHEP::RandFlat::shoot(simulstate.randomEngine(), 0, 1);
366 
367  float e_init = simulstate.getAuxInfo<float>("BSEinit"_FCShash);
368  std::vector<float> available_energies = m_upscaling_energies;
369 
370  unsigned int e_index = 0;
371 
372  std::vector<float> probabilities = {0.25f, 0.5f, 0.75f};
373 
374  if (available_energies.size() > 1) {
375  // find closest energy index using binary search
376  auto it = std::upper_bound(available_energies.begin(),
377  available_energies.end(), e_init);
378  if (it != available_energies.end()) {
379  e_index = std::distance(available_energies.begin(), it);
380  } else {
381  e_index = available_energies.size() - 1;
382  }
383 
384  float e_high = available_energies.at(e_index);
385  if (e_high < e_init || e_index == 0) {
386  if (m_sub_bin_distribution.at(e_index).size() > layer_index) {
387  probabilities =
388  m_sub_bin_distribution.at(e_index).at(layer_index).at(bin_index);
389  }
390  } else {
391  if (m_sub_bin_distribution.at(e_index).size() > layer_index &&
392  m_sub_bin_distribution.at(e_index - 1).size() > layer_index) {
393  float e_low = available_energies.at(e_index - 1);
394  float f_low = std::log(e_high / e_init) / (std::log(e_high / e_low));
395  float f_high = 1 - f_low;
396  for (unsigned int i = 0; i < 3; ++i) {
397  float p_low = m_sub_bin_distribution.at(e_index - 1)
398  .at(layer_index)
399  .at(bin_index)
400  .at(i);
401  float p_high = m_sub_bin_distribution.at(e_index)
402  .at(layer_index)
403  .at(bin_index)
404  .at(i);
405  probabilities[i] = f_low * p_low + f_high * p_high;
406  }
407  }
408  }
409  }
410 
411  else if (available_energies.size() == 1) {
412  probabilities = m_sub_bin_distribution.at(0).at(layer_index).at(bin_index);
413  }
414 
415  float p_alpha_low = probabilities[2] - probabilities[1] + probabilities[0];
416  float p_r;
417 
418  if (p < p_alpha_low) {
419  alpha_max = (alpha_min + alpha_max) / 2.;
420  p_r = probabilities[0] / (p_alpha_low);
421  } else {
422  alpha_min = (alpha_min + alpha_max) / 2.;
423  p_r = (probabilities[1] - probabilities[0]) / (1 - p_alpha_low);
424  }
425 
426  p = CLHEP::RandFlat::shoot(simulstate.randomEngine(), 0, 1);
427  if (layer_index != 2){
428  // if ((layer_index != 2) && (layer_index != 1)) {
429  if (p > p_r) {
430  R_min = (R_min + R_max) / 2.;
431  return;
432  } else {
433  R_max = (R_min + R_max) / 2.;
434  return;
435  }
436  }
437 
438 
439  // Use linear interpolation for layer 2
440  // It works better than uniform sampling for the second layer...
441  if (p_r < 0.25) {
442  p_r = 0.25; // Values below 0.25 are not allowed for linear pdf
443  } else if (p_r > 0.75) {
444  p_r = 0.75; // Values above 0.75 are not allowed for linear pdf
445  } else if (TMath::Abs(p_r - 0.5) < std::numeric_limits<float>::epsilon()) {
446  return; // Best upscaling is uniform sampling. Nothing to do here.
447  }
448 
449  // Inverse CDF for linear pdf
450  float r = (1. - 4. * p_r) / (2. - 4. * p_r) -
451  TMath::Sqrt(((1. - 4. * p_r) / (2. - 4. * p_r)) *
452  ((1. - 4. * p_r) / (2. - 4. * p_r)) +
453  p / ((1. / 2.) - p_r));
454  if (r < 0) {
455  r = (1. - 4. * p_r) / (2. - 4. * p_r) +
456  TMath::Sqrt(((1. - 4. * p_r) / (2. - 4. * p_r)) *
457  ((1. - 4. * p_r) / (2. - 4. * p_r)) +
458  p / ((1. / 2.) - p_r));
459  }
460 
461  R_min = R_min + r / 2 * (R_max - R_min);
462  R_max = R_min;
463 
464  return;
465 }
466 
467 std::tuple<float, float, float> TFCSBinnedShower::get_hit_position_and_energy(
468  TFCSSimulationState &simulstate, long unsigned int layer_index,
469  long unsigned int hit_index) const {
470 
471  event_t *event = static_cast<event_t *>(
472  simulstate.getAuxInfo<void *>("BSEventData"_FCShash));
473 
474  float e_init = simulstate.getAuxInfo<float>("BSEinit"_FCShash);
475 
476  if (layer_index >= event->event_data.size()) {
477  ATH_MSG_ERROR("Layer index out of bounds: " << layer_index << " >= "
478  << event->event_data.size());
479  return std::make_tuple(0.0f, 0.0f, 0.0f);
480  }
481 
482  long unsigned int energy_index = get_energy_index(
483  simulstate, layer_index, hit_index); // Get the bin index for the hit
484 
485  std::vector<std::vector<long unsigned int>> *hits_per_layer_ptr =
486  static_cast<std::vector<std::vector<long unsigned int>> *>(
487  simulstate.getAuxInfo<void *>("BSNHits"_FCShash));
488 
489  long unsigned int hits_per_bin;
490  if (energy_index == 0) {
491  hits_per_bin = hits_per_layer_ptr->at(layer_index).at(energy_index);
492  } else {
493  hits_per_bin = hits_per_layer_ptr->at(layer_index).at(energy_index) -
494  hits_per_layer_ptr->at(layer_index).at(energy_index - 1);
495  }
496 
497  float r, alpha;
498 
499  layer_t &layer = event->event_data.at(layer_index);
500 
501  std::tie(r, alpha) = get_coordinates(simulstate, layer_index,
502  layer.bin_index_vector.at(energy_index));
503 
504  float E = layer.E_vector.at(energy_index) * e_init / hits_per_bin;
505 
506  return std::make_tuple(r, alpha, E);
507 }
508 
510  // Delete the event data
511  void *event_ptr = simulstate.getAuxInfo<void *>("BSEventData"_FCShash);
512  if (event_ptr) {
513  delete static_cast<event_t *>(event_ptr);
514  simulstate.setAuxInfo<void *>("BSEventData"_FCShash, nullptr);
515  } else {
516  ATH_MSG_ERROR("No event data found to delete.");
517  }
518 
519  void *n_hits_ptr = simulstate.getAuxInfo<void *>("BSNHits"_FCShash);
520  if (n_hits_ptr) {
521  delete static_cast<std::vector<std::vector<long unsigned int>> *>(
522  n_hits_ptr);
523  simulstate.setAuxInfo<void *>("BSNHits"_FCShash, nullptr);
524  } else {
525  ATH_MSG_ERROR("No event hits data found to delete.");
526  }
527 
528  void *elayer_ptr = simulstate.getAuxInfo<void *>("BSELayer"_FCShash);
529  if (elayer_ptr) {
530  delete static_cast<std::vector<float> *>(elayer_ptr);
531  simulstate.setAuxInfo<void *>("BSELayer"_FCShash, nullptr);
532  } else {
533  ATH_MSG_ERROR("No event layer energy data found to delete.");
534  }
535 
536  return;
537 }
538 
540  const std::string &filename, std::vector<long unsigned int> &layers,
541  bool only_load_meta_data) {
542 
543  if (!only_load_meta_data) {
544  m_eventlibrary.clear();
545  }
546 
547  m_coordinates.clear();
548 
549  if (m_use_upscaling) {
550  m_sub_bin_distribution.clear();
551  }
552 
553  // layer dependent variables
554  for (long unsigned int layer_index : layers) {
555 
556  ATH_MSG_INFO("Loading layer " << layer_index << " from file: " << filename);
557 
558  // Load the bin boundaries for this layer
559  load_bin_boundaries(filename, layer_index);
560 
561  if (!only_load_meta_data) {
562  // Load the layer energies
563  load_layer_energy(filename, layer_index);
564  }
565 
566  }
567 
569  !only_load_meta_data) {
571  }
572 
573  return;
574 }
575 
576 std::tuple<std::vector<float>, std::vector<hsize_t>, bool>
578  const std::string &datasetname) {
579 
580  // Open the HDF5 file and dataset
581  H5::H5File file(filename, H5F_ACC_RDONLY);
582 
583  // check if the dataset exists
584  if (!file.exists(datasetname)) {
585  return std::make_tuple(std::vector<float>{}, std::vector<hsize_t>{}, false);
586  }
587 
588  H5::DataSet dataset = file.openDataSet(datasetname);
589 
590  // Get the dataspace of the dataset
591  H5::DataSpace dataspace = dataset.getSpace();
592 
593  // Get the number of dimensions and the size of each dimension
594  int rank = dataspace.getSimpleExtentNdims();
595  std::vector<hsize_t> dims_out(rank);
596  dataspace.getSimpleExtentDims(dims_out.data(), NULL);
597 
598  // Calculate the total number of elements
599  hsize_t totalSize = 1;
600  for (const auto &dim : dims_out) {
601  totalSize *= dim;
602  }
603 
604  // Read the dataset into a buffer
605  std::vector<float> data(totalSize);
606  dataset.read(data.data(), H5::PredType::NATIVE_FLOAT);
607  file.close();
608  return std::make_tuple(data, dims_out, true);
609 }
610 
612  long unsigned int layer_index) {
613 
614  std::string datasetname = "energy_layer_" + std::to_string(layer_index);
615 
616  std::vector<float> data;
617  std::vector<hsize_t> dims;
618  bool success;
619  std::tie(data, dims, success) = load_hdf5_dataset(filename, datasetname);
620  if (!success) {
621  ATH_MSG_ERROR("Error while extracting the layer energy for layer "
622  << layer_index << " from " << filename << ".");
623  return;
624  }
625 
626  // Store the data in the event library
627  std::vector<unsigned int> bin_index_vector;
628  std::vector<float> E_vector;
629 
630  for (size_t i = 0; i < data.size(); ++i) {
631  long unsigned int event_index = i / dims.at(1);
632  float bin_index = i % dims.at(1);
633 
634  if (bin_index == 0) {
635  bin_index_vector.clear();
636  E_vector.clear();
637  }
638 
639  if (data.at(i) != 0.0) {
640  bin_index_vector.push_back(bin_index);
641  E_vector.push_back(data.at(i));
642  }
643 
644  if (bin_index ==
645  dims.at(1) - 1) // True for the last voxel of the event in this layer
646  {
647  set_layer_energy(event_index, layer_index, bin_index_vector, E_vector);
648  }
649  }
650 }
651 
653  long unsigned int layer_index) {
654 
655  // Assert that the layer index is valid
656  if (layer_index >= m_coordinates.size()) {
657  m_coordinates.resize(layer_index + 1);
658  }
659 
660  std::vector<std::string> datasetnames = {
661  "binstart_radius_layer_", "binsize_radius_layer_",
662  "binstart_alpha_layer_", "binsize_alpha_layer_"};
663 
664  for (long unsigned int i = 0; i < datasetnames.size(); i++) {
665  std::string datasetname = datasetnames.at(i) + std::to_string(layer_index);
666  std::vector<float> data;
667  std::vector<hsize_t> dims;
668  bool success;
669  std::tie(data, dims, success) = load_hdf5_dataset(filename, datasetname);
670  if (!success) {
671  ATH_MSG_ERROR("Error while extracting the bin boundaries for layer "
672  << layer_index << " from " << filename << "."
673  << "Specifically, the key " << datasetname
674  << " could not be loaded.");
675  return;
676  }
677 
678  // Fill the corresponding vector in the layer_bins_t structure
679  auto &event_bins = m_coordinates.at(layer_index);
680  switch (i) {
681  case 0:
682  event_bins.R_lower = std::move(data);
683  break;
684  case 1:
685  event_bins.R_size = std::move(data);
686  break;
687  case 2:
688  event_bins.alpha_lower = std::move(data);
689  break;
690  case 3:
691  event_bins.alpha_size = std::move(data);
692  break;
693  }
694  }
695 }
696 
698  const std::string &filename) {
699 
700  // Open the HDF5 file
701  H5::H5File file(filename, H5F_ACC_RDONLY);
702 
703  // Open the dataset
704  std::vector<std::string> datasetnames = {"phi_mod", "center_eta",
705  "incident_energy"};
706 
707  for (long unsigned int i = 0; i < datasetnames.size(); i++) {
708  std::string datasetname = datasetnames.at(i);
709  std::vector<float> data;
710  std::vector<hsize_t> dims;
711  bool success;
712  std::tie(data, dims, success) = load_hdf5_dataset(filename, datasetname);
713  if (!success) {
714  if (datasetname == "phi_mod" && m_use_eta_matching) {
715  // We do not necessarly need the phi_mod for eta matching, so we can
716  // just skip this dataset
717  continue;
718  } else {
720  "Error while extracting the shower center information from "
721  << filename << "."
722  << "Specifically, the key " << datasetname
723  << " could not be loaded.");
724  }
725  return;
726  }
727 
728  for (long unsigned int event_index = 0; event_index < data.size();
729  ++event_index) {
730  switch (i) {
731  case 0:
732  m_eventlibrary.at(event_index).phi_mod = data.at(event_index);
733  break;
734  case 1:
735  m_eventlibrary.at(event_index).center_eta = data.at(event_index);
736  break;
737  case 2:
738  m_eventlibrary.at(event_index).e_init = data.at(event_index);
739  break;
740  }
741  }
742  }
743 }
744 
745 void TFCSBinnedShower::Streamer(TBuffer &R__b) {
746  // Stream an object of class TFCSBinnedShower
747 
748  if (R__b.IsReading()) {
749  R__b.ReadClassBuffer(TFCSBinnedShower::Class(), this);
750 
751  // Load the event library from file
752  if (!m_hdf5_file.empty()) {
753  std::vector<long unsigned int> layers;
754  for (long unsigned int i = 0; i < m_n_layers; ++i) {
755  layers.push_back(i);
756  }
757  ATH_MSG_INFO("Loading event library from " << m_hdf5_file);
758  ((TFCSBinnedShower *)this)->load_event_library(m_hdf5_file, layers);
759  ATH_MSG_INFO("Size after loading" << m_eventlibrary.size());
760  } else {
761  ATH_MSG_INFO(
762  "Using existing event library of size: " << m_eventlibrary.size());
763  }
764 
765  } else {
766  // Remove the event library again, if it was loaded from file
767  if (!m_hdf5_file.empty()) {
768  ATH_MSG_DEBUG("Clear event library before saving");
769  m_eventlibrary.resize(0);
770  }
771 
772  R__b.WriteClassBuffer(TFCSBinnedShower::Class(), this);
773  }
774 }
775 
777  m_use_upscaling = true;
778  TFile *file = TFile::Open(filename.c_str(), "READ");
779  if (!file || file->IsZombie()) {
780  std::cerr << "Failed to open file: " << filename << std::endl;
781  return;
782  }
783 
784  std::regex pattern(R"(probabilities_layer_(\d+)_energy_([0-9.]+))");
785  std::map<float, std::map<int, std::vector<std::vector<float>>>> temp_storage;
786 
787  TIter next(file->GetListOfKeys());
788  TKey *key;
789 
790  while ((key = (TKey *)next())) {
791  std::string keyname = key->GetName();
792  std::smatch match;
793  if (std::regex_match(keyname, match, pattern)) {
794  int layer = std::stoi(match[1].str());
795  float energy = std::stod(match[2].str());
796 
797  TMatrixD *matrix = dynamic_cast<TMatrixD *>(file->Get(keyname.c_str()));
798  if (matrix) {
799  std::vector<std::vector<float>> mat_vec(
800  matrix->GetNrows(), std::vector<float>(matrix->GetNcols()));
801  for (int i = 0; i < matrix->GetNrows(); ++i) {
802  for (int j = 0; j < matrix->GetNcols(); ++j) {
803  mat_vec[i][j] = static_cast<float>((*matrix)(i, j));
804  }
805  }
806  temp_storage[energy][layer] = std::move(mat_vec);
807  }
808  }
809  }
810 
811  file->Close();
812  delete file;
813 
814  // Output containers
815  std::vector<float> energies;
816  std::vector<std::vector<std::vector<std::vector<float>>>>
817  data; // [energy][layer][row][col]
818 
819  for (const auto &[energy, layer_map] : temp_storage) {
820  energies.push_back(energy);
821  int max_layer = 0;
822  for (const auto &[l, _] : layer_map)
823  max_layer = std::max(max_layer, l);
824 
825  std::vector<std::vector<std::vector<float>>> layer_vec(max_layer + 1);
826  for (const auto &[layer_idx, mat] : layer_map) {
827  layer_vec[layer_idx] = mat;
828  }
829  data.push_back(std::move(layer_vec));
830  }
831 
832  // Example output
833  for (size_t i = 0; i < energies.size(); ++i) {
834  std::cout << "Energy index " << i << ": " << energies[i] << " GeV\n";
835  for (size_t j = 0; j < data[i].size(); ++j) {
836  if (!data[i][j].empty()) {
837  std::cout << " Layer " << j << " Shape: (" << data[i][j].size() << ", "
838  << data[i][j][0].size() << ")\n";
839  }
840  }
841  }
842 
843  m_upscaling_energies = std::move(energies);
844  m_sub_bin_distribution = std::move(data);
845 }
TFCSBinnedShower::get_n_hits
virtual long unsigned int get_n_hits(TFCSSimulationState &simulstate, long unsigned int layer_index) const override
Definition: TFCSBinnedShower.cxx:267
TFCSCenterPositionCalculation.h
mergePhysValFiles.pattern
pattern
Definition: DataQuality/DataQualityUtils/scripts/mergePhysValFiles.py:25
beamspotman.r
def r
Definition: beamspotman.py:672
TFCSBinnedShowerBase::m_geo
ICaloGeometry * m_geo
Definition: TFCSBinnedShowerBase.h:63
data
char data[hepevt_bytes_allocation_ATLAS]
Definition: HepEvt.cxx:11
TFCSBinnedShower::layer_t
Definition: TFCSBinnedShower.h:25
TFCSSimulationState::getAuxInfo
const T getAuxInfo(std::uint32_t index) const
Definition: TFCSSimulationState.h:161
createLinkingScheme.layer_idx
layer_idx
Definition: createLinkingScheme.py:43
TFCSBinnedShower::m_max_hits_per_voxel
int m_max_hits_per_voxel
Definition: TFCSBinnedShower.h:191
TFCSBinnedShower::load_shower_center_information
void load_shower_center_information(const std::string &filename)
Definition: TFCSBinnedShower.cxx:697
TFCSBinnedShower::load_sub_bin_distribution
void load_sub_bin_distribution(const std::string &filename)
Definition: TFCSBinnedShower.cxx:776
yodamerge_tmp.dim
dim
Definition: yodamerge_tmp.py:239
add-xsec-uncert-quadrature-N.alpha
alpha
Definition: add-xsec-uncert-quadrature-N.py:110
TRTCalib_Extractor.hits
hits
Definition: TRTCalib_Extractor.py:35
Run3DQTestingDriver._
_
Definition: Run3DQTestingDriver.py:35
TFCSBinnedShower::load_event_library
void load_event_library(const std::string &filename, std::vector< long unsigned int > &layers, bool only_load_meta_data=false)
Definition: TFCSBinnedShower.cxx:539
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
TFCSBinnedShower::m_upscaling_energies
std::vector< float > m_upscaling_energies
Definition: TFCSBinnedShower.h:234
TFCSBinnedShower::~TFCSBinnedShower
virtual ~TFCSBinnedShower()
Definition: TFCSBinnedShower.cxx:53
max
constexpr double max()
Definition: ap_fixedTest.cxx:33
mat
GeoMaterial * mat
Definition: LArDetectorConstructionTBEC.cxx:55
min
constexpr double min()
Definition: ap_fixedTest.cxx:26
TFCSBinnedShower::load_bin_boundaries
void load_bin_boundaries(const std::string &filename, long unsigned int layer_index)
Definition: TFCSBinnedShower.cxx:652
CaloDetDescrElement
This class groups all DetDescr information related to a CaloCell. Provides a generic interface for al...
Definition: Calorimeter/CaloDetDescr/CaloDetDescr/CaloDetDescrElement.h:66
TRT::Track::event
@ event
Definition: InnerDetector/InDetCalibEvent/TRT_CalibData/TRT_CalibData/TrackInfo.h:74
TFCSBinnedShower::find_best_match
long unsigned int find_best_match(float eta_center, float phi_center, float e_init, long unsigned int reference_layer_index, bool phi_mod_matching) const
Definition: TFCSBinnedShower.cxx:115
CaloClusterMLCalib::epsilon
constexpr float epsilon
Definition: CaloClusterMLGaussianMixture.h:16
TFCSBinnedShower::set_layer_energy
void set_layer_energy(long unsigned int event_index, long unsigned int layer_index, const std::vector< unsigned int > &bin_index_vector, const std::vector< float > &E_vector)
Definition: TFCSBinnedShower.cxx:55
module_driven_slicing.layers
layers
Definition: module_driven_slicing.py:113
skel.it
it
Definition: skel.GENtoEVGEN.py:407
TFCSBinnedShower::m_use_upscaling
bool m_use_upscaling
Definition: TFCSBinnedShower.h:228
TFCSBinnedShower
Definition: TFCSBinnedShower.h:23
PrintTrkAnaSummary.l
l
Printing final latex table to .tex output file.
Definition: PrintTrkAnaSummary.py:371
TFCSSimulationState::randomEngine
CLHEP::HepRandomEngine * randomEngine()
Definition: TFCSSimulationState.h:36
TFCSBinnedShower::event_t
Definition: TFCSBinnedShower.h:30
MuonR4::to_string
std::string to_string(const SectorProjector proj)
Definition: MsTrackSeeder.cxx:66
TFCSBinnedShower::get_layer_energy
virtual float get_layer_energy(TFCSSimulationState &simulstate, long unsigned int layer_index) const override
Definition: TFCSBinnedShower.cxx:282
TFCSBinnedShower::upscale
void upscale(TFCSSimulationState &simulstate, float &R_min, float &R_max, float &alpha_min, float &alpha_max, long unsigned int layer_index, int bin_index) const
Definition: TFCSBinnedShower.cxx:360
TFCSBinnedShower::delete_event
virtual void delete_event(TFCSSimulationState &simulstate) const override
Definition: TFCSBinnedShower.cxx:509
TFCSBinnedShower::set_bin_boundaries
void set_bin_boundaries(long unsigned int layer_index, std::vector< float > &R_lower, std::vector< float > &R_size, std::vector< float > &alpha_lower, std::vector< float > &alpha_size)
Definition: TFCSBinnedShower.cxx:76
PrepareReferenceFile.regex
regex
Definition: PrepareReferenceFile.py:43
TFCSBinnedShower::m_n_layers
const long unsigned int m_n_layers
Definition: TFCSBinnedShower.h:185
TFCSBinnedShowerBase.h
TFCSLateralShapeParametrizationHitBase.h
TFCSBinnedShower::get_event
virtual void get_event(TFCSSimulationState &simulstate, float eta_center, float phi_center, float e_init, long unsigned int reference_layer_index) const override
do not persistify
Definition: TFCSBinnedShower.cxx:179
TFCSBinnedShower::m_use_eta_matching
bool m_use_eta_matching
Definition: TFCSBinnedShower.h:216
python.utils.AtlRunQueryDQUtils.p
p
Definition: AtlRunQueryDQUtils.py:209
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
ParticleGun_FastCalo_ChargeFlip_Config.energy
energy
Definition: ParticleGun_FastCalo_ChargeFlip_Config.py:78
fillPileUpNoiseLumi.next
next
Definition: fillPileUpNoiseLumi.py:52
TFCSBinnedShower::get_hit_position_and_energy
virtual std::tuple< float, float, float > get_hit_position_and_energy(TFCSSimulationState &simulstate, long unsigned int layer_index, long unsigned int hit_index) const override
Definition: TFCSBinnedShower.cxx:467
lumiFormat.i
int i
Definition: lumiFormat.py:85
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
TRT::Hit::layer
@ layer
Definition: HitInfo.h:79
python.CaloAddPedShiftConfig.str
str
Definition: CaloAddPedShiftConfig.py:42
covarianceTool.title
title
Definition: covarianceTool.py:542
TFCSSimulationState::hasAuxInfo
bool hasAuxInfo(std::uint32_t index) const
Definition: TFCSSimulationState.h:155
TFCSBinnedShower::compute_n_hits_and_elayer
virtual void compute_n_hits_and_elayer(TFCSSimulationState &simulstate) const
Definition: TFCSBinnedShower.cxx:221
file
TFile * file
Definition: tile_monitor.h:29
hist_file_dump.f
f
Definition: hist_file_dump.py:140
dataset
Definition: dataset.h:27
TFCSBinnedShower::get_coordinates
const event_bins_t & get_coordinates()
Definition: TFCSBinnedShower.h:130
AnalysisUtils::Delta::R
double R(const INavigable4Momentum *p1, const double v_eta, const double v_phi)
Definition: AnalysisMisc.h:49
TFCSBinnedShower::load_layer_energy
void load_layer_energy(const std::string &filename, long unsigned int layer_index)
Definition: TFCSBinnedShower.cxx:611
TFCSBinnedShowerBase
Definition: TFCSBinnedShowerBase.h:17
TFCSBinnedShower::m_eventlibrary
eventvector_t m_eventlibrary
Definition: TFCSBinnedShower.h:197
TFCSBinnedShower::m_hdf5_file
std::string m_hdf5_file
Definition: TFCSBinnedShower.h:194
TFCSBinnedShower::set_shower_center_information
void set_shower_center_information(long unsigned int event_index, long unsigned int reference_layer_index, float eta_center, float phi_center)
Definition: TFCSBinnedShower.cxx:90
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
VP1PartSpect::E
@ E
Definition: VP1PartSpectFlags.h:21
TFCSSimulationState::setAuxInfo
void setAuxInfo(std::uint32_t index, const T &val)
Definition: TFCSSimulationState.h:168
TFCSBinnedShower::load_hdf5_dataset
std::tuple< std::vector< float >, std::vector< hsize_t >, bool > load_hdf5_dataset(const std::string &filename, const std::string &datasetname)
Definition: TFCSBinnedShower.cxx:577
TFCSInitWithEkin.h
TFCSPhiModulationCorrection.h
TFCSBinnedShower::m_sub_bin_distribution
std::vector< std::vector< std::vector< std::vector< float > > > > m_sub_bin_distribution
Definition: TFCSBinnedShower.h:233
python.testIfMatch.matrix
matrix
Definition: testIfMatch.py:63
TFCSBinnedShower::m_use_event_matching
bool m_use_event_matching
Definition: TFCSBinnedShower.h:205
TFCSBinnedShower::m_default_hit_energy
float m_default_hit_energy
Definition: TFCSBinnedShower.h:189
TFCSTruthState.h
TFCSExtrapolationState.h
TFCSBinnedShower::m_coordinates
event_bins_t m_coordinates
Definition: TFCSBinnedShower.h:198
python.CaloCondTools.log
log
Definition: CaloCondTools.py:20
CaloCellTimeCorrFiller.filename
filename
Definition: CaloCellTimeCorrFiller.py:23
TFCSBinnedShower.h
TFCSBinnedShower::m_use_event_cherry_picking
bool m_use_event_cherry_picking
Definition: TFCSBinnedShower.h:211
python.copyTCTOutput.totalSize
totalSize
Definition: copyTCTOutput.py:90
CaloDetDescrElement::phi
float phi() const
cell phi
Definition: Calorimeter/CaloDetDescr/CaloDetDescr/CaloDetDescrElement.h:346
TFCSSimulationState.h
TFCSBinnedShower::TFCSBinnedShower
TFCSBinnedShower(const char *name=nullptr, const char *title=nullptr)
Definition: TFCSBinnedShower.cxx:50
ICaloGeometry::getDDE
virtual const CaloDetDescrElement * getDDE(Identifier identify) const =0
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
TFCSSimulationState
Definition: TFCSSimulationState.h:32
match
bool match(std::string s1, std::string s2)
match the individual directories of two strings
Definition: hcg.cxx:357
TFCSBinnedShower::get_energy_index
long unsigned int get_energy_index(TFCSSimulationState &simulstate, long unsigned int layer_index, long unsigned int hit_index) const
Definition: TFCSBinnedShower.cxx:296
mapkey::key
key
Definition: TElectronEfficiencyCorrectionTool.cxx:37
TrackOverlayDecisionAlg::e_diff
const float e_diff
Definition: TrackOverlayDecisionAlg.h:33