Skip to content

Commit b543836

Browse files
authored
Add Lstar gun generator, ini and config (#2495)
1 parent 1fd2fb7 commit b543836

4 files changed

Lines changed: 329 additions & 0 deletions

File tree

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[GeneratorExternal]
2+
fileName=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator_pythia8_Lstar.C
3+
funcName=generator_Lstar()
4+
5+
[GeneratorPythia8]
6+
config=${O2DPG_MC_CONFIG_ROOT}/MC/config/PWGLF/pythia8/generator/pythia8_inel_forceLStar.cfg
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
int External()
2+
{
3+
std::string path{"o2sim_Kine.root"};
4+
const int pdgMother = 3124; // Lambda(1520)0 (sign randomized by the generator)
5+
6+
TFile file(path.c_str(), "READ");
7+
if (file.IsZombie()) {
8+
std::cerr << "Cannot open ROOT file " << path << "\n";
9+
return 1;
10+
}
11+
auto tree = (TTree *)file.Get("o2sim");
12+
if (!tree) {
13+
std::cerr << "Cannot find tree o2sim in file " << path << "\n";
14+
return 1;
15+
}
16+
std::vector<o2::MCTrack> *tracks{};
17+
tree->SetBranchAddress("MCTrack", &tracks);
18+
19+
const auto nEvents = tree->GetEntries();
20+
int nMother = 0;
21+
int nNotDecayed = 0;
22+
int nBadDecay = 0; // mothers not decaying exactly to Lambda + gamma
23+
int nEventsWrongCount = 0; // events without exactly one injected mother
24+
25+
for (int i = 0; i < nEvents; i++) {
26+
tree->GetEntry(i);
27+
int nInEvent = 0;
28+
for (auto &track : *tracks) {
29+
const int pdg = track.GetPdgCode();
30+
if (std::abs(pdg) != pdgMother) {
31+
continue;
32+
}
33+
nInEvent++;
34+
nMother++;
35+
36+
if (track.getFirstDaughterTrackId() < 0) {
37+
nNotDecayed++;
38+
continue;
39+
}
40+
const int expectedLambda = (pdg > 0) ? 3122 : -3122;
41+
int nLambda = 0, nGamma = 0, nDau = 0;
42+
for (int j = track.getFirstDaughterTrackId(); j <= track.getLastDaughterTrackId(); ++j) {
43+
const int pdgDau = tracks->at(j).GetPdgCode();
44+
nDau++;
45+
if (pdgDau == expectedLambda) nLambda++;
46+
if (pdgDau == 22) nGamma++;
47+
}
48+
if (nDau != 2 || nLambda != 1 || nGamma != 1) {
49+
nBadDecay++;
50+
std::cerr << "Unexpected decay of " << pdg << " (" << nDau << " daughters)\n";
51+
}
52+
}
53+
if (nInEvent != 1) {
54+
nEventsWrongCount++;
55+
}
56+
}
57+
58+
std::cout << "--------------------------------\n";
59+
std::cout << "# Events: " << nEvents << "\n";
60+
std::cout << "# Lambda(1520) + anti: " << nMother << "\n";
61+
std::cout << "# not decayed: " << nNotDecayed << "\n";
62+
std::cout << "# unexpected decays: " << nBadDecay << "\n";
63+
std::cout << "# events with != 1 mother: " << nEventsWrongCount << "\n";
64+
std::cout << "--------------------------------\n";
65+
66+
if (nEventsWrongCount > 0) {
67+
std::cerr << "Each event must contain exactly one injected Lambda(1520)\n";
68+
return 1;
69+
}
70+
if (nNotDecayed > 0 || nBadDecay > 0) {
71+
std::cerr << "Lambda(1520) must always decay to Lambda + gamma\n";
72+
return 1;
73+
}
74+
return 0;
75+
}
76+
77+
void GeneratorLF_Strangeness_ppLStar() { External(); }
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
### beams
2+
Beams:idA 2212 # proton
3+
Beams:idB 2212 # proton
4+
Beams:eCM 13600. # GeV
5+
6+
### processes
7+
SoftQCD:inelastic on # all inelastic processes
8+
9+
### decays
10+
ParticleDecays:limitTau0 on
11+
ParticleDecays:tau0Max 10.
12+
13+
### Add Lambda* decay 3124 102134
14+
# id::all = name antiName spinType chargeType colType m0 mWidth mMin mMax tau0
15+
3124:all = Lambda1520 Lambda1520bar 4 0 0 1.51950 0.01560 1.47 1.60 0
16+
17+
### add Resonance decays absent in PYTHIA8 decay table and set BRs from PDG for other
18+
3124:oneChannel = 1 1.000 0 3122 22
19+
3124:onMode = off
20+
3124:onIfMatch = 3122 22
Lines changed: 226 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,226 @@
1+
2+
#include "Pythia8/Pythia.h"
3+
#include "Pythia8/HeavyIons.h"
4+
#include "FairGenerator.h"
5+
#include "FairPrimaryGenerator.h"
6+
#include "Generators/GeneratorPythia8.h"
7+
#include "TF1.h"
8+
#include "TRandom3.h"
9+
//#include "TParticlePDG.h"
10+
//#include "TDatabasePDG.h"
11+
12+
#include <map>
13+
#include <unordered_set>
14+
15+
class GeneratorPythia8ExtraStrangeness : public o2::eventgen::GeneratorPythia8
16+
{
17+
public:
18+
/// default constructor
19+
GeneratorPythia8ExtraStrangeness() = default;
20+
21+
/// Constructor
22+
GeneratorPythia8ExtraStrangeness(int input_pdg)
23+
{
24+
genMinPt=0.0;
25+
genMaxPt=12.0;
26+
genminY=-1.5;
27+
genmaxY=1.5;
28+
genminEta=-1.5;
29+
genmaxEta=1.5;
30+
31+
pdg=input_pdg;
32+
m = 0;
33+
E=0;
34+
px=0;
35+
py=0;
36+
pz=0;
37+
p=0;
38+
y=0;
39+
eta=0;
40+
xProd=0.; yProd=0.; zProd=0.;
41+
42+
fLVHelper = std::make_unique<TLorentzVector>();
43+
44+
randomizePDGsign = false;
45+
46+
fSpectra = makeLevySpectrum("fSpectra", genMinPt, genMaxPt, mPythia.particleData.m0(input_pdg), 0.30, 7.);
47+
}
48+
49+
/// randomize the PDG code sign of core particle
50+
void setRandomizePDGsign() { randomizePDGsign = true; }
51+
52+
Double_t y2eta(Double_t pt, Double_t mass, Double_t y){
53+
Double_t mt = TMath::Sqrt(mass * mass + pt * pt);
54+
return TMath::ASinH(mt / pt * TMath::SinH(y));
55+
}
56+
57+
58+
/// set mass
59+
double sampleMass(int input_pdg)
60+
{
61+
auto& pd = mPythia.particleData;
62+
const double mass = pd.mWidth(input_pdg) > 0. ? pd.mSel(input_pdg) : pd.m0(input_pdg);
63+
return mass;
64+
}
65+
66+
static double myLevyPt(double* pt, double* par)
67+
{
68+
const double lMass = par[0];
69+
const double ldNdy = par[1];
70+
const double lTemp = par[2];
71+
const double lPower = par[3];
72+
73+
const double lBigCoef = ((lPower-1)*(lPower-2)) / (lPower*lTemp*(lPower*lTemp+lMass*(lPower-2)));
74+
const double lInPower = 1 + (TMath::Sqrt(pt[0]*pt[0]+lMass*lMass)-lMass) / (lPower*lTemp);
75+
76+
return ldNdy * pt[0] * lBigCoef * TMath::Power(lInPower, -lPower);
77+
}
78+
79+
/// build a Levy-Tsallis pT spectrum for a particle of given mass
80+
TF1* makeLevySpectrum(const char* name, double ptMin, double ptMax, double mass, double T, double n, double norm = 1.)
81+
{
82+
TF1* f = new TF1(name, myLevyPt, ptMin, ptMax, 4);
83+
f->SetParNames("mass", "norm", "T", "n");
84+
f->FixParameter(0, mass); // mass [GeV/c^2]
85+
f->SetParameter(1, norm); // normalization (irrelevant for GetRandom)
86+
f->SetParameter(2, T); // slope parameter [GeV]
87+
f->SetParameter(3, n); // power-law exponent
88+
f->SetNpx(1000);
89+
return f;
90+
}
91+
92+
/// set 4-momentum
93+
void set4momentum(double input_px, double input_py, double input_pz){
94+
px = input_px;
95+
py = input_py;
96+
pz = input_pz;
97+
E = sqrt( m*m+px*px+py*py+pz*pz );
98+
fourMomentum.px(px);
99+
fourMomentum.py(py);
100+
fourMomentum.pz(pz);
101+
fourMomentum.e(E);
102+
p = sqrt( px*px+py*py+pz*pz );
103+
y = 0.5*log( (E+pz)/(E-pz) );
104+
eta = 0.5*log( (p+pz)/(p-pz) );
105+
}
106+
107+
108+
//_________________________________________________________________________________
109+
/// generate uniform eta and uniform momentum
110+
void genSpectraMomentumEta(double minPt, double maxPt, double minY, double maxY){
111+
// random generator
112+
std::unique_ptr<TRandom3> ranGenerator { new TRandom3() };
113+
ranGenerator->SetSeed(0);
114+
115+
// generate transverse momentum
116+
//const double gen_pT = ranGenerator->Uniform(minPt, maxPt);
117+
const double gen_pT = fSpectra->GetRandom(minPt,maxPt);
118+
119+
//Actually could be something else without loss of generality but okay
120+
const double gen_phi = ranGenerator->Uniform(0,2*TMath::Pi());
121+
122+
// sample flat in rapidity, calculate eta
123+
Double_t gen_Y=10, gen_eta=10;
124+
125+
while( gen_eta>genmaxEta || gen_eta<genminEta ){
126+
gen_Y = ranGenerator->Uniform(minY,maxY);
127+
gen_eta = y2eta(gen_pT, m, gen_Y);
128+
}
129+
130+
fLVHelper->SetPtEtaPhiM(gen_pT, gen_eta, gen_phi, m);
131+
set4momentum(fLVHelper->Px(),fLVHelper->Py(),fLVHelper->Pz());
132+
}
133+
134+
//__________________________________________________________________
135+
Pythia8::Particle createParticle(){
136+
//std::cout << "createParticle() mass " << m << " pdgCode " << pdg << std::endl;
137+
Pythia8::Particle myparticle;
138+
myparticle.id(pdg);
139+
myparticle.status(11);
140+
myparticle.px(px);
141+
myparticle.py(py);
142+
myparticle.pz(pz);
143+
myparticle.e(E);
144+
myparticle.m(m);
145+
myparticle.xProd(xProd);
146+
myparticle.yProd(yProd);
147+
myparticle.zProd(zProd);
148+
149+
return myparticle;
150+
}
151+
152+
//__________________________________________________________________
153+
int randomizeSign()
154+
{
155+
std::unique_ptr<TRandom3> gen_random{new TRandom3(0)};
156+
const float n = gen_random->Uniform(-1, 1);
157+
158+
return n / abs(n);
159+
}
160+
161+
//__________________________________________________________________
162+
Bool_t generateEvent() override {
163+
// Generate PYTHIA event
164+
165+
mPythia.event.reset();
166+
167+
/// go to next Pythia event
168+
Bool_t lPythiaOK = kFALSE;
169+
while (!lPythiaOK){
170+
lPythiaOK = mPythia.next();
171+
}
172+
173+
/// reset event
174+
//mPythia.event.reset();
175+
176+
/// create and append the desired particle
177+
m = sampleMass(pdg);
178+
genSpectraMomentumEta(genMinPt, genMaxPt, genminY, genmaxY);
179+
180+
if (randomizePDGsign)
181+
pdg *= randomizeSign();
182+
183+
Pythia8::Particle particle = createParticle();
184+
mPythia.event.append(particle);
185+
mPythia.moreDecays();
186+
187+
return true;
188+
}
189+
190+
private:
191+
192+
double genMinPt; /// minimum 3-momentum for generated particles
193+
double genMaxPt; /// maximum 3-momentum for generated particles
194+
double genminY; /// minimum pseudorapidity for generated particles
195+
double genmaxY; /// maximum pseudorapidity for generated particles
196+
double genminEta;
197+
double genmaxEta;
198+
199+
Pythia8::Vec4 fourMomentum; /// four-momentum (px,py,pz,E)
200+
//std::unique_ptr<o2::eventgen::FlowMapper> lutGen;
201+
202+
double E; /// energy: sqrt( m*m+px*px+py*py+pz*pz ) [GeV/c]
203+
double m; /// particle mass [GeV/c^2]
204+
int pdg; /// particle pdg code
205+
double px; /// x-component momentum [GeV/c]
206+
double py; /// y-component momentum [GeV/c]
207+
double pz; /// z-component momentum [GeV/c]
208+
double p; /// momentum
209+
double y; /// rapidity
210+
double eta; /// pseudorapidity
211+
double xProd; /// x-coordinate position production vertex [cm]
212+
double yProd; /// y-coordinate position production vertex [cm]
213+
double zProd; /// z-coordinate position production vertex [cm]
214+
215+
bool randomizePDGsign; /// bool to randomize the PDG code of the core particle
216+
217+
TF1 *fSpectra = nullptr; /// TF1 to store more realistic shape of spectrum
218+
std::unique_ptr<TLorentzVector> fLVHelper;
219+
};
220+
221+
FairGenerator *generator_Lstar()
222+
{
223+
auto myGen = new GeneratorPythia8ExtraStrangeness(3124);
224+
myGen->setRandomizePDGsign(); // randomization of PDG switched on
225+
return myGen;
226+
}

0 commit comments

Comments
 (0)