Skip to content

Commit de6b301

Browse files
author
Mattia Faggin
committed
First commit of Pythia8 gun event generator
Event generator based on Pythia8 that injects only the desired particles in the event. Files: 1) generator_pythia8_gun.C: it cotains the class with the generator and the custo functions to be called from the *.ini file; 2) config_custom_OmegaC.cfg: custom settings for OmegaC generations. In this version: decay forced to Omega-pion; ctau set to 80 micron; 3) configOmegaAnd20Pions_randomCharge.ini: example of config file used to call the gun. The function produces events containing a Omega (with random sign) plus 10 pi+ and 10 pi-. The function is defined inside the file in point 1).
1 parent 52692fd commit de6b301

File tree

3 files changed

+296
-0
lines changed

3 files changed

+296
-0
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[GeneratorExternal]
2+
fileName=${O2DPG_ROOT}/MC/config/PWGHF/pythia8_gun/generator_pythia8_gun.C
3+
funcName=generateOmegaAndPions_RandomCharge(20)
4+
5+
[GeneratorPythia8]
6+
config=${O2DPG_ROOT}/MC/config/PWGHF/pythia8_gun/config_custom_OmegaC.cfg
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
### Omega_c
2+
#4332:all = Omega_c0 Omega_cbar0 2 0 0 2.69520 0. 0. 0. 10
3+
4+
ProcessLevel:all = off
5+
6+
### changing the ctau value in mm/c
7+
4332:tau0=0.08000000000
8+
9+
### add OmegaC decay absent in PYTHIA8 decay table
10+
4332:addChannel = 1 0.0001 0 3334 211
11+
12+
### force the OmegaC to decay in the Omega_c -> Omega pi channel
13+
4332:onMode = off
14+
4332:onIfMatch = 3334 211
15+
16+
### switch off Omega and Lambda decay channel (treated in GEANT)
17+
3334:onMode = off
18+
3122:onMode = off
Lines changed: 272 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,272 @@
1+
#include "Pythia8/Pythia.h"
2+
#include "FairGenerator.h"
3+
#include "FairPrimaryGenerator.h"
4+
#include "Generators/GeneratorPythia8.h"
5+
#include "TRandom3.h"
6+
#include "TParticlePDG.h"
7+
#include "TDatabasePDG.h"
8+
9+
#include <map>
10+
#include <unordered_set>
11+
//#include <utility> // for std::pair
12+
13+
using namespace Pythia8;
14+
15+
class GeneratorPythia8Gun : public o2::eventgen::GeneratorPythia8{
16+
public:
17+
/// default constructor
18+
GeneratorPythia8Gun() = default;
19+
20+
/// constructor
21+
GeneratorPythia8Gun(int input_pdg){
22+
genMinP=1.;
23+
genMaxP=16.;
24+
genMinEta=-0.1;
25+
genMaxEta=0.1;
26+
27+
pdg = input_pdg;
28+
E=0;
29+
px=0;
30+
py=0;
31+
pz=0;
32+
p=0;
33+
y=0;
34+
eta=0;
35+
xProd=0;
36+
yProd=0;
37+
zProd=0;
38+
xProd=0.; yProd=0.; zProd=0.;
39+
//addFurtherPion=false;
40+
41+
randomizePDGsign=false;
42+
43+
m = getMass(input_pdg);
44+
furtherPrim={};
45+
keys_furtherPrim={};
46+
}
47+
48+
/// Destructor
49+
~GeneratorPythia8Gun() = default;
50+
51+
/// set PDG code
52+
void setPDG(int input_pdg){pdg=input_pdg;}
53+
54+
/// randomize the PDG code sign of core particle
55+
void setRandomizePDGsign(){randomizePDGsign=true;}
56+
57+
/// set mass
58+
void setMass(int input_m){m=input_m;}
59+
60+
/// set 4-momentum
61+
void set4momentum(double input_px, double input_py, double input_pz){
62+
px = input_px;
63+
py = input_py;
64+
pz = input_pz;
65+
E = sqrt( m*m+px*px+py*py+pz*pz );
66+
fourMomentum.px(px);
67+
fourMomentum.py(py);
68+
fourMomentum.pz(pz);
69+
fourMomentum.e(E);
70+
p = sqrt( px*px+py*py+pz*pz );
71+
y = 0.5*log( (E+pz)/(E-pz) );
72+
eta = 0.5*log( (p+pz)/(p-pz) );
73+
74+
////std::cout << "##### Particle #####" << std::endl;
75+
////std::cout << " - PDG code: " << pdg << std::endl;
76+
////std::cout << " - mass: " << m << std::endl;
77+
////std::cout << " - (px,py,pz): (" << px << "," << py << "," << pz << ")" << std::endl;
78+
////std::cout << " - momentum: " << p << std::endl;
79+
////std::cout << " - energy: " << E << std::endl;
80+
////std::cout << " - rapidity: " << y << std::endl;
81+
////std::cout << " - pseudorapidity: " << eta << std::endl;
82+
////std::cout << " - production vertex: (" << xProd << "," << yProd << "," << zProd << ")" << std::endl;
83+
}
84+
85+
/// set 3-momentum
86+
void setMomentum(double input_p){p=input_p;}
87+
88+
/// set x,y,z of production vertex
89+
void setProdVtx(double input_xProd, double input_yProd, double input_zProd){xProd=input_xProd; yProd=input_xProd; zProd=input_zProd;}
90+
91+
/// setter to add further primary particles to the event
92+
void setAddFurtherPrimaries(const int pdgCode, const int howMany){
93+
/// check if this species has been already added
94+
const int map_counts = furtherPrim.count(pdgCode);
95+
if(map_counts==1){ // species already present
96+
const int howMany_already = furtherPrim[pdgCode];
97+
std::cout << "BEWARE: " << howMany_already << " particles of species " << pdgCode << " already required.";
98+
std::cout << " Ignoring the command setAddFurtherPrimaries(" << pdgCode << "," << howMany << ")" << std::endl;
99+
return;
100+
}
101+
/// add particles, if not yet present
102+
furtherPrim[pdgCode] = howMany;
103+
keys_furtherPrim.insert(pdgCode);
104+
}
105+
106+
/// set add a further primary pion
107+
//void setAddFurtherPion(){addFurtherPion=true;}
108+
109+
/// get mass from TParticlePDG
110+
double getMass(int input_pdg){
111+
double mass = 0;
112+
if(TDatabasePDG::Instance()){
113+
TParticlePDG* particle = TDatabasePDG::Instance()->GetParticle(input_pdg);
114+
if(particle) mass = particle->Mass();
115+
else std::cout << "===> particle mass equal to 0" << std::endl;
116+
}
117+
return mass;
118+
}
119+
120+
//_________________________________________________________________________________
121+
/// generate uniform eta and uniform momentum
122+
void genUniformMomentumEta(double minP, double maxP, double minEta, double maxEta){
123+
// random generator
124+
std::unique_ptr<TRandom3> ranGenerator { new TRandom3() };
125+
ranGenerator->SetSeed(0);
126+
127+
// momentum
128+
const double gen_p = ranGenerator->Uniform(minP,maxP);
129+
// eta
130+
const double gen_eta = ranGenerator->Uniform(minEta,maxEta);
131+
// z-component momentum from eta
132+
const double cosTheta = ( exp(2*gen_eta)-1 ) / ( exp(2*gen_eta)+1 ); // starting from eta = -ln(tan(theta/2)) = 1/2*ln( (1+cos(theta))/(1-cos(theta)) ) ---> NB: valid for cos(theta)!=1
133+
const double gen_pz = gen_p*cosTheta;
134+
// y-component: random uniform
135+
const double maxVal = sqrt( gen_p*gen_p-gen_pz*gen_pz );
136+
double sign_py = ranGenerator->Uniform(0,1);
137+
sign_py = (sign_py>0.5)?1.:-1.;
138+
const double gen_py = ranGenerator->Uniform(0.,maxVal)*sign_py;
139+
// x-component momentum
140+
double sign_px = ranGenerator->Uniform(0,1);
141+
sign_px = (sign_px>0.5)?1.:-1.;
142+
const double gen_px = sqrt( gen_p*gen_p-gen_pz*gen_pz-gen_py*gen_py )*sign_px;
143+
144+
set4momentum(gen_px,gen_py,gen_pz);
145+
}
146+
147+
protected:
148+
149+
//__________________________________________________________________
150+
Particle createParticle(){
151+
std::cout << "createParticle() mass " << m << " pdgCode " << pdg << std::endl;
152+
Particle myparticle;
153+
myparticle.id(pdg);
154+
myparticle.status(11);
155+
myparticle.px(px);
156+
myparticle.py(py);
157+
myparticle.pz(pz);
158+
myparticle.e(E);
159+
myparticle.m(m);
160+
myparticle.xProd(xProd);
161+
myparticle.yProd(yProd);
162+
myparticle.zProd(zProd);
163+
164+
return myparticle;
165+
}
166+
167+
//__________________________________________________________________
168+
int randomizeSign(){
169+
170+
std::unique_ptr<TRandom3> gen_random {new TRandom3(0)};
171+
const float n = gen_random->Uniform(-1,1);
172+
173+
return n/abs(n);
174+
}
175+
176+
//__________________________________________________________________
177+
Bool_t generateEvent() override {
178+
179+
const double original_m = m;
180+
const int original_pdg = pdg;
181+
182+
/// reset event
183+
mPythia.event.reset();
184+
185+
/// create and append the desired particle
186+
//genUniformMomentumEta(1.,16.,-0.1,0.1);
187+
genUniformMomentumEta(genMinP,genMaxP,genMinEta,genMaxEta);
188+
if(randomizePDGsign) pdg *= randomizeSign();
189+
Particle particle = createParticle();
190+
//
191+
mPythia.event.append(particle);
192+
//
193+
194+
/// add further particles, if required
195+
if(furtherPrim.size()>0){
196+
if(keys_furtherPrim.size()<1){ /// protection
197+
std::cout << "Something wrong with the insertion of further particles" << std::endl;
198+
return false;
199+
}
200+
/// loop in the map
201+
for(const int addPDG: keys_furtherPrim){
202+
const int numAddPrim = furtherPrim[addPDG]; // we will add "numAddPrim" particles of type "addPDG"
203+
//
204+
// Modify the mass before calling genUniformMomentumEta (required inside set4momentum function)
205+
m = getMass(addPDG);
206+
pdg = addPDG;
207+
//
208+
for(int iAdd=0; iAdd<numAddPrim; iAdd++){ // generated and append the desired particle
209+
genUniformMomentumEta(genMinP,genMaxP,genMinEta,genMaxEta);
210+
Particle further_particle = createParticle();
211+
mPythia.event.append(further_particle);
212+
}
213+
} // end loop map
214+
215+
// restore the values for the desired injected particle (mandatory for next iteration)
216+
m = original_m;
217+
pdg = original_pdg;
218+
}
219+
220+
/// go to next Pythia event
221+
mPythia.next();
222+
223+
return true;
224+
}
225+
226+
private:
227+
228+
double genMinP; /// minimum 3-momentum for generated particles
229+
double genMaxP; /// maximum 3-momentum for generated particles
230+
double genMinEta; /// minimum pseudorapidity for generated particles
231+
double genMaxEta; /// maximum pseudorapidity for generated particles
232+
233+
Vec4 fourMomentum; /// four-momentum (px,py,pz,E)
234+
double E; /// energy: sqrt( m*m+px*px+py*py+pz*pz ) [GeV/c]
235+
double m; /// particle mass [GeV/c^2]
236+
int pdg; /// particle pdg code
237+
double px; /// x-component momentum [GeV/c]
238+
double py; /// y-component momentum [GeV/c]
239+
double pz; /// z-component momentum [GeV/c]
240+
double p; /// momentum
241+
double y; /// rapidity
242+
double eta; /// pseudorapidity
243+
double xProd; /// x-coordinate position production vertex [cm]
244+
double yProd; /// y-coordinate position production vertex [cm]
245+
double zProd; /// z-coordinate position production vertex [cm]
246+
247+
bool randomizePDGsign; /// bool to randomize the PDG code of the core particle
248+
249+
//bool addFurtherPion; /// bool to attach an additional primary pion
250+
std::map<int,int> furtherPrim; /// key: PDG code; value: how many further primaries of this species to be added
251+
std::unordered_set<int> keys_furtherPrim; /// keys of the above map (NB: only unique elements allowed!)
252+
};
253+
254+
///___________________________________________________________
255+
FairGenerator* generateOmegaC(){
256+
auto myGen = new GeneratorPythia8Gun(4332);
257+
myGen->setRandomizePDGsign(); // randomization of OmegaC PDG switched on
258+
return myGen;
259+
}
260+
261+
///___________________________________________________________
262+
FairGenerator* generateOmegaAndPions_RandomCharge(const int nPions){
263+
264+
auto myGen = new GeneratorPythia8Gun(3334);
265+
myGen->setRandomizePDGsign(); // randomization of Omega PDG switched on
266+
267+
/// add further pions
268+
myGen->setAddFurtherPrimaries( 211,nPions/2); // pi+
269+
myGen->setAddFurtherPrimaries(-211,nPions/2); // pi-
270+
271+
return myGen;
272+
}

0 commit comments

Comments
 (0)