ATLAS Offline Software
Loading...
Searching...
No Matches
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
50TFCSBinnedShower::TFCSBinnedShower(const char *name, const char *title)
51 : TFCSBinnedShowerBase(name, title) {}
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
76void 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
333std::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
360void 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
467std::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) {
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
576std::tuple<std::vector<float>, std::vector<hsize_t>, bool>
577TFCSBinnedShower::load_hdf5_dataset(const std::string &filename,
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
611void TFCSBinnedShower::load_layer_energy(const std::string &filename,
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
652void TFCSBinnedShower::load_bin_boundaries(const std::string &filename,
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
745void 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 {
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
776void TFCSBinnedShower::load_sub_bin_distribution(const std::string &filename) {
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}
#define ATH_MSG_ERROR(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_DEBUG(x)
char data[hepevt_bytes_allocation_ATLAS]
Definition HepEvt.cxx:11
static unsigned int totalSize(const MultiDimArray< T, N > &ht)
static const Attributes_t empty
This class groups all DetDescr information related to a CaloCell.
TFCSBinnedShowerBase(const char *name=nullptr, const char *title=nullptr)
virtual long unsigned int get_n_hits(TFCSSimulationState &simulstate, long unsigned int layer_index) const override
void load_event_library(const std::string &filename, std::vector< long unsigned int > &layers, bool only_load_meta_data=false)
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)
virtual float get_layer_energy(TFCSSimulationState &simulstate, long unsigned int layer_index) const override
const long unsigned int m_n_layers
void load_sub_bin_distribution(const std::string &filename)
long unsigned int get_energy_index(TFCSSimulationState &simulstate, long unsigned int layer_index, long unsigned int hit_index) const
TFCSBinnedShower(const char *name=nullptr, const char *title=nullptr)
event_bins_t m_coordinates
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
void load_layer_energy(const std::string &filename, long unsigned int layer_index)
std::vector< std::vector< std::vector< std::vector< float > > > > m_sub_bin_distribution
void load_shower_center_information(const std::string &filename)
virtual void delete_event(TFCSSimulationState &simulstate) const override
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
std::string m_hdf5_file
const event_bins_t & get_coordinates()
void set_shower_center_information(long unsigned int event_index, long unsigned int reference_layer_index, float eta_center, float phi_center)
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)
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
std::tuple< std::vector< float >, std::vector< hsize_t >, bool > load_hdf5_dataset(const std::string &filename, const std::string &datasetname)
virtual void compute_n_hits_and_elayer(TFCSSimulationState &simulstate) const
void load_bin_boundaries(const std::string &filename, long unsigned int layer_index)
eventvector_t m_eventlibrary
std::vector< float > m_upscaling_energies
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
static float get_phi_cell_size(long unsigned int layer, float eta)
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()
int r
Definition globals.cxx:22
bool match(std::string s1, std::string s2)
match the individual directories of two strings
Definition hcg.cxx:357
TFile * file