126 const int pdgId = truth->
pdgid();
127 const float charge = HepPDT::ParticleID(pdgId).charge();
130 const float Ekin = truth->
Ekin();
132 Einit = simulstate.
E();
138 if (!
m_slice->IsGanCorrectlyLoaded()) {
146 m_slice->GetNetworkOutputs(truth, extrapol, simulstate);
150 const auto ganVersion =
m_param.GetGANVersion();
156 double totalEnergy = 0;
157 for (
const auto & output : outputs) {
158 totalEnergy += output.second;
160 if (totalEnergy < 0) {
170 for (
const auto &[layer,
h] : binsInLayers) {
173 if (
h.IsZombie() ||
h.IsOnHeap() ||
dynamic_cast<const TH2D*
>(&
h) ==
nullptr) {
174 ATH_MSG_ERROR(
"Histogram for layer " << layer <<
" is broken; " <<
175 "zombie: " <<
h.IsZombie() <<
176 "on heap: " <<
h.IsOnHeap() <<
177 "dynamic type: " <<
typeid(
h).name());
195 const int xBinNum =
h.GetNbinsX();
196 const int yBinNum =
h.GetNbinsY();
197 const TAxis *
x =
h.GetXaxis();
203 <<
" has only one bin in r, this means is it not used, "
204 "skipping (this is needed to keep correct "
205 "syncronisation of voxel and layers)");
213 for (
int ix = 1; ix <= xBinNum; ++ix) {
215 for (
int iy = 1; iy <= binsInAlphaInRBin; ++iy) {
216 const double energyInVoxel = outputs.at(std::to_string(vox));
218 <<
" binx " << ix <<
" biny " << iy);
220 if (energyInVoxel <= 0) {
225 simulstate.
add_E(layer, Einit * energyInVoxel);
231 for (
unsigned int ichain =
m_bin_start.back(); ichain <
size(); ++ichain) {
240 for (
const auto &[layer,
h] : binsInLayers) {
241 const int xBinNum =
h.GetNbinsX();
242 const int yBinNum =
h.GetNbinsY();
243 const TAxis *
x =
h.GetXaxis();
244 const TAxis *
y =
h.GetYaxis();
246 simulstate.
setAuxInfo<
int>(
"GANlayer"_FCShash, layer);
253 <<
" has only one bin in r, this means is it not used, "
254 "skipping (this is needed to keep correct "
255 "syncronisation of voxel and layers)");
261 const int bin =
get_bin(simulstate, truth, extrapol);
269 <<
chain()[ichain]->GetName());
270 if (
chain()[ichain]->InheritsFrom(
271 TFCSLateralShapeParametrizationHitBase::Class())) {
274 if (sim->
simulate_hit(hit, simulstate, truth, extrapol) !=
279 <<
chain()[ichain]->GetName());
286 <<
chain()[ichain]->GetName()
287 <<
" does not inherit from "
288 "TFCSLateralShapeParametrizationHitBase");
299 int binResolution = 5;
300 if (layer == 1 || layer == 5) {
305 const double center_phi = hit.center_phi();
306 const double center_r = hit.center_r();
307 const double center_z = hit.center_z();
310 <<
" phi " << center_phi <<
" R " << center_r);
312 const float dist000 =
313 TMath::Sqrt(center_r * center_r + center_z * center_z);
314 const float eta_jakobi = TMath::Abs(2.0 * TMath::Exp(-center_eta) /
315 (1.0 + TMath::Exp(-2 * center_eta)));
321 for (
int ix = 1; ix <= xBinNum; ++ix) {
325 const int binsToMerge = yBinNum == 32 ? 32 / binsInAlphaInRBin : 1;
326 for (
int iy = 1; iy <= binsInAlphaInRBin; ++iy) {
327 const double energyInVoxel = outputs.at(std::to_string(vox));
328 const int lowEdgeIndex = (iy - 1) * binsToMerge + 1;
331 <<
" binx " << ix <<
" biny " << iy);
333 if (energyInVoxel <= 0) {
338 if (std::abs(pdgId) == 22 || std::abs(pdgId) == 11) {
340 int maxHitsInVoxel = energyInVoxel * truth->
Ekin() / 10;
341 if (maxHitsInVoxel < 1)
343 nHitsAlpha = std::sqrt(maxHitsInVoxel);
344 nHitsR = std::sqrt(maxHitsInVoxel);
347 nHitsR =
x->GetBinUpEdge(ix) -
x->GetBinLowEdge(ix);
350 const double r =
x->GetBinUpEdge(ix);
351 nHitsAlpha = ceil(2 * TMath::Pi() *
r / binResolution);
355 const double angle =
y->GetBinUpEdge(iy) -
y->GetBinLowEdge(iy);
356 const double r =
x->GetBinUpEdge(ix);
357 const double d = 2 *
r * sin(
angle / 2 *
r);
358 nHitsAlpha = ceil(d / binResolution);
361 if (layer != 1 && layer != 5) {
365 const int maxNhits = 10;
366 nHitsAlpha = std::min(maxNhits, std::max(1, nHitsAlpha));
367 nHitsR = std::min(maxNhits, std::max(1, nHitsR));
371 for (
int ir = 0;
ir < nHitsR; ++
ir) {
373 x->GetBinLowEdge(ix) +
x->GetBinWidth(ix) / (nHitsR + 1) *
ir;
375 for (
int ialpha = 1; ialpha <= nHitsAlpha; ++ialpha) {
376 if (ganVersion > 1) {
377 if (fitResults.at(layer)[ix - 1] != 0) {
380 x->GetBinLowEdge(ix),
381 x->GetBinUpEdge(ix));
383 log((
a -
x->GetBinLowEdge(ix)) / (
x->GetBinWidth(ix))) /
384 fitResults.at(layer)[ix - 1];
385 while ((rand_r < x->GetBinLowEdge(ix) ||
386 rand_r >
x->GetBinUpEdge(ix)) &&
389 x->GetBinLowEdge(ix),
390 x->GetBinUpEdge(ix));
392 log((
a -
x->GetBinLowEdge(ix)) / (
x->GetBinWidth(ix))) /
393 fitResults.at(layer)[ix - 1];
398 <<
x->GetBinLowEdge(ix) <<
"-"
399 <<
x->GetBinUpEdge(ix) <<
"] having slope "
400 << fitResults.at(layer)[ix - 1]
401 <<
" will use grid (old method)");
409 if (binsInAlphaInRBin == 1) {
410 alpha = CLHEP::RandFlat::shoot(simulstate.
randomEngine(),
411 -TMath::Pi(), TMath::Pi());
414 y->GetBinLowEdge(lowEdgeIndex) +
415 y->GetBinWidth(iy) * binsToMerge / (nHitsAlpha + 1) * ialpha;
417 if (
m_param.IsSymmetrisedAlpha()) {
419 -TMath::Pi(), TMath::Pi()) < 0) {
426 hit.E() = Einit * energyInVoxel / (nHitsAlpha * nHitsR);
429 float delta_eta_mm =
r * cos(alpha);
430 float delta_phi_mm =
r * sin(alpha);
440 delta_eta_mm = -delta_eta_mm;
445 if ((
charge < 0. && pdgId != 11) || pdgId == -11)
446 delta_phi_mm = -delta_phi_mm;
448 const float delta_eta = delta_eta_mm / eta_jakobi / dist000;
449 const float delta_phi = delta_phi_mm / center_r;
451 hit.eta() = center_eta + delta_eta;
452 hit.phi() = TVector2::Phi_mpi_pi(center_phi + delta_phi);
455 <<
" layer " << layer);
457 const float hit_r =
r * cos(alpha) + center_r;
458 float delta_phi =
r * sin(alpha) / center_r;
463 if ((
charge < 0. && pdgId != 11) || pdgId == -11)
464 delta_phi = -delta_phi;
465 const float hit_phi =
466 TVector2::Phi_mpi_pi(center_phi + delta_phi);
467 hit.x() = hit_r * cos(hit_phi);
468 hit.y() = hit_r * sin(hit_phi);
471 <<
" layer " << layer);
475 const int bin =
get_bin(simulstate, truth, extrapol);
477 for (
unsigned int ichain =
483 <<
chain()[ichain]->GetName());
484 if (
chain()[ichain]->InheritsFrom(
485 TFCSLateralShapeParametrizationHitBase::Class())) {
489 if (sim->
simulate_hit(hit, simulstate, truth, extrapol) !=
495 <<
chain()[ichain]->GetName());
502 <<
chain()[ichain]->GetName()
503 <<
" does not inherit from "
504 "TFCSLateralShapeParametrizationHitBase");
527 if (simulstate.
E() > std::numeric_limits<double>::epsilon()) {
529 simulstate.
set_Efrac(ilayer, simulstate.
E(ilayer) / simulstate.
E());
A number of constexpr particle constants to avoid hardcoding them directly in various places.