Skip to content

Commit e956bae

Browse files
authored
[PWGLF] Appended the injected event in MB event correctly (#2481)
* Appended the injected event in MB correctly * Made phi max pT configurable * Custom phi injected resonance
1 parent 2cc0f9a commit e956bae

3 files changed

Lines changed: 105 additions & 112 deletions

File tree

‎MC/config/PWGLF/ini/GeneratorLF_phiphiInvMass.ini‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[GeneratorExternal]
22
fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/GeneratorLF_phiphi.C
3-
funcName=generatePhiResonanceGun(999999, 0.0, 50.0, -1.0, 1.0, "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg", 3)
3+
funcName=generatePhiResonanceGun(999999, 888888, 0.0, 50.0, 100.0, -1.0, 1.0, "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg", 3)
44

55
[GeneratorPythia8]
66
config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg

‎MC/config/PWGLF/ini/tests/GeneratorLF_phiphiInvMass.C‎

Lines changed: 31 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -76,14 +76,34 @@ int External()
7676
for (int k = phiTrack.getFirstDaughterTrackId(); k <= phiTrack.getLastDaughterTrackId(); ++k)
7777
{
7878
auto grandDauPdg = tracks->at(k).GetPdgCode();
79-
if (grandDauPdg == 321) ++nKPlusFromResonancePhi;
80-
if (grandDauPdg == -321) ++nKMinusFromResonancePhi;
79+
if (grandDauPdg == 321)
80+
++nKPlusFromResonancePhi;
81+
if (grandDauPdg == -321)
82+
++nKMinusFromResonancePhi;
8183
}
8284
}
8385
}
8486
}
8587
}
8688

89+
else if (pdg == 888888)
90+
{
91+
++nDirectInjectedPhi;
92+
hasInjection = true;
93+
94+
if (track.getFirstDaughterTrackId() >= 0)
95+
{
96+
for (int j = track.getFirstDaughterTrackId(); j <= track.getLastDaughterTrackId(); ++j)
97+
{
98+
auto dauPdg = tracks->at(j).GetPdgCode();
99+
if (dauPdg == 321)
100+
++nKPlusFromDirectPhi;
101+
if (dauPdg == -321)
102+
++nKMinusFromDirectPhi;
103+
}
104+
}
105+
}
106+
87107
// 2. Process Phi (333) Mesons
88108
else if (pdg == 333)
89109
{
@@ -96,36 +116,18 @@ int External()
96116
continue;
97117
}
98118

99-
bool isDirectInjected = (motherId < 0);
119+
// Minimum Bias Phi
120+
++nMBPhi;
100121

101-
if (isDirectInjected)
122+
if (track.getFirstDaughterTrackId() >= 0)
102123
{
103-
++nDirectInjectedPhi;
104-
hasInjection = true;
105-
106-
if (track.getFirstDaughterTrackId() >= 0)
124+
for (int j = track.getFirstDaughterTrackId(); j <= track.getLastDaughterTrackId(); ++j)
107125
{
108-
for (int j = track.getFirstDaughterTrackId(); j <= track.getLastDaughterTrackId(); ++j)
109-
{
110-
auto dauPdg = tracks->at(j).GetPdgCode();
111-
if (dauPdg == 321) ++nKPlusFromDirectPhi;
112-
if (dauPdg == -321) ++nKMinusFromDirectPhi;
113-
}
114-
}
115-
}
116-
else
117-
{
118-
// Minimum Bias Phi
119-
++nMBPhi;
120-
121-
if (track.getFirstDaughterTrackId() >= 0)
122-
{
123-
for (int j = track.getFirstDaughterTrackId(); j <= track.getLastDaughterTrackId(); ++j)
124-
{
125-
auto dauPdg = tracks->at(j).GetPdgCode();
126-
if (dauPdg == 321) ++nKPlusFromMBPhi;
127-
if (dauPdg == -321) ++nKMinusFromMBPhi;
128-
}
126+
auto dauPdg = tracks->at(j).GetPdgCode();
127+
if (dauPdg == 321)
128+
++nKPlusFromMBPhi;
129+
if (dauPdg == -321)
130+
++nKMinusFromMBPhi;
129131
}
130132
}
131133
}

‎MC/config/PWGLF/pythia8/GeneratorLF_phiphi.C‎

Lines changed: 73 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
#include "Pythia8/Pythia.h"
77
#include "TRandom3.h"
88
#include "TMath.h"
9-
// #include "TF1.h"
109
#include "TParticle.h"
1110
#include "TSystem.h"
1211
#if __has_include("SimulationDataFormat/MCGenStatus.h")
@@ -19,40 +18,51 @@
1918
#endif
2019
#include <cmath>
2120
#include <string>
21+
#include <vector>
2222
#endif
2323

24-
// Double_t FuncLavy(Double_t *x, Double_t *par)
25-
// {
26-
27-
// Double_t p = (par[0] - 1) * (par[0] - 2) * par[1] * x[0] / (((pow((1 + (((sqrt((par[2] * par[2]) + (x[0] * x[0]))) - par[2]) / (par[0] * par[3]))), par[0]) * (par[0] * par[3] * ((par[0] * par[3]) + (par[2] * (par[0] - 2)))))));
28-
// return (p);
29-
// }
30-
3124
class GeneratorPhiResonance : public o2::eventgen::GeneratorPythia8
3225
{
3326
public:
3427
GeneratorPhiResonance(int resoPDG = 999999,
35-
float ptMin = 0.0, float ptMax = 50.0,
28+
int customPhiPDG = 888888,
29+
float ptMin = 0.0, float ptMax = 50.0, float ptMaxPhi = 100.0,
3630
float yMin = -1.0, float yMax = 1.0,
3731
std::string pythiaCfgMb = "${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_136tev.cfg",
3832
int signalInterval = 3)
39-
: GeneratorPythia8(), mResoPDG(resoPDG), mPtMin(ptMin), mPtMaxPhiPhi(ptMax), mYMin(yMin), mYMax(yMax), mSignalInterval(signalInterval)
33+
: GeneratorPythia8(), mResoPDG(resoPDG), mCustomPhiPDG(customPhiPDG), mPtMin(ptMin), mPtMaxPhiPhi(ptMax), mPtMaxPhi(ptMaxPhi), mYMin(yMin), mYMax(yMax), mSignalInterval(signalInterval)
4034
{
41-
// 1. Initialize Gun Pythia object & define custom resonance
42-
// # id::all = name antiName spinType chargeType colType m0 mWidth mMin mMax tau0
35+
// 1. Define Custom Directly Injected Phi (PDG: 888888) with mass, width, and decay to kaons
36+
std::string createCustomPhi = std::to_string(mCustomPhiPDG) + ":new = custom_phi custom_phi 3 0 0 1.019461 0.004249 0.980 1.100 0.0";
37+
std::string customPhiMayDecay = std::to_string(mCustomPhiPDG) + ":mayDecay = on";
38+
std::string addPhiDecayKPlusKMinus = std::to_string(mCustomPhiPDG) + ":addChannel = 1 0.492 0 321 -321";
39+
40+
// 2. Define Custom Signal Resonance (PDG: 999999) decay into standard Phis (333 333)
4341
std::string createReso = std::to_string(mResoPDG) + ":new = f2_Custom void 5 0 0 2.714 0.012 2.05 3.50 0.0";
44-
mPythiaGun.readString(createReso);
45-
mPythiaGun.readString(std::to_string(mResoPDG) + ":mayDecay = on");
46-
// id:addChannel = onMode bRatio meMode product1 product2, (onMode = 1: allow decay, bRatio = branching ratio, meMode = matrix element mode where 0 is isotropic decay)
47-
std::string addDecay = std::to_string(mResoPDG) + ":addChannel = 1 1.0 0 333 333";
48-
mPythiaGun.readString(addDecay);
42+
std::string resoMayDecay = std::to_string(mResoPDG) + ":mayDecay = on";
43+
std::string addResoDecay = std::to_string(mResoPDG) + ":addChannel = 1 1.0 0 333 333";
44+
45+
// Helper lambda to load custom particle definitions across ALL Pythia engines
46+
auto applyCustomParticles = [&](Pythia8::Pythia &pythiaInst)
47+
{
48+
pythiaInst.readString(createCustomPhi);
49+
pythiaInst.readString(customPhiMayDecay);
50+
pythiaInst.readString(addPhiDecayKPlusKMinus);
51+
pythiaInst.readString(createReso);
52+
pythiaInst.readString(resoMayDecay);
53+
pythiaInst.readString(addResoDecay);
54+
};
55+
56+
// 1: Apply particle definitions to mPythia, mPythiaGun, and pythiaObjectMinimumBias
57+
applyCustomParticles(mPythia);
58+
applyCustomParticles(mPythiaGun);
4959

5060
mPythiaGun.readString("ProcessLevel:all off");
5161
mPythiaGun.readString("Random:setSeed = on");
5262
mPythiaGun.readString("Random:seed = " + std::to_string(1 + gRandom->Integer(900000000)));
5363
mPythiaGun.init();
5464

55-
// 2. Initialize Minimum Bias Pythia Engine
65+
// 3. Initialize Minimum Bias Pythia Engine
5666
if (pythiaCfgMb.empty())
5767
{
5868
auto &param = o2::eventgen::GeneratorPythia8Param::Instance();
@@ -67,25 +77,8 @@ public:
6777
pythiaObjectMinimumBias.readString("Random:setSeed = on");
6878
pythiaObjectMinimumBias.readString("Random:seed = " + std::to_string(1 + gRandom->Integer(900000000)));
6979

70-
// Add custom particle definition to MB instance so particle table matches
71-
pythiaObjectMinimumBias.readString(createReso);
72-
pythiaObjectMinimumBias.readString(std::to_string(mResoPDG) + ":mayDecay = on");
73-
pythiaObjectMinimumBias.readString(addDecay);
74-
80+
applyCustomParticles(pythiaObjectMinimumBias);
7581
pythiaObjectMinimumBias.init();
76-
77-
// // Thermal pT distribution for phi-phi resonance
78-
// mThermal = new TF1("mThermal", "x*sqrt(x*x+[0]*[0])*exp(-sqrt(x*x+[0]*[0])/[1])", mPtMin, mPtMaxPhiPhi);
79-
80-
// // Lévy-Tsallis pT distribution for direct phi
81-
// mLevyTsallis = new TF1("mLevyTsallis", FuncLavy, mPtMin, 100.0, 4);
82-
83-
// mLevyTsallis->SetParameters(
84-
// 7.60279, // n
85-
// 0.0374237, // dN/dy
86-
// 1.01946, // mass
87-
// 0.338379 // T
88-
// );
8982
}
9083

9184
Bool_t generateEvent() override
@@ -99,69 +92,77 @@ public:
9992
mbOK = pythiaObjectMinimumBias.next();
10093
}
10194

102-
// Copy MB event into mPythia
103-
mPythia.event = pythiaObjectMinimumBias.event;
95+
// 2: Copy MB event using exact pointer binding from generator_pythia8_LF_rapidity_width.C
96+
copyMinimumBiasEventForInjection();
10497

10598
// 2. Clear Gun event container
10699
mPythiaGun.event.reset();
107100

108101
// 3. Inject Signal Gun Particles into mPythiaGun
109102
if (mEventCounter % mSignalInterval == 0)
110103
{
111-
// Theramal distribution
104+
// Resonant signal -> Decays into 333 333 (Standard Phis)
112105
injectParticle(mResoPDG, 1, true);
113106
}
114107
else
115108
{
116-
// From published
117-
injectParticle(333, 2, false);
109+
// Directly injected uncorrelated Phi -> Uses Custom PDG 888888
110+
injectParticle(mCustomPhiPDG, 2, false);
118111
}
119112

120113
// 4. Force Decay of injected particles using Pythia's Decayer
121-
for (int i = 1; i < mPythiaGun.event.size(); ++i)
122-
{
123-
if (mPythiaGun.event[i].status() > 0)
124-
{ // Active injected particles
125-
mPythiaGun.particleData.mayDecay(mPythiaGun.event[i].id(), true);
126-
mPythiaGun.moreDecays();
127-
}
128-
}
114+
mPythiaGun.moreDecays();
115+
mPythiaGun.next();
129116

130-
// 5. Merge mPythiaGun event into mPythia.event
117+
// 3: Index Mapping during Event Merging
131118
int offset = mPythia.event.size();
119+
std::vector<int> indexMap(mPythiaGun.event.size(), 0);
132120

133121
for (int i = 1; i < mPythiaGun.event.size(); ++i)
134-
{ // Skip system particle 0
122+
{
123+
indexMap[i] = mPythia.event.size();
135124
Pythia8::Particle p = mPythiaGun.event[i];
125+
mPythia.event.append(p);
126+
}
136127

137-
// Adjust history indices accurately
138-
int mother1 = (p.mother1() > 0) ? p.mother1() + offset - 1 : p.mother1();
139-
int mother2 = (p.mother2() > 0) ? p.mother2() + offset - 1 : p.mother2();
140-
int daughter1 = (p.daughter1() > 0) ? p.daughter1() + offset - 1 : p.daughter1();
141-
int daughter2 = (p.daughter2() > 0) ? p.daughter2() + offset - 1 : p.daughter2();
128+
// Re-link mother and daughter index relationships accurately
129+
for (int i = 1; i < mPythiaGun.event.size(); ++i)
130+
{
131+
int newIdx = indexMap[i];
132+
Pythia8::Particle &p = mPythia.event[newIdx];
142133

143-
p.mothers(mother1, mother2);
144-
p.daughters(daughter1, daughter2);
134+
int m1 = p.mother1();
135+
int m2 = p.mother2();
136+
int d1 = p.daughter1();
137+
int d2 = p.daughter2();
145138

146-
mPythia.event.append(p);
139+
p.mothers((m1 > 0 && m1 < (int)indexMap.size()) ? indexMap[m1] : 0,
140+
(m2 > 0 && m2 < (int)indexMap.size()) ? indexMap[m2] : 0);
141+
142+
p.daughters((d1 > 0 && d1 < (int)indexMap.size()) ? indexMap[d1] : 0,
143+
(d2 > 0 && d2 < (int)indexMap.size()) ? indexMap[d2] : 0);
147144
}
148145

149-
// 6. CRITICAL: Restore Pythia particleData pointers for O2 exporter
146+
// 4: Restore Pythia particleData pointers for O2 exporter
150147
mPythia.event.restorePtrs();
151148

152-
// 7. Invoke base generator hooks to sync O2 event record
153-
// return GeneratorPythia8::generateEvent();
154-
return true; // Skip base generator processing to avoid overwriting injected particles
149+
return true;
155150
}
156151

157152
private:
153+
void copyMinimumBiasEventForInjection()
154+
{
155+
mPythia.event = pythiaObjectMinimumBias.event;
156+
mPythia.event.init("Minimum-bias event with injected particles", &mPythia.particleData);
157+
mPythia.event.restorePtrs();
158+
}
159+
158160
void injectParticle(int pdg, int nParticles, bool thermalPt)
159161
{
160162
const double phiMass = 1.019461;
161163

162164
for (int i = 0; i < nParticles; ++i)
163165
{
164-
// const double pt = gRandom->Uniform(mPtMin, mPtMaxPhiPhi);
165166
const double y = gRandom->Uniform(mYMin, mYMax);
166167
const double phi = gRandom->Uniform(0, TMath::TwoPi());
167168

@@ -175,26 +176,17 @@ private:
175176
}
176177
else
177178
{
178-
mass = mPythiaGun.particleData.mSel(pdg);
179+
mass = mPythiaGun.particleData.mSel(333); // Use standard phi mass for directly injected custom phi
179180
}
180181

181182
double pt;
182-
183183
if (thermalPt)
184184
{
185-
// const double T = 0.160;
186-
187-
// mThermal->SetParameter(0, mass);
188-
// mThermal->SetParameter(1, T);
189-
190-
// pt = mThermal->GetRandom();
191-
192-
pt = gRandom->Uniform(mPtMin, mPtMaxPhiPhi); // Falling back to flat pT due to low statistics in high pT
185+
pt = gRandom->Uniform(mPtMin, mPtMaxPhiPhi);
193186
}
194187
else
195188
{
196-
// pt = mLevyTsallis->GetRandom();
197-
pt = gRandom->Uniform(mPtMin, 100.0); // Falling back to flat pT due to low statistics in high pT
189+
pt = gRandom->Uniform(mPtMin, mPtMaxPhi);
198190
}
199191

200192
const double px = pt * std::cos(phi);
@@ -215,24 +207,23 @@ private:
215207
particle.yProd(0.);
216208
particle.zProd(0.);
217209

210+
mPythiaGun.particleData.mayDecay(pdg, true);
218211
mPythiaGun.event.append(particle);
219212
}
220213
}
221214

222215
int mEventCounter = 0;
223216
int mResoPDG;
217+
int mCustomPhiPDG;
224218
int mSignalInterval;
225-
float mPtMin, mPtMaxPhiPhi, mYMin, mYMax;
219+
float mPtMin, mPtMaxPhiPhi, mPtMaxPhi, mYMin, mYMax;
226220

227221
Pythia8::Pythia mPythiaGun;
228222
Pythia8::Pythia pythiaObjectMinimumBias;
229-
230-
// TF1 *mThermal;
231-
// TF1 *mLevyTsallis;
232223
};
233224

234225
/// Entry point for o2-sim
235-
FairGenerator *generatePhiResonanceGun(int resoPDG = 999999, float ptMin = 0.0, float ptMax = 50.0, float yMin = -1.0, float yMax = 1.0, std::string pythiaCfgMb = "", int signalInterval = 3)
226+
FairGenerator *generatePhiResonanceGun(int resoPDG = 999999, int customPhiPDG = 888888, float ptMin = 0.0, float ptMax = 50.0, float ptMaxPhi = 100.0, float yMin = -1.0, float yMax = 1.0, std::string pythiaCfgMb = "", int signalInterval = 3)
236227
{
237-
return new GeneratorPhiResonance(resoPDG, ptMin, ptMax, yMin, yMax, pythiaCfgMb, signalInterval);
228+
return new GeneratorPhiResonance(resoPDG, customPhiPDG, ptMin, ptMax, ptMaxPhi, yMin, yMax, pythiaCfgMb, signalInterval);
238229
}

0 commit comments

Comments
 (0)