8#include "TClonesArray.h"
9#include "TLorentzVector.h"
10#include "TMCProcess.h"
23#include "EvtGen/EvtGen.hh"
24#include "EvtGenBase/EvtAbsRadCorr.hh"
25#include "EvtGenBase/EvtId.hh"
26#include "EvtGenBase/EvtMTRandomEngine.hh"
27#include "EvtGenBase/EvtPDL.hh"
28#include "EvtGenBase/EvtParticle.hh"
29#include "EvtGenBase/EvtParticleFactory.hh"
30#include "EvtGenBase/EvtRandom.hh"
31#include "EvtGenBase/EvtVector4R.hh"
32#include "EvtGenExternal/EvtExternalGenList.hh"
36 : TVirtualMCDecayer(),
37 fPythia8Decayer(nullptr),
41 fEvtGenProducts(nullptr),
42 fHasEvtGenDecay(kFALSE) {
67 UInt_t seed = gRandom->GetSeed();
70 TPythia8* pythia8 = TPythia8::Instance();
72 pythia8->Pythia8()->readString(Form(
"Random:seed = %u", seed));
73 pythia8->Pythia8()->readString(
"Random:setSeed = on");
74 pythia8->Pythia8()->init();
75 LOG(
debug) <<
"TEvtGenDecayer: Pythia8 RNG seeded with " << seed;
78 EvtRandomEngine* randomEngine =
new EvtMTRandomEngine(seed);
79 EvtRandom::setRandomEngine(randomEngine);
81 LOG(info) <<
"TEvtGenDecayer: Random engine initialized with seed " << seed;
84 std::string photonType(
"gamma");
85 bool useEvtGenRandom(
true);
86 bool convertPythiaCodes(
false);
87 std::string pythiaDir(
"");
89 EvtExternalGenList* externalGenList =
new EvtExternalGenList(
90 convertPythiaCodes, pythiaDir, photonType, useEvtGenRandom);
93 EvtAbsRadCorr* radCorrEngine = externalGenList->getPhotosModel();
95 LOG(info) <<
"TEvtGenDecayer: PHOTOS radiative corrections enabled";
97 LOG(warning) <<
"TEvtGenDecayer: PHOTOS not available, proceeding "
98 "without radiative corrections";
102 std::list<EvtDecayBase*> extraModels = externalGenList->getListOfModels();
106 radCorrEngine, &extraModels, 1,
false);
108 LOG(
debug) <<
"TEvtGenDecayer: EvtGen created with " << EvtPDL::entries()
109 <<
" particle entries";
111 LOG(info) <<
"TEvtGenDecayer: EvtGen initialized with decay file: "
116 <<
"TEvtGenDecayer: No EvtGen files specified, using Pythia8 only";
120 LOG(info) <<
"TEvtGenDecayer initialized - EvtGen: "
135 LOG(debug2) <<
"TEvtGenDecayer::Decay called for PDG " << pdg
136 <<
" (E=" << p->E() <<
", p=" << p->P() <<
")";
140 Bool_t evtGenAvailable = (
fEvtGen !=
nullptr);
142 LOG(debug1) <<
"UseEvtGenForParticle(" << pdg <<
") = " << useEvtGen
143 <<
", EvtGen available = " << evtGenAvailable;
145 if (useEvtGen && evtGenAvailable) {
146 LOG(
debug) <<
"Routing PDG " << pdg <<
" to EvtGen";
149 LOG(
debug) <<
"Routing PDG " << pdg <<
" to Pythia8 fallback";
157 LOG(debug2) <<
"UseEvtGenForParticle: Checking PDG " << pdg
158 <<
" against EvtGen particle list";
161 if (pdg == evtGenPdg) {
162 LOG(debug2) <<
"UseEvtGenForParticle: Match found - PDG " << pdg
163 <<
" should use EvtGen";
168 LOG(warning) <<
"UseEvtGenForParticle: PDG " << pdg
169 <<
" not in EvtGen particle list, falling back to Pythia8";
183 LOG(debug1) <<
"DecayWithEvtGen: Decaying PDG " << pdg <<
" with EvtGen";
187 EvtVector4R p4(p->E(), p->Px(), p->Py(), p->Pz());
190 EvtId evtId = EvtPDL::evtIdFromStdHep(pdg);
193 if (evtId.getId() < 0 ||
194 static_cast<size_t>(evtId.getId()) >= EvtPDL::entries()) {
195 LOG(warning) <<
"TEvtGenDecayer: Invalid EvtId for PDG " << pdg
196 <<
" (EvtId: " << evtId.getId()
197 <<
"), falling back to Pythia8";
203 EvtParticle* parent = EvtParticleFactory::particleFactory(evtId, p4);
207 fEvtGen->generateDecay(parent);
213 <<
"TEvtGenDecayer: EvtGen decay products converted and stored";
216 parent->deleteTree();
218 LOG(warning) <<
"TEvtGenDecayer: Could not create EvtParticle for PDG "
223 }
catch (
const std::exception& e) {
224 LOG(error) <<
"TEvtGenDecayer: EvtGen exception for PDG " << pdg <<
": "
238 int nDaughters = parent->getNDaug();
239 LOG(debug2) <<
"ConvertEvtGenDecay: Converting " << nDaughters
240 <<
" daughter particles";
243 for (
int i = 0; i < nDaughters; i++) {
244 EvtParticle* daughter = parent->getDaug(i);
245 EvtVector4R p4 = daughter->getP4();
246 int pdgId = EvtPDL::getStdHep(daughter->getId());
249 TParticle* particle =
new ((*fEvtGenProducts)[i]) TParticle();
250 particle->SetPdgCode(pdgId);
251 particle->SetMomentum(p4.get(1), p4.get(2), p4.get(3),
253 particle->SetProductionVertex(0, 0, 0, 0);
254 particle->SetStatusCode(1);
256 LOG(debug2) <<
" Daughter " << i <<
": PDG=" << pdgId
257 <<
", E=" << p4.get(0) <<
", px=" << p4.get(1)
258 <<
", py=" << p4.get(2) <<
", pz=" << p4.get(3);
261 LOG(debug1) <<
"ConvertEvtGenDecay: Stored "
268 LOG(debug1) <<
"DecayWithPythia8: Handling PDG " << pdg <<
" with Pythia8";
283 LOG(debug1) <<
"ImportParticles: Returning "
289 for (
int i = 0; i < nParticles; i++) {
290 TParticle* srcParticle =
static_cast<TParticle*
>(
fEvtGenProducts->At(i));
291 new ((*particles)[i]) TParticle(*srcParticle);
299 LOG(debug1) <<
"ImportParticles: Delegating to Pythia8";
320 LOG(info) <<
"TEvtGenDecayer: Added PDG " << pdg <<
" to EvtGen particle list"
std::vector< Int_t > fEvtGenParticles
void ReadDecayTable() override
Int_t ImportParticles(TClonesArray *particles) override
void SetForceDecay(Int_t type) override
void DecayWithPythia8(Int_t pdg, TLorentzVector *p)
void AddEvtGenParticle(Int_t pdg)
void SetEvtGenParticleFile(const char *particleFile)
Float_t GetLifetime(Int_t kf) override
TClonesArray * fEvtGenProducts
void Decay(Int_t pdg, TLorentzVector *p) override
void ForceDecay() override
Float_t GetPartialBranchingRatio(Int_t ipart) override
void ConvertEvtGenDecay(EvtParticle *parent)
void SetEvtGenDecayFile(const char *decayFile)
~TEvtGenDecayer() override
void DecayWithEvtGen(Int_t pdg, TLorentzVector *p)
TPythia8Decayer * fPythia8Decayer
Bool_t UseEvtGenForParticle(Int_t pdg)