Skip to content

Commit 79ef45a

Browse files
committed
Add option to modify the decay table in the otf decayer
1 parent 89b39d7 commit 79ef45a

2 files changed

Lines changed: 90 additions & 7 deletions

File tree

‎ALICE3/Core/Decayer.h‎

Lines changed: 83 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,13 @@
1919
#ifndef ALICE3_CORE_DECAYER_H_
2020
#define ALICE3_CORE_DECAYER_H_
2121

22+
#include "ALICE3/Core/ConfigurationParser.h"
2223
#include "ALICE3/Core/OTFParticle.h"
2324
#include "ALICE3/Core/TrackUtilities.h"
2425

26+
#include <CCDB/BasicCCDBManager.h>
2527
#include <CommonConstants/PhysicsConstants.h>
28+
#include <Framework/Logger.h>
2629
#include <MathUtils/Primitive2D.h>
2730
#include <ReconstructionDataFormats/Track.h>
2831

@@ -34,6 +37,10 @@
3437
#include <array>
3538
#include <cmath>
3639
#include <cstddef>
40+
#include <map>
41+
#include <sstream>
42+
#include <string>
43+
#include <unordered_map>
3744
#include <vector>
3845

3946
namespace o2::upgrade
@@ -45,6 +52,53 @@ class Decayer
4552
// Default constructor
4653
Decayer() = default;
4754

55+
static constexpr double BranchingRatioTolerance = 0.01;
56+
57+
struct DecayChannel {
58+
double branchingRatio{};
59+
std::vector<int> daughters;
60+
};
61+
62+
template <typename TDatabase>
63+
void loadDecayTable(const std::string& path, const TDatabase& pdgDB, o2::ccdb::BasicCCDBManager* ccdb = nullptr)
64+
{
65+
std::string fileName = o2::fastsim::ConfigurationParser::accessFile(path, "./.ALICE3/Configuration/", ccdb);
66+
std::vector<std::string> mothers;
67+
const std::map<std::string, std::map<std::string, std::string>> config = o2::fastsim::ConfigurationParser::parseTEnvConfiguration(fileName, mothers);
68+
69+
mDecayTable.clear();
70+
for (const auto& [motherName, channels] : config) {
71+
const int motherPdg = std::stoi(motherName);
72+
if (!pdgDB->GetParticle(motherPdg)) {
73+
LOG(fatal) << "Decay table: unknown mother PDG code " << motherPdg;
74+
}
75+
for (const auto& [channelName, value] : channels) {
76+
DecayChannel channel;
77+
std::istringstream stream(value);
78+
stream >> channel.branchingRatio;
79+
int daughterPdg{};
80+
while (stream >> daughterPdg) {
81+
if (!pdgDB->GetParticle(daughterPdg)) {
82+
LOG(fatal) << "Decay table: unknown daughter PDG code " << daughterPdg << " in " << motherName << "." << channelName;
83+
}
84+
channel.daughters.push_back(daughterPdg);
85+
}
86+
if (!stream.eof() || channel.branchingRatio <= 0. || channel.daughters.size() < 2) {
87+
LOG(fatal) << "Decay table: invalid channel " << motherName << "." << channelName << ": \"" << value << "\"";
88+
}
89+
mDecayTable[motherPdg].push_back(channel);
90+
}
91+
double brTotal = 0.;
92+
for (const auto& channel : mDecayTable[motherPdg]) {
93+
brTotal += channel.branchingRatio;
94+
}
95+
if (std::abs(brTotal - 1.) > BranchingRatioTolerance) {
96+
LOG(fatal) << "Decay table: branching ratios of PDG " << motherPdg << " sum to " << brTotal << ", expected 1 within " << BranchingRatioTolerance;
97+
}
98+
LOG(info) << "Decay table: overriding " << mDecayTable[motherPdg].size() << " decay channel(s) of PDG " << motherPdg;
99+
}
100+
}
101+
48102
template <typename TDatabase>
49103
std::vector<o2::upgrade::OTFParticle> decayParticle(const OTFParticle& particle, const TDatabase& pdgDB)
50104
{
@@ -69,21 +123,22 @@ class Decayer
69123
py = particle.py() * std::cos(mTheta) + particle.px() * std::sin(mTheta);
70124
}
71125

72-
double brTotal = 0.;
73126
e = std::sqrt(mass * mass + px * px + py * py + particle.pz() * particle.pz());
74-
for (int ch = 0; ch < particleInfo->NDecayChannels(); ++ch) {
75-
brTotal += particleInfo->DecayChannel(ch)->BranchingRatio();
127+
const std::vector<DecayChannel> channels = getDecayChannels(particle.pdgCode(), particleInfo);
128+
129+
double brTotal = 0.;
130+
for (const auto& channel : channels) {
131+
brTotal += channel.branchingRatio;
76132
}
77133

78134
double brSum = 0.;
79135
std::vector<double> dauMasses;
80136
std::vector<int> pdgCodesDaughters;
81137
const double randomChannel = mRand3.Uniform(0., brTotal);
82-
for (int ch = 0; ch < particleInfo->NDecayChannels(); ++ch) {
83-
brSum += particleInfo->DecayChannel(ch)->BranchingRatio();
138+
for (const auto& channel : channels) {
139+
brSum += channel.branchingRatio;
84140
if (randomChannel < brSum) {
85-
for (int dau = 0; dau < particleInfo->DecayChannel(ch)->NDaughters(); ++dau) {
86-
const int pdgDau = particleInfo->DecayChannel(ch)->DaughterPdgCode(dau);
141+
for (const int pdgDau : channel.daughters) {
87142
pdgCodesDaughters.push_back(pdgDau);
88143
const auto& dauInfo = pdgDB->GetParticle(pdgDau);
89144
dauMasses.push_back(dauInfo->Mass());
@@ -166,6 +221,27 @@ class Decayer
166221
[[nodiscard]] float getDecayRadius() const { return static_cast<float>(std::hypot(mVx, mVy)); }
167222

168223
private:
224+
/// Decay channels from the loaded decay table if the mother is listed there, otherwise from TDatabasePDG
225+
template <typename TParticleInfo>
226+
std::vector<DecayChannel> getDecayChannels(const int pdgCode, const TParticleInfo& particleInfo) const
227+
{
228+
if (const auto it = mDecayTable.find(pdgCode); it != mDecayTable.end()) {
229+
return it->second;
230+
}
231+
232+
std::vector<DecayChannel> channels;
233+
for (int ch = 0; ch < particleInfo->NDecayChannels(); ++ch) {
234+
DecayChannel channel;
235+
channel.branchingRatio = particleInfo->DecayChannel(ch)->BranchingRatio();
236+
for (int dau = 0; dau < particleInfo->DecayChannel(ch)->NDaughters(); ++dau) {
237+
channel.daughters.push_back(particleInfo->DecayChannel(ch)->DaughterPdgCode(dau));
238+
}
239+
channels.push_back(channel);
240+
}
241+
return channels;
242+
}
243+
244+
std::unordered_map<int, std::vector<DecayChannel>> mDecayTable;
169245
double mBz{20.}; // kG
170246
double mVx{-1.}, mVy{-1.}, mVz{-1.};
171247
double mTheta{};

‎ALICE3/TableProducer/OTF/onTheFlyDecayer.cxx‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "ALICE3/Core/TrackUtilities.h"
2121
#include "ALICE3/DataModel/tracksAlice3.h"
2222

23+
#include <CCDB/BasicCCDBManager.h>
2324
#include <CommonConstants/PhysicsConstants.h>
2425
#include <Framework/AnalysisDataModel.h>
2526
#include <Framework/AnalysisHelpers.h>
@@ -92,10 +93,12 @@ struct OnTheFlyDecayer {
9293

9394
o2::upgrade::Decayer decayer;
9495
Service<o2::framework::O2DatabasePDG> pdgDB{};
96+
Service<o2::ccdb::BasicCCDBManager> ccdb{};
9597
HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject};
9698

9799
Configurable<int> seed{"seed", 0, "Set seed for particle decayer"};
98100
Configurable<float> magneticField{"magneticField", 20., "Magnetic field (kG)"};
101+
Configurable<std::string> decayTable{"decayTable", "", "Decay table overriding the TDatabasePDG decay channels of the listed particles (local path or ccdb:<path>), empty to disable"};
99102
Configurable<LabeledArray<int>> enabledDecays{"enabledDecays",
100103
{DefaultParameters[0].data(), NumDecays, NumParameters, particleNames, parameterNames},
101104
"Enable option for particle to be decayed: 0 - no, 1 - yes"};
@@ -111,6 +114,10 @@ struct OnTheFlyDecayer {
111114
LOG(info) << " --- Using magnetic field: " << magneticField;
112115
decayer.setSeed(seed);
113116
decayer.setBField(magneticField);
117+
if (!decayTable.value.empty()) {
118+
LOG(info) << " --- Using decay table: " << decayTable.value;
119+
decayer.loadDecayTable(decayTable.value, pdgDB, ccdb.operator->());
120+
}
114121
for (int i = 0; i < NumDecays; ++i) {
115122
if (enabledDecays->get(particleNames[i].c_str(), "enable") != 0) {
116123
LOG(info) << " --- Decay enabled: " << pdgCodes[i];

0 commit comments

Comments
 (0)