fTrials(0),
fDeltaPt(0.01),
fSelectAll(kFALSE),
- fDecayer(0)
+ fDecayer(0),
+ fForceConv(kFALSE)
{
// Default constructor
}
fTrials(0),
fDeltaPt(0.01),
fSelectAll(kFALSE),
- fDecayer(0)
+ fDecayer(0),
+ fForceConv(kFALSE)
{
// Constructor using number of particles parameterisation id and library
fName = "Param";
fTrials(0),
fDeltaPt(0.01),
fSelectAll(kFALSE),
- fDecayer(0)
+ fDecayer(0),
+ fForceConv(kFALSE)
{
// Constructor using parameterisation id and number of particles
//
fTrials(0),
fDeltaPt(0.01),
fSelectAll(kFALSE),
- fDecayer(0)
+ fDecayer(0),
+ fForceConv(kFALSE)
{
// Constructor
// Gines Martinez 1/10/99
delete fdNdPhi;
}
+//-------------------------------------------------------------------
+TVector3 AliGenParam::OrthogonalVector(TVector3 &inVec){
+ double abc[]={inVec.x(), inVec.y(), inVec.z()};
+ double xyz[]={1,1,1};
+ int solvDim=0;
+ double tmp=abc[0];
+ for(int i=0; i<3; i++)
+ if(abs(abc[i])>tmp){
+ solvDim=i;
+ tmp=abs(abc[i]);
+ }
+ xyz[solvDim]=(-abc[(1+solvDim)%3]-abc[(2+solvDim)%3])/abc[(0+solvDim)%3];
+
+ TVector3 res(xyz[0],xyz[1],xyz[2]);
+ return res;
+}
+
+double AliGenParam::ScreenFunc1(double d){
+ if(d>1)
+ return 21.12-4.184*log(d+0.952);
+ else
+ return 20.867-3.242*d+0.652*d*d;
+}
+
+double AliGenParam::ScreenFunc2(double d){
+ if(d>1)
+ return 21.12-4.184*log(d+0.952);
+ else
+ return 20.209-1.93*d-0.086*d*d;
+}
+
+double AliGenParam::EnergyFraction(double Z, double E){
+ double e0=0.000511/E;
+ double aZ=Z/137.036;
+ double dmin=ScreenVar(Z,e0,0.5);
+ double fcZ=(aZ*aZ)*(1/(1+aZ*aZ)+0.20206-0.0368*aZ*aZ+0.0083*aZ*aZ*aZ);
+ double Fz=8*log(Z)/3;
+ if(E>0.05)
+ Fz+=8*fcZ;
+ double dmax=exp((42.24-Fz)/8.368)-0.952;
+ if(!(dmax>dmin))
+ return fRandom->Uniform(e0,0.5);
+
+ double e1=0.5-0.5*sqrt(1-dmin/dmax);
+ double emin=TMath::Max(e0,e1);
+
+ double normval=1/(0.5*(ScreenFunc1(dmin)-0.5*Fz)+0.1666667*(ScreenFunc2(dmin)-0.5*Fz));
+ while(true){
+ double y=fRandom->Uniform(emin,1);
+ double eps=y*(0.38453+y*(0.10234+y*(0.026072+y*(0.014367-0.027313*y)))); //inverse to the enveloping cumulative probability distribution
+ double val=fRandom->Uniform(0,2.12*(eps*eps-eps)+1.53); //enveloping probability density
+ double d=ScreenVar(Z,e0,eps);
+ double bh=((eps*eps)+(1-eps)*(1-eps))*(ScreenFunc1(d)-0.5*Fz)+0.6666667*eps*(1-eps)*(ScreenFunc2(d)-0.5*Fz);
+ bh*=normval;
+ if(val<bh)
+ return eps;
+ }
+}
+
+double AliGenParam::PolarAngle(double E){
+ float rand[3];
+ AliRndm rndm;
+ rndm.Rndm(rand,3);
+ double u=-8*log(rand[1]*rand[2])/5;
+ if(!(rand[0]<9.0/36))
+ u/=3;
+ return u*0.000511/E;
+}
+
+Int_t AliGenParam::ForceGammaConversion(TClonesArray *particles, Int_t nPart)
+{
+ //based on: http://geant4.cern.ch/G4UsersDocuments/UsersGuides/PhysicsReferenceManual/html/node27.html
+ // and: http://geant4.cern.ch/G4UsersDocuments/UsersGuides/PhysicsReferenceManual/html/node58.html
+ Int_t nPartNew=nPart;
+ for(int iPart=0; iPart<nPart; iPart++){
+ TParticle *gamma = (TParticle *) particles->At(iPart);
+ if(gamma->GetPdgCode()!=22) continue;
+
+ TVector3 gammaV3(gamma->Px(),gamma->Py(),gamma->Pz());
+ Float_t az=fRandom->Uniform(TMath::Pi()*2);
+ double frac=EnergyFraction(1,gamma->Energy());
+ double Ee1=frac*gamma->Energy();
+ double Ee2=(1-frac)*gamma->Energy();
+ double Pe1=Ee1;//sqrt(Ee1*Ee1-0.000511*0.000511);
+ double Pe2=Ee2;//sqrt(Ee2*Ee2-0.000511*0.000511);
+
+ TVector3 rotAxis(OrthogonalVector(gammaV3));
+ rotAxis.Rotate(az,gammaV3);
+ TVector3 e1V3(gammaV3);
+ e1V3.Rotate(PolarAngle(Ee1),rotAxis);
+ e1V3=e1V3.Unit();
+ e1V3*=Pe1;
+ TVector3 e2V3(gammaV3);
+ e2V3.Rotate(-PolarAngle(Ee2),rotAxis);
+ e2V3=e2V3.Unit();
+ e2V3*=Pe2;
+ // gamma = new TParticle(*gamma);
+ // particles->RemoveAt(iPart);
+ gamma->SetFirstDaughter(nPartNew+1);
+ gamma->SetLastDaughter(nPartNew+2);
+ // new((*particles)[iPart]) TParticle(*gamma);
+ // delete gamma;
+
+ TLorentzVector vtx;
+ gamma->ProductionVertex(vtx);
+ new((*particles)[nPartNew]) TParticle(11, gamma->GetStatusCode(), iPart+1, -1, 0, 0, TLorentzVector(e1V3,Ee1), vtx);
+ nPartNew++;
+ new((*particles)[nPartNew]) TParticle(-11, gamma->GetStatusCode(), iPart+1, -1, 0, 0, TLorentzVector(e2V3,Ee2), vtx);
+ nPartNew++;
+ }
+ // particles->Compress();
+ return particles->GetEntriesFast();
+}
+
//____________________________________________________________
void AliGenParam::Init()
{
fdNdy0=fYParaFunc(&y1,&y2);
//
// Integral over generation region
+#if ROOT_VERSION_CODE < ROOT_VERSION(5,99,0)
Float_t intYS = yPara.Integral(fYMin, fYMax,(Double_t*) 0x0,1.e-6);
Float_t intPt0 = ptPara.Integral(0,15,(Double_t *) 0x0,1.e-6);
Float_t intPtS = ptPara.Integral(fPtMin,fPtMax,(Double_t*) 0x0,1.e-6);
+#else
+ Float_t intYS = yPara.Integral(fYMin, fYMax,1.e-6);
+ Float_t intPt0 = ptPara.Integral(0,15,1.e-6);
+ Float_t intPtS = ptPara.Integral(fPtMin,fPtMax,1.e-6);
+#endif
Float_t phiWgt=(fPhiMax-fPhiMin)/2./TMath::Pi(); //TR: should probably be done differently in case of anisotropic phi...
if (fAnalog == kAnalog) {
fYWgt = intYS/fdNdy0;
//____________________________________________________________
void AliGenParam::Generate()
{
+ //
+ // Generate 1 event (see Generate(Int_t ntimes) for details
//
- // Generate 'npart' of light and heavy mesons (J/Psi, upsilon or phi, Pion,
+ GenerateN(1);
+}
+//____________________________________________________________
+void AliGenParam::GenerateN(Int_t ntimes)
+{
+ //
+ // Generate ntimes*'npart' light and heavy mesons (J/Psi, upsilon or phi, Pion,
// Kaons, Etas, Omegas) and Baryons (proton, antiprotons, neutrons and
// antineutrons in the the desired theta, phi and momentum windows;
// Gaussian smearing on the vertex is done if selected.
// Generating fNpart particles
fNprimaries = 0;
- while (ipa<fNpart) {
+ Int_t nGen = fNpart*ntimes;
+ while (ipa<nGen) {
while(1) {
//
// particle type
}
//
// phi
- // if(!ipa)
- // phi=fEvPlane; //align first particle of each event with event plane
- // else{
+ // if(!ipa)
+ //phi=fEvPlane; //align first particle of each event with event plane
+ //else{
double v2 = fV2Para->Eval(pt);
fdNdPhi->SetParameter(0,v2);
fdNdPhi->SetParameter(1,fEvPlane);
phi=fdNdPhi->GetRandom();
- // }
+ // }
pl=xmt*ty/sqrt((1.-ty)*(1.+ty));
theta=TMath::ATan2(pt,pl);
// select decay particles
Int_t np=fDecayer->ImportParticles(particles);
+ if(fForceConv) np=ForceGammaConversion(particles,np);
+
+ // for(int iPart=0; iPart<np; iPart++){
+ // TParticle *gamma = (TParticle *) particles->At(iPart);
+ // printf("%i %i:", iPart, gamma->GetPdgCode());
+ // printf("%i %i %i|",gamma->GetFirstMother(),gamma->GetFirstDaughter(),gamma->GetLastDaughter());
+ // }
+
// Selecting GeometryAcceptance for particles fPdgCodeParticleforAcceptanceCut;
if (fGeometryAcceptance)
if (!CheckAcceptanceGeometry(np,particles)) continue;
//
// Normalisation for selected kinematic region
//
+#if ROOT_VERSION_CODE < ROOT_VERSION(5,99,0)
Float_t ratio =
fPtPara->Integral(ptMin,ptMax,(Double_t *)0,1.e-6) / fPtPara->Integral( fPtPara->GetXmin(), fPtPara->GetXmax(),(Double_t *)0,1.e-6) *
fYPara->Integral(yMin,yMax,(Double_t *)0,1.e-6)/fYPara->Integral(fYPara->GetXmin(),fYPara->GetXmax(),(Double_t *)0,1.e-6) *
(phiMax-phiMin)/360.;
+#else
+ Float_t ratio =
+ fPtPara->Integral(ptMin,ptMax,1.e-6) / fPtPara->Integral( fPtPara->GetXmin(), fPtPara->GetXmax(),1.e-6) *
+ fYPara->Integral(yMin,yMax,1.e-6)/fYPara->Integral(fYPara->GetXmin(),fYPara->GetXmax(),1.e-6) *
+ (phiMax-phiMin)/360.;
+#endif
return TMath::Abs(ratio);
}