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