22 #include <unordered_map>
26 #include <TDirectory.h>
31 namespace ActsExamples {
32 struct AlgorithmContext;
48 for (Parametrisation::EventFraction&
event :
events) {
50 double maxMomOthers = 0.;
55 if (p.
pdg() ==
event.initialParticle.pdg()) {
64 event.initialMomentum =
event.initialParticle.absoluteMomentum();
68 event.soft = (maxMom > maxMomOthers);
76 ptVec[0] += particlePt[0];
77 ptVec[1] += particlePt[1];
82 if (
event.soft && pt <=
event.interactingParticle.transverseMomentum()) {
87 event.multiplicity =
event.finalParticles.size();
99 std::tuple<std::vector<float>, std::vector<double>,
double>
100 buildNotNormalisedMap(TH1F
const*
hist) {
102 const int nBins = hist->GetNbinsX();
103 std::vector<float> histoBorders(nBins + 1);
107 std::vector<double> temp_HistoContents(nBins);
108 for (
int iBin = 0; iBin < nBins; iBin++) {
109 float binval = hist->GetBinContent(iBin + 1);
116 temp_HistoContents[iBin] =
integral;
120 if (integral == 0.) {
121 histoBorders.clear();
122 temp_HistoContents.clear();
127 for (
int iBin = 1; iBin <= nBins; iBin++) {
128 histoBorders[iBin - 1] = hist->GetXaxis()->GetBinLowEdge(iBin);
130 histoBorders[nBins] = hist->GetXaxis()->GetXmax();
139 void reduceMap(std::vector<float>& histoBorders,
140 std::vector<uint32_t>& histoContents) {
141 for (
auto cit = histoContents.cbegin(); cit != histoContents.cend(); cit++) {
142 while (
std::next(cit, 1) != histoContents.end() &&
147 histoBorders.erase(histoBorders.begin() +
distance);
148 histoContents.erase(histoContents.begin() +
distance);
161 std::pair<std::vector<float>, std::vector<uint32_t>> buildMap(
164 std::tuple<std::vector<float>, std::vector<double>,
double> map =
165 buildNotNormalisedMap(hist);
166 const int nBins = hist->GetNbinsX();
167 std::vector<double>& histoContents = std::get<1>(map);
170 if (histoContents.empty()) {
171 return std::make_pair(std::get<0>(map), std::vector<uint32_t>());
175 std::vector<uint32_t> normalisedHistoContents(nBins);
176 const double invIntegral = 1. / std::get<2>(map);
177 for (
int iBin = 0; iBin < nBins; ++iBin) {
178 normalisedHistoContents[iBin] =
static_cast<unsigned int>(
179 UINT32_MAX * (histoContents[iBin] * invIntegral));
182 auto histoBorders = std::get<0>(map);
183 reduceMap(histoBorders, normalisedHistoContents);
184 return std::make_pair(histoBorders, normalisedHistoContents);
198 std::pair<std::vector<float>, std::vector<uint32_t>> buildMap(TH1F
const* hist,
201 std::tuple<std::vector<float>, std::vector<double>,
double> map =
202 buildNotNormalisedMap(hist);
204 const int nBins = hist->GetNbinsX();
205 std::vector<double>& histoContents = std::get<1>(map);
208 if (histoContents.empty()) {
209 return std::make_pair(std::get<0>(map), std::vector<uint32_t>());
213 std::vector<uint32_t> normalisedHistoContents(nBins);
214 const double invIntegral = 1. / std::max(integral, std::get<2>(map));
215 for (
int iBin = 0; iBin < nBins; ++iBin) {
216 normalisedHistoContents[iBin] =
static_cast<unsigned int>(
217 UINT32_MAX * (histoContents[iBin] * invIntegral));
220 std::vector<float> histoBorders = std::get<0>(map);
221 reduceMap(histoBorders, normalisedHistoContents);
223 return std::make_pair(histoBorders, normalisedHistoContents);
233 std::vector<std::pair<std::vector<float>, std::vector<uint32_t>>> buildMaps(
234 const std::vector<TH1F*>&
histos) {
235 std::vector<std::pair<std::vector<float>, std::vector<uint32_t>>>
maps;
236 for (
auto&
h : histos) {
237 maps.push_back(buildMap(
h));
248 inline void recordKinematicParametrisation(
251 eventFractionCollection,
261 eventFractionCollection, multiplicity, interactionType, cfg.
momentumBins);
262 std::vector<Parametrisation::CumulativeDistribution> distributionsMom =
263 momentumParameters.second;
265 const auto invariantMassParameters =
267 eventFractionCollection, multiplicity, interactionType,
269 std::vector<Parametrisation::CumulativeDistribution> distributionsInvMass =
270 invariantMassParameters.second;
273 if (!distributionsMom.empty() && !distributionsInvMass.empty()) {
274 if (multiplicity > 1) {
277 momentumParameters.first;
279 auto momEigenVal = std::get<0>(esComponentsMom);
280 auto momEigenVec = std::get<1>(esComponentsMom);
281 auto momMean = std::get<2>(esComponentsMom);
282 std::vector<float> momVecVal(momEigenVal.data(),
283 momEigenVal.data() + momEigenVal.size());
284 std::vector<float> momVecVec(momEigenVec.data(),
285 momEigenVec.data() + momEigenVec.size());
286 std::vector<float> momVecMean(momMean.data(),
287 momMean.data() + momMean.size());
288 gDirectory->WriteObject(&momVecVal,
"MomentumEigenvalues");
289 gDirectory->WriteObject(&momVecVec,
"MomentumEigenvectors");
290 gDirectory->WriteObject(&momVecMean,
"MomentumMean");
294 invariantMassParameters.first;
296 auto invMassEigenVal = std::get<0>(esComponentsInvMass);
297 auto invMassEigenVec = std::get<1>(esComponentsInvMass);
298 auto invMassMean = std::get<2>(esComponentsInvMass);
299 std::vector<float> invMassVecVal(
300 invMassEigenVal.data(),
301 invMassEigenVal.data() + invMassEigenVal.size());
302 std::vector<float> invMassVecVec(
303 invMassEigenVec.data(),
304 invMassEigenVec.data() + invMassEigenVec.size());
305 std::vector<float> invMassVecMean(
306 invMassMean.data(), invMassMean.data() + invMassMean.size());
307 gDirectory->WriteObject(&invMassVecVal,
"InvariantMassEigenvalues");
308 gDirectory->WriteObject(&invMassVecVec,
"InvariantMassEigenvectors");
309 gDirectory->WriteObject(&invMassVecMean,
"InvariantMassMean");
312 const auto momDistributions = buildMaps(distributionsMom);
313 const auto invMassDistributions = buildMaps(distributionsInvMass);
318 gDirectory->WriteObject(
322 gDirectory->WriteObject(
323 &momDistributions[i].first,
325 gDirectory->WriteObject(
326 &momDistributions[i].second,
327 (
"MomentumDistributionBinContents_" +
std::to_string(i)).c_str());
331 gDirectory->WriteObject(
332 distributionsInvMass[i],
336 gDirectory->WriteObject(
337 &invMassDistributions[i].first,
338 (
"InvariantMassDistributionBinBorders_" +
std::to_string(i)).c_str());
339 gDirectory->WriteObject(
340 &invMassDistributions[i].second,
345 gDirectory->cd(
"..");
354 :
WriterT(config.inputSimulationProcesses,
355 "RootNuclearInteractionParametersWriter", level),
358 throw std::invalid_argument(
"Missing input collection");
361 throw std::invalid_argument(
"Missing output filename for parameters");
371 if (m_eventFractionCollection.empty()) {
372 return ProcessCode::ABORT;
376 std::lock_guard<std::mutex> lock(m_writeMutex);
379 TFile* tf = TFile::Open(
m_cfg.filePath.c_str(),
m_cfg.fileMode.c_str());
382 std::to_string(m_eventFractionCollection[0].initialParticle.pdg())
385 std::to_string(m_eventFractionCollection[0].initialParticle.pdg())
388 std::to_string(m_eventFractionCollection[0].initialMomentum).c_str());
390 std::to_string(m_eventFractionCollection[0].initialMomentum).c_str());
391 gDirectory->mkdir(
"soft");
392 gDirectory->mkdir(
"hard");
395 ACTS_DEBUG(
"Starting parametrisation of nuclear interaction probability");
396 const auto nuclearInteractionProbability =
398 m_eventFractionCollection,
m_cfg.interactionProbabilityBins);
400 if (
m_cfg.writeOptionalHistograms) {
401 gDirectory->WriteObject(nuclearInteractionProbability,
402 "NuclearInteractionHistogram");
404 const auto mapNIprob =
405 buildMap(nuclearInteractionProbability,
m_cfg.nSimulatedEvents);
406 gDirectory->WriteObject(&mapNIprob.first,
"NuclearInteractionBinBorders");
407 gDirectory->WriteObject(&mapNIprob.second,
"NuclearInteractionBinContents");
408 ACTS_DEBUG(
"Nuclear interaction probability parametrised");
410 ACTS_DEBUG(
"Starting calulcation of probability of interaction type");
416 ACTS_DEBUG(
"Calulcation of probability of interaction type finished");
420 "Starting calulcation of transition probabilities between PDG IDs");
421 const auto pdgIdMap =
423 std::vector<int> branchingPdgIds;
424 std::vector<int> targetPdgIds;
425 std::vector<float> targetPdgProbability;
426 for (
const auto& targetPdgIdMap : pdgIdMap) {
427 for (
const auto& producedPdgIdMap : targetPdgIdMap.second) {
428 branchingPdgIds.push_back(targetPdgIdMap.first);
429 targetPdgIds.push_back(producedPdgIdMap.first);
430 targetPdgProbability.push_back(producedPdgIdMap.second);
434 gDirectory->WriteObject(&branchingPdgIds,
"BranchingPdgIds");
435 gDirectory->WriteObject(&targetPdgIds,
"TargetPdgIds");
436 gDirectory->WriteObject(&targetPdgProbability,
"TargetPdgProbability");
438 "Calulcation of transition probabilities between PDG IDs finished");
441 ACTS_DEBUG(
"Starting parametrisation of multiplicity probabilities");
443 m_eventFractionCollection,
m_cfg.multiplicityMax);
444 ACTS_DEBUG(
"Parametrisation of multiplicity probabilities finished");
446 gDirectory->cd(
"soft");
447 if (
m_cfg.writeOptionalHistograms) {
448 gDirectory->WriteObject(multiplicity.first,
"MultiplicityHistogram");
450 const auto multProbSoft = buildMap(multiplicity.first);
451 gDirectory->WriteObject(&multProbSoft.first,
"MultiplicityBinBorders");
452 gDirectory->WriteObject(&multProbSoft.second,
"MultiplicityBinContents");
453 for (
unsigned int i = 1; i <=
m_cfg.multiplicityMax; i++) {
454 ACTS_DEBUG(
"Starting parametrisation of final state kinematics for soft " +
456 recordKinematicParametrisation(m_eventFractionCollection,
true, i,
m_cfg);
457 ACTS_DEBUG(
"Parametrisation of final state kinematics for soft " +
460 gDirectory->cd(
"../hard");
461 if (
m_cfg.writeOptionalHistograms) {
462 gDirectory->WriteObject(multiplicity.second,
"MultiplicityHistogram");
464 const auto multProbHard = buildMap(multiplicity.second);
465 gDirectory->WriteObject(&multProbHard.first,
"MultiplicityBinBorders");
466 gDirectory->WriteObject(&multProbHard.second,
"MultiplicityBinContents");
468 for (
unsigned int i = 1; i <=
m_cfg.multiplicityMax; i++) {
469 ACTS_DEBUG(
"Starting parametrisation of final state kinematics for hard " +
471 recordKinematicParametrisation(m_eventFractionCollection,
false, i,
m_cfg);
472 ACTS_DEBUG(
"Parametrisation of final state kinematics for hard " +
486 std::vector<detail::NuclearInteractionParametrisation::EventFraction>
488 eventFractions.reserve(event.size());
489 for (
const auto&
e : event) {
490 eventFractions.emplace_back(
e);
493 labelEvents(eventFractions);
495 m_eventFractionCollection.insert(m_eventFractionCollection.end(),
496 eventFractions.begin(),
497 eventFractions.end());