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