LCOV - code coverage report
Current view: top level - EVGEN - AliGenParam.cxx (source / functions) Hit Total Coverage
Test: coverage.info Lines: 1 502 0.2 %
Date: 2016-06-14 17:26:59 Functions: 1 28 3.6 %

          Line data    Source code
       1             : /**************************************************************************
       2             :  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
       3             :  *                                                                        *
       4             :  * Author: The ALICE Off-line Project.                                    *
       5             :  * Contributors are mentioned in the code where appropriate.              *
       6             :  *                                                                        *
       7             :  * Permission to use, copy, modify and distribute this software and its   *
       8             :  * documentation strictly for non-commercial purposes is hereby granted   *
       9             :  * without fee, provided that the above copyright notice appears in all   *
      10             :  * copies and that both the copyright notice and this permission notice   *
      11             :  * appear in the supporting documentation. The authors make no claims     *
      12             :  * about the suitability of this software for any purpose. It is          *
      13             :  * provided "as is" without express or implied warranty.                  *
      14             :  **************************************************************************/
      15             : 
      16             : /* $Id$ */
      17             : 
      18             : // Class to generate particles from using paramtrized pT and y distributions.
      19             : // Distributions are obtained from pointer to object of type AliGenLib.
      20             : // (For example AliGenMUONlib)
      21             : // Decays are performed using Pythia.
      22             : // andreas.morsch@cern.ch
      23             : 
      24             : #include <TCanvas.h>
      25             : #include <TClonesArray.h>
      26             : #include <TDatabasePDG.h>
      27             : #include <TF1.h>
      28             : #include <TH1F.h>
      29             : #include <TLorentzVector.h>
      30             : #include <TMath.h>
      31             : #include <TParticle.h>
      32             : #include <TParticlePDG.h>
      33             : #include <TROOT.h>
      34             : #include <TVirtualMC.h>
      35             : 
      36             : #include "AliDecayer.h"
      37             : #include "AliGenMUONlib.h"
      38             : #include "AliGenParam.h"
      39             : #include "AliMC.h"
      40             : #include "AliRun.h"
      41             : #include "AliGenEventHeader.h"
      42             : 
      43           6 : ClassImp(AliGenParam)
      44             : 
      45             : //------------------------------------------------------------
      46             : 
      47             : //Begin_Html
      48             : /*
      49             :   <img src="picts/AliGenParam.gif">
      50             : */
      51             : //End_Html
      52             : 
      53             : //____________________________________________________________
      54           0 : AliGenParam::AliGenParam()
      55           0 : : fPtParaFunc(0),
      56           0 :   fYParaFunc(0),
      57           0 :   fIpParaFunc(0),
      58           0 :   fV2ParaFunc(0),
      59           0 :   fPtPara(0),
      60           0 :   fYPara(0),
      61           0 :   fV2Para(0),
      62           0 :   fdNdPhi(0),
      63           0 :   fParam(0),
      64           0 :   fdNdy0(0.),
      65           0 :   fYWgt(0.),
      66           0 :   fPtWgt(0.),
      67           0 :   fBias(0.),
      68           0 :   fTrials(0),
      69           0 :   fDeltaPt(0.01),
      70           0 :   fSelectAll(kFALSE),
      71           0 :   fDecayer(0),
      72           0 :   fForceConv(kFALSE),
      73           0 :   fKeepParent(kFALSE),
      74           0 :   fKeepIfOneChildSelected(kFALSE),
      75           0 :   fPreserveFullDecayChain(kFALSE)
      76           0 : {
      77             :   // Default constructor
      78           0 : }
      79             : //____________________________________________________________
      80             : AliGenParam::AliGenParam(Int_t npart, const AliGenLib * Library,  Int_t param, const char* tname)
      81           0 :   :AliGenMC(npart),
      82           0 :    fPtParaFunc(Library->GetPt(param, tname)),
      83           0 :    fYParaFunc (Library->GetY (param, tname)),
      84           0 :    fIpParaFunc(Library->GetIp(param, tname)),
      85           0 :    fV2ParaFunc(Library->GetV2(param, tname)),
      86           0 :    fPtPara(0),
      87           0 :    fYPara(0),
      88           0 :    fV2Para(0),
      89           0 :    fdNdPhi(0),
      90           0 :    fParam(param),
      91           0 :    fdNdy0(0.),
      92           0 :    fYWgt(0.),
      93           0 :    fPtWgt(0.),
      94           0 :    fBias(0.),
      95           0 :    fTrials(0),
      96           0 :    fDeltaPt(0.01),
      97           0 :    fSelectAll(kFALSE),
      98           0 :    fDecayer(0),
      99           0 :    fForceConv(kFALSE),
     100           0 :    fKeepParent(kFALSE),
     101           0 :    fKeepIfOneChildSelected(kFALSE),
     102           0 :    fPreserveFullDecayChain(kFALSE)
     103           0 : {
     104             :   // Constructor using number of particles parameterisation id and library
     105           0 :   fName = "Param";
     106           0 :   fTitle= "Particle Generator using pT and y parameterisation";
     107           0 :   fAnalog = kAnalog;
     108           0 :   SetForceDecay();
     109           0 : }
     110             : //____________________________________________________________
     111             : AliGenParam::AliGenParam(Int_t npart, Int_t param, const char* tname, const char* name):
     112           0 :   AliGenMC(npart),
     113           0 :   fPtParaFunc(0),
     114           0 :   fYParaFunc (0),
     115           0 :   fIpParaFunc(0),
     116           0 :   fV2ParaFunc(0),
     117           0 :   fPtPara(0),
     118           0 :   fYPara(0),
     119           0 :   fV2Para(0),
     120           0 :   fdNdPhi(0),
     121           0 :   fParam(param),
     122           0 :   fdNdy0(0.),
     123           0 :   fYWgt(0.),
     124           0 :   fPtWgt(0.),
     125           0 :   fBias(0.),
     126           0 :   fTrials(0),
     127           0 :   fDeltaPt(0.01),
     128           0 :   fSelectAll(kFALSE),
     129           0 :   fDecayer(0),
     130           0 :   fForceConv(kFALSE),
     131           0 :   fKeepParent(kFALSE),
     132           0 :   fKeepIfOneChildSelected(kFALSE),
     133           0 :   fPreserveFullDecayChain(kFALSE)
     134           0 : {
     135             :   // Constructor using parameterisation id and number of particles
     136             :   //
     137           0 :   fName = name;
     138           0 :   fTitle= "Particle Generator using pT and y parameterisation";
     139             :       
     140           0 :   AliGenLib* pLibrary = new AliGenMUONlib();
     141           0 :   fPtParaFunc = pLibrary->GetPt(param, tname);
     142           0 :   fYParaFunc  = pLibrary->GetY (param, tname);
     143           0 :   fIpParaFunc = pLibrary->GetIp(param, tname);
     144           0 :   fV2ParaFunc = pLibrary->GetV2(param, tname);
     145             :     
     146           0 :   fAnalog = kAnalog;
     147           0 :   fChildSelect.Set(5);
     148           0 :   for (Int_t i=0; i<5; i++) fChildSelect[i]=0;
     149           0 :   SetForceDecay();
     150           0 :   SetCutOnChild();
     151           0 :   SetChildMomentumRange();
     152           0 :   SetChildPtRange();
     153           0 :   SetChildPhiRange();
     154           0 :   SetChildThetaRange(); 
     155           0 : }
     156             : //____________________________________________________________
     157             : 
     158             : AliGenParam::AliGenParam(Int_t npart, Int_t param,
     159             :                          Double_t (*PtPara) (const Double_t*, const Double_t*),
     160             :                          Double_t (*YPara ) (const Double_t* ,const Double_t*),
     161             :                          Double_t (*V2Para) (const Double_t* ,const Double_t*),
     162             :                          Int_t    (*IpPara) (TRandom *))                 
     163           0 :   :AliGenMC(npart),
     164             :      
     165           0 :    fPtParaFunc(PtPara),
     166           0 :    fYParaFunc(YPara),
     167           0 :    fIpParaFunc(IpPara),
     168           0 :    fV2ParaFunc(V2Para),
     169           0 :    fPtPara(0),
     170           0 :    fYPara(0),
     171           0 :    fV2Para(0),
     172           0 :    fdNdPhi(0),
     173           0 :    fParam(param),
     174           0 :    fdNdy0(0.),
     175           0 :    fYWgt(0.),
     176           0 :    fPtWgt(0.),
     177           0 :    fBias(0.),
     178           0 :    fTrials(0),
     179           0 :    fDeltaPt(0.01),
     180           0 :    fSelectAll(kFALSE),
     181           0 :    fDecayer(0),
     182           0 :    fForceConv(kFALSE),
     183           0 :    fKeepParent(kFALSE),
     184           0 :    fKeepIfOneChildSelected(kFALSE)
     185           0 : {
     186             :   // Constructor
     187             :   // Gines Martinez 1/10/99 
     188           0 :   fName = "Param";
     189           0 :   fTitle= "Particle Generator using pT and y parameterisation";
     190             : 
     191           0 :   fAnalog = kAnalog;
     192           0 :   fChildSelect.Set(5);
     193           0 :   for (Int_t i=0; i<5; i++) fChildSelect[i]=0;
     194           0 :   SetForceDecay();
     195           0 :   SetCutOnChild();
     196           0 :   SetChildMomentumRange();
     197           0 :   SetChildPtRange();
     198           0 :   SetChildPhiRange();
     199           0 :   SetChildThetaRange();  
     200           0 : }
     201             : 
     202             : //____________________________________________________________
     203           0 : AliGenParam::~AliGenParam()
     204           0 : {
     205             :   // Destructor
     206           0 :   delete  fPtPara;
     207           0 :   delete  fYPara;
     208           0 :   delete  fV2Para;
     209           0 :   delete  fdNdPhi;
     210           0 : }
     211             : 
     212             : //-------------------------------------------------------------------
     213             : TVector3 AliGenParam::OrthogonalVector(TVector3 &inVec){
     214           0 :   double abc[]={inVec.x(), inVec.y(), inVec.z()}; 
     215           0 :   double xyz[]={1,1,1};
     216             :   int solvDim=0;
     217           0 :   double tmp=abc[0];
     218           0 :   for(int i=0; i<3; i++)
     219           0 :     if(fabs(abc[i])>tmp){
     220             :       solvDim=i;
     221             :       tmp=fabs(abc[i]);
     222           0 :     }
     223           0 :   xyz[solvDim]=(-abc[(1+solvDim)%3]-abc[(2+solvDim)%3])/abc[(0+solvDim)%3];
     224             :   
     225           0 :   TVector3 res(xyz[0],xyz[1],xyz[2]);
     226             :   return res;
     227           0 : }
     228             : 
     229             : void AliGenParam::RotateVector(Double_t *pin, Double_t *pout, Double_t costheta, Double_t sintheta,
     230             :                                Double_t cosphi, Double_t sinphi)
     231             : {
     232             :   // Perform rotation
     233           0 :   pout[0] = pin[0]*costheta*cosphi-pin[1]*sinphi+pin[2]*sintheta*cosphi;
     234           0 :   pout[1] = pin[0]*costheta*sinphi+pin[1]*cosphi+pin[2]*sintheta*sinphi;
     235           0 :   pout[2] = -1.0  * pin[0] * sintheta + pin[2] * costheta;
     236           0 :   return;
     237             : }
     238             : 
     239             : double AliGenParam::ScreenFunction1(double screenVariable){
     240           0 :   if(screenVariable>1)
     241           0 :     return 42.24 - 8.368 * log(screenVariable + 0.952);
     242             :   else
     243           0 :     return 42.392 - screenVariable * (7.796 - 1.961 * screenVariable);
     244           0 : }
     245             : 
     246             : double AliGenParam::ScreenFunction2(double screenVariable){
     247           0 :   if(screenVariable>1)
     248           0 :     return 42.24 - 8.368 * log(screenVariable + 0.952);
     249             :   else
     250           0 :     return 41.405 - screenVariable * (5.828 - 0.8945 * screenVariable);
     251           0 : }
     252             : 
     253             : double AliGenParam::RandomEnergyFraction(double Z, double photonEnergy){
     254           0 :   double aZ=Z/137.036;
     255             :   double epsilon ;
     256           0 :   double epsilon0Local = 0.000511 / photonEnergy ;
     257             : 
     258             :   // Do it fast if photon energy < 2. MeV
     259           0 :   if (photonEnergy < 0.002 )
     260             :     {
     261           0 :       epsilon = epsilon0Local + (0.5 - epsilon0Local) * fRandom->Rndm();
     262           0 :     }
     263             :   else
     264             :     {
     265           0 :       double fZ = 8*log(Z)/3;
     266           0 :       double fcZ=(aZ*aZ)*(1/(1+aZ*aZ)+0.20206-0.0368*aZ*aZ+0.0083*aZ*aZ*aZ);
     267           0 :       if (photonEnergy > 0.050) fZ += 8*fcZ;
     268             :       
     269             :       // Limits of the screening variable
     270           0 :       double screenFactor = 136. * epsilon0Local / pow (Z,1/3);
     271           0 :       double screenMax = exp ((42.24 - fZ)/8.368) - 0.952 ;
     272           0 :       double screenMin = std::min(4.*screenFactor,screenMax) ;
     273             : 
     274             :       // Limits of the energy sampling
     275           0 :       double epsilon1 = 0.5 - 0.5 * sqrt(1. - screenMin / screenMax) ;
     276           0 :       double epsilonMin = std::max(epsilon0Local,epsilon1);
     277           0 :       double epsilonRange = 0.5 - epsilonMin ;
     278             : 
     279             :       // Sample the energy rate of the created electron (or positron)
     280             :       double screen;
     281             :       double gReject ;
     282             : 
     283           0 :       double f10 = ScreenFunction1(screenMin) - fZ;
     284           0 :       double f20 = ScreenFunction2(screenMin) - fZ;
     285           0 :       double normF1 = std::max(f10 * epsilonRange * epsilonRange,0.);
     286           0 :       double normF2 = std::max(1.5 * f20,0.);
     287             : 
     288           0 :       do 
     289             :         {
     290           0 :           if (normF1 / (normF1 + normF2) > fRandom->Rndm() )
     291             :             {
     292           0 :               epsilon = 0.5 - epsilonRange * pow(fRandom->Rndm(), 0.333333) ;
     293           0 :               screen = screenFactor / (epsilon * (1. - epsilon));
     294           0 :               gReject = (ScreenFunction1(screen) - fZ) / f10 ;
     295           0 :             }
     296             :           else
     297             :             {
     298           0 :               epsilon = epsilonMin + epsilonRange * fRandom->Rndm();
     299           0 :               screen = screenFactor / (epsilon * (1 - epsilon));
     300           0 :               gReject = (ScreenFunction2(screen) - fZ) / f20 ;
     301             :             }
     302           0 :         } while ( gReject < fRandom->Rndm() );
     303             :     
     304           0 :     }   //  End of epsilon sampling
     305           0 :   return epsilon;
     306           0 : }
     307             : 
     308             : double AliGenParam::RandomPolarAngle(){
     309             :   double u;
     310             :   const double a1 = 0.625;
     311             :   double a2 = 3. * a1;
     312             :   //  double d = 27. ;
     313             : 
     314             :   //  if (9. / (9. + d) > fRandom->Rndm())
     315           0 :   if (0.25 > fRandom->Rndm())
     316             :     {
     317           0 :       u = - log(fRandom->Rndm() * fRandom->Rndm()) / a1 ;
     318           0 :     }
     319             :   else
     320             :     {
     321           0 :       u = - log(fRandom->Rndm() * fRandom->Rndm()) / a2 ;
     322             :     }
     323           0 :   return u*0.000511;
     324             : }
     325             :   
     326             : Double_t AliGenParam::RandomMass(Double_t mh){
     327           0 :   while(true){
     328           0 :     double y=fRandom->Rndm();
     329           0 :     double mee=2*0.000511*TMath::Power(2*0.000511/mh,-y); //inverse of the enveloping cumulative distribution
     330           0 :     double apxkw=2.0/3.0/137.036/TMath::Pi()/mee; //enveloping probability density
     331           0 :     double val=fRandom->Uniform(0,apxkw);
     332           0 :     double kw=apxkw*sqrt(1-4*0.000511*0.000511/mee/mee)*(1+2*0.000511*0.000511/mee/mee)*1*1*TMath::Power(1-mee*mee/mh/mh,3);
     333           0 :     if(val<kw)
     334           0 :       return mee;
     335           0 :   }
     336           0 : }
     337             : 
     338             : Int_t AliGenParam::VirtualGammaPairProduction(TClonesArray *particles, Int_t nPart)
     339             : {
     340             :   Int_t nPartNew=nPart;
     341           0 :   for(int iPart=0; iPart<nPart; iPart++){      
     342           0 :     TParticle *gamma = (TParticle *) particles->At(iPart);
     343           0 :     if(gamma->GetPdgCode()!=220001) continue;
     344           0 :     if(gamma->Pt()<0.002941) continue;  //approximation of kw in AliGenEMlib is 0 below 0.002941
     345           0 :     double mass=RandomMass(gamma->Pt());
     346             : 
     347             :     // lepton pair kinematics in virtual photon rest frame 
     348           0 :     double Ee=mass/2;
     349           0 :     double Pe=TMath::Sqrt((Ee+0.000511)*(Ee-0.000511));
     350             : 
     351           0 :     double costheta = (2.0 * gRandom->Rndm()) - 1.;
     352           0 :     double sintheta = TMath::Sqrt((1. + costheta) * (1. - costheta));
     353           0 :     double phi      = 2.0 * TMath::ACos(-1.) * gRandom->Rndm();
     354           0 :     double sinphi   = TMath::Sin(phi);
     355           0 :     double cosphi   = TMath::Cos(phi);
     356             :     
     357             :     // momentum vectors of leptons in virtual photon rest frame
     358           0 :     Double_t pProd1[3] = {Pe * sintheta * cosphi,
     359           0 :                           Pe * sintheta * sinphi,
     360           0 :                           Pe * costheta};
     361             : 
     362           0 :     Double_t pProd2[3] = {-1.0 * Pe * sintheta * cosphi,
     363           0 :                           -1.0 * Pe * sintheta * sinphi,
     364           0 :                           -1.0 * Pe * costheta}; 
     365             : 
     366             :     // lepton 4-vectors in properly rotated virtual photon rest frame
     367           0 :     Double_t pRot1[3] = {0.};
     368           0 :     RotateVector(pProd1, pRot1, costheta, -sintheta, -cosphi, -sinphi);
     369           0 :     Double_t pRot2[3] = {0.};
     370           0 :     RotateVector(pProd2, pRot2, costheta, -sintheta, -cosphi, -sinphi); 
     371             : 
     372           0 :     TLorentzVector e1V4(pRot1[0],pRot1[1],pRot1[2],Ee);
     373           0 :     TLorentzVector e2V4(pRot2[0],pRot2[1],pRot2[2],Ee);
     374             :   
     375           0 :     TVector3 boost(gamma->Px(),gamma->Py(),gamma->Pz());
     376           0 :     boost*=1/sqrt(gamma->P()*gamma->P()+mass*mass);
     377           0 :     e1V4.Boost(boost);
     378           0 :     e2V4.Boost(boost);
     379             : 
     380           0 :     TLorentzVector vtx;
     381           0 :     gamma->ProductionVertex(vtx);
     382           0 :     new((*particles)[nPartNew]) TParticle(11, gamma->GetStatusCode(), iPart+1, -1, 0, 0, e1V4, vtx);
     383           0 :     nPartNew++;
     384           0 :     new((*particles)[nPartNew]) TParticle(-11, gamma->GetStatusCode(), iPart+1, -1, 0, 0, e2V4, vtx);
     385           0 :     nPartNew++;
     386           0 :   }
     387           0 :   return nPartNew;
     388           0 : }
     389             : 
     390             : Int_t AliGenParam::ForceGammaConversion(TClonesArray *particles, Int_t nPart)
     391             : {
     392             :   //based on: http://geant4.cern.ch/G4UsersDocuments/UsersGuides/PhysicsReferenceManual/html/node27.html
     393             :   //     and: http://geant4.cern.ch/G4UsersDocuments/UsersGuides/PhysicsReferenceManual/html/node58.html
     394             :   //     and: G4LivermoreGammaConversionModel.cc
     395             :   Int_t nPartNew=nPart;
     396           0 :   for(int iPart=0; iPart<nPart; iPart++){      
     397           0 :     TParticle *gamma = (TParticle *) particles->At(iPart);
     398           0 :     if(gamma->GetPdgCode()!=22 & gamma->GetPdgCode()!=220000) continue;
     399           0 :     if(gamma->Energy()<=0.001022) continue;
     400           0 :     TVector3 gammaV3(gamma->Px(),gamma->Py(),gamma->Pz());
     401           0 :     double frac=RandomEnergyFraction(1,gamma->Energy());
     402           0 :     double Ee1=frac*gamma->Energy();
     403           0 :     double Ee2=(1-frac)*gamma->Energy();
     404           0 :     double Pe1=sqrt((Ee1+0.000511)*(Ee1-0.000511));
     405           0 :     double Pe2=sqrt((Ee2+0.000511)*(Ee2-0.000511));
     406             :     
     407           0 :     TVector3 rotAxis(OrthogonalVector(gammaV3));
     408           0 :     Float_t az=fRandom->Uniform(TMath::Pi()*2);
     409           0 :     rotAxis.Rotate(az,gammaV3);
     410           0 :     TVector3 e1V3(gammaV3);
     411           0 :     double u=RandomPolarAngle();
     412           0 :     e1V3.Rotate(u/Ee1,rotAxis);
     413           0 :     e1V3=e1V3.Unit();
     414           0 :     e1V3*=Pe1;
     415           0 :     TVector3 e2V3(gammaV3);
     416           0 :     e2V3.Rotate(-u/Ee2,rotAxis);
     417           0 :     e2V3=e2V3.Unit();
     418           0 :     e2V3*=Pe2;
     419             :     // gamma = new TParticle(*gamma);
     420             :     // particles->RemoveAt(iPart);
     421           0 :     gamma->SetFirstDaughter(nPartNew+1);
     422           0 :     gamma->SetLastDaughter(nPartNew+2);
     423             :     // new((*particles)[iPart]) TParticle(*gamma);
     424             :     // delete gamma;
     425             : 
     426             :     // conversion probability per atom
     427             :     // fitted G4EMLOW6.35/pair/pp-cs-8.dat, fit is great for E>20MeV
     428           0 :     double convProb = 1/(exp(-log(28.44*(gamma->Energy()-0.001022))*(0.775+0.0271*log(gamma->Energy()+1)))+1);
     429             : 
     430             :     // radiation length is not considered here, so you have to normalize yourself in after-production from infinite radiation length to whatever you want
     431             :     // double meanExessPathlength=0.5*(exp(0.9)-exp(-0.9))/0.9; double scale=(1-exp(-7.0/9.0*radLength*meanExessPathlength))/(1-0);
     432             :     
     433           0 :     TLorentzVector vtx;
     434           0 :     gamma->ProductionVertex(vtx);
     435             :     TParticle *currPart;
     436           0 :     Int_t sign = (gRandom->Rndm() < 0.5) ? 1 : -1; 
     437           0 :     currPart = new((*particles)[nPartNew]) TParticle(sign * 220011, gamma->GetStatusCode(), iPart+1, -1, 0, 0, TLorentzVector(e1V3,Ee1), vtx);
     438           0 :     currPart->SetWeight(convProb);
     439             :     nPartNew++;
     440           0 :     currPart = new((*particles)[nPartNew]) TParticle(- sign * 220011, gamma->GetStatusCode(), iPart+1, -1, 0, 0, TLorentzVector(e2V3,Ee2), vtx);
     441           0 :     currPart->SetWeight(convProb);
     442           0 :     nPartNew++;
     443           0 :   }
     444           0 :   return nPartNew;
     445           0 : }
     446             : 
     447             : //____________________________________________________________
     448             : void AliGenParam::Init()
     449             : {
     450             :   // Initialisation
     451             : 
     452           0 :   if (TVirtualMC::GetMC()) fDecayer = TVirtualMC::GetMC()->GetDecayer();
     453             :   //Begin_Html
     454             :   /*
     455             :     <img src="picts/AliGenParam.gif">
     456             :   */
     457             :   //End_Html
     458           0 :   char name[256];
     459           0 :   snprintf(name, 256, "pt-parameterisation for %s", GetName());
     460             :     
     461           0 :   if (fPtPara) fPtPara->Delete();
     462           0 :   fPtPara = new TF1(name, fPtParaFunc, fPtMin, fPtMax,0);
     463           0 :   gROOT->GetListOfFunctions()->Remove(fPtPara);
     464             :   //  Set representation precision to 10 MeV
     465           0 :   Int_t npx= Int_t((fPtMax - fPtMin) / fDeltaPt);
     466             :     
     467           0 :   fPtPara->SetNpx(npx);
     468             : 
     469           0 :   snprintf(name, 256, "y-parameterisation  for %s", GetName());
     470           0 :   if (fYPara) fYPara->Delete();
     471           0 :   fYPara  = new TF1(name, fYParaFunc, fYMin, fYMax, 0);
     472           0 :   gROOT->GetListOfFunctions()->Remove(fYPara);
     473             : 
     474           0 :   snprintf(name, 256, "v2-parameterisation for %s", GetName());
     475           0 :   if (fV2Para) fV2Para->Delete();
     476           0 :   fV2Para  = new TF1(name, fV2ParaFunc, fPtMin, fPtMax, 0);
     477             :   // fV2Para  = new TF1(name, "2*[0]/(1+TMath::Exp([1]*([2]-x)))-[0]", fPtMin, fPtMax);
     478             :   // fV2Para->SetParameter(0, 0.236910);
     479             :   // fV2Para->SetParameter(1, 1.71122);
     480             :   // fV2Para->SetParameter(2, 0.0827617);
     481             :   //gROOT->GetListOfFunctions()->Remove(fV2Para);  //TR: necessary?
     482             :     
     483           0 :   snprintf(name, 256, "dNdPhi for %s", GetName());
     484           0 :   if (fdNdPhi) fdNdPhi->Delete();
     485           0 :   fdNdPhi  = new TF1(name, "1+2*[0]*TMath::Cos(2*(x-[1]))", fPhiMin, fPhiMax);
     486             :   //gROOT->GetListOfFunctions()->Remove(fdNdPhi);  //TR: necessary?
     487             :     
     488           0 :   snprintf(name, 256, "pt-for-%s", GetName());
     489           0 :   TF1 ptPara(name ,fPtParaFunc, 0, 15, 0);
     490           0 :   snprintf(name, 256, "y-for-%s", GetName());
     491           0 :   TF1 yPara(name, fYParaFunc, -6, 6, 0);
     492             : 
     493             :   //
     494             :   // dN/dy| y=0
     495           0 :   Double_t y1=0;
     496           0 :   Double_t y2=0;
     497             :     
     498           0 :   fdNdy0=fYParaFunc(&y1,&y2);
     499             :   //
     500             :   // Integral over generation region
     501             : #if ROOT_VERSION_CODE < ROOT_VERSION(5,99,0)
     502           0 :   Float_t intYS  = yPara.Integral(fYMin, fYMax,(Double_t*) 0x0,1.e-6);
     503           0 :   Float_t intPt0 = ptPara.Integral(0,15,(Double_t *) 0x0,1.e-6);
     504           0 :   Float_t intPtS = ptPara.Integral(fPtMin,fPtMax,(Double_t*) 0x0,1.e-6);
     505             : #else
     506             :   Float_t intYS  = yPara.Integral(fYMin, fYMax,1.e-6);
     507             :   Float_t intPt0 = ptPara.Integral(0,15,1.e-6);
     508             :   Float_t intPtS = ptPara.Integral(fPtMin,fPtMax,1.e-6);
     509             : #endif
     510           0 :   Float_t phiWgt=(fPhiMax-fPhiMin)/2./TMath::Pi();    //TR: should probably be done differently in case of anisotropic phi...
     511           0 :   if (fAnalog == kAnalog) {
     512           0 :     fYWgt  = intYS/fdNdy0;
     513           0 :     fPtWgt = intPtS/intPt0;
     514           0 :     fParentWeight = fYWgt*fPtWgt*phiWgt/fNpart;
     515           0 :   } else {
     516             :     fYWgt = intYS/fdNdy0;
     517           0 :     fPtWgt = (fPtMax-fPtMin)/intPt0;
     518           0 :     fParentWeight = fYWgt*fPtWgt*phiWgt/fNpart;
     519             :   }
     520             :   //
     521             :   // particle decay related initialization
     522           0 :   fDecayer->SetForceDecay(fForceDecay);
     523           0 :   fDecayer->Init();
     524             : 
     525             :   //
     526           0 :   AliGenMC::Init();
     527           0 : }
     528             : 
     529             : //____________________________________________________________
     530             : void AliGenParam::Generate()
     531             : {
     532             :   // 
     533             :   // Generate 1 event (see Generate(Int_t ntimes) for details
     534             :   //
     535           0 :   GenerateN(1);
     536           0 : }
     537             : //____________________________________________________________
     538             : void AliGenParam::GenerateN(Int_t ntimes)
     539             : {
     540             :   //
     541             :   // Generate ntimes*'npart' light and heavy mesons (J/Psi, upsilon or phi, Pion,
     542             :   // Kaons, Etas, Omegas) and Baryons (proton, antiprotons, neutrons and 
     543             :   // antineutrons in the the desired theta, phi and momentum windows; 
     544             :   // Gaussian smearing on the vertex is done if selected. 
     545             :   // The decay of heavy mesons is done using lujet, 
     546             :   //    and the childern particle are tracked by GEANT
     547             :   // However, light mesons are directly tracked by GEANT 
     548             :   // setting fForceDecay = nodecay (SetForceDecay(nodecay)) 
     549             :   //
     550             :   //
     551             :   //  Reinitialize decayer
     552           0 :   fDecayer->SetForceDecay(fForceDecay);
     553           0 :   fDecayer->Init();
     554             : 
     555             :   //
     556             :   Float_t polar[3]= {0,0,0};  // Polarisation of the parent particle (for GEANT tracking)
     557           0 :   Double_t origin0[3];         // Origin of the generated parent particle (for GEANT tracking)
     558             :   Double_t time0;              // Time0 of the generated parent particle
     559             :   Double_t pt, pl, ptot;       // Transverse, logitudinal and total momenta of the parent particle
     560             :   Double_t phi, theta;         // Phi and theta spherical angles of the parent particle momentum
     561             :   Double_t p[3], pc[3], och[3];// Momentum, polarisation and origin of the children particles from lujet
     562             :   Double_t ty, xmt;
     563           0 :   Int_t nt, i, j;
     564             :   Double_t energy;
     565             :   Float_t  wgtp, wgtch;
     566           0 :   Double_t dummy;
     567             :   static TClonesArray *particles;
     568             :   //
     569           0 :   if(!particles) particles = new TClonesArray("TParticle",1000);
     570             :   
     571           0 :   TDatabasePDG *pDataBase = TDatabasePDG::Instance();
     572             :   //
     573           0 :   Float_t random[6];
     574             :  
     575             :   // Calculating vertex position per event
     576           0 :   for (j=0;j<3;j++) origin0[j]=fOrigin[j];
     577           0 :   time0 = fTimeOrigin;
     578           0 :   if(fVertexSmear==kPerEvent) {
     579           0 :     Vertex();
     580           0 :     for (j=0;j<3;j++) origin0[j]=fVertex[j];
     581           0 :     time0 = fTime;
     582           0 :   }
     583             :   
     584             :   Int_t ipa=0;
     585             :   
     586             :   // Generating fNpart particles
     587           0 :   fNprimaries = 0;
     588             :   
     589           0 :   Int_t nGen = fNpart*ntimes;
     590           0 :   while (ipa<nGen) {
     591             :     while(1) {
     592             :       //
     593             :       // particle type 
     594           0 :       Int_t iPart = fIpParaFunc(fRandom);
     595             :       Int_t iTemp = iPart;
     596             : 
     597             :       // custom pdg codes to destinguish direct photons
     598           0 :       if(iPart>=220000 & iPart<=220001) iPart=22;
     599             : 
     600           0 :       fChildWeight=(fDecayer->GetPartialBranchingRatio(iPart))*fParentWeight;           
     601           0 :       TParticlePDG *particle = pDataBase->GetParticle(iPart);
     602           0 :       Float_t am = particle->Mass();
     603             :           
     604           0 :       Rndm(random,2);
     605             : 
     606             : // --- For Exodus --------------------------------//
     607           0 :       Double_t awidth = particle->Width();
     608           0 :       if(awidth>0){
     609           0 :         TF1 rbw("rbw","pow([1],2)*pow([0],2)/(pow(x*x-[0]*[0],2)+pow(x*x*[1]/[0],2))",am-5*awidth,am+5*awidth);
     610           0 :         rbw.SetParameter(0,am);
     611           0 :         rbw.SetParameter(1,awidth);
     612           0 :         am = rbw.GetRandom();
     613           0 :       }
     614             : // -----------------------------------------------//
     615             : 
     616             :       //
     617             :       // y
     618           0 :       ty = TMath::TanH(fYPara->GetRandom());
     619             : 
     620             :       //
     621             :       // pT
     622           0 :       if (fAnalog == kAnalog) {
     623           0 :         pt=fPtPara->GetRandom();
     624           0 :         wgtp=fParentWeight;
     625           0 :         wgtch=fChildWeight;
     626           0 :       } else {
     627           0 :         pt=fPtMin+random[1]*(fPtMax-fPtMin);
     628           0 :         Double_t ptd=pt;
     629           0 :         wgtp=fParentWeight*fPtParaFunc(& ptd, &dummy);
     630           0 :         wgtch=fChildWeight*fPtParaFunc(& ptd, &dummy);
     631           0 :       }
     632           0 :       xmt=sqrt(pt*pt+am*am);
     633           0 :       if (TMath::Abs(ty)==1.) {
     634             :         ty=0.;
     635           0 :         Fatal("AliGenParam", 
     636             :               "Division by 0: Please check you rapidity range !");
     637           0 :       }
     638             :       //
     639             :       // phi
     640             :       //      if(!ipa)
     641             :       //phi=fEvPlane; //align first particle of each event with event plane
     642             :       //else{
     643           0 :       double v2 = fV2Para->Eval(pt);
     644           0 :       fdNdPhi->SetParameter(0,v2);
     645           0 :       fdNdPhi->SetParameter(1,fEvPlane);
     646           0 :       phi=fdNdPhi->GetRandom();
     647             :       //     }
     648             :           
     649           0 :       pl=xmt*ty/sqrt((1.-ty)*(1.+ty));
     650           0 :       theta=TMath::ATan2(pt,pl);
     651             :       // Cut on theta
     652           0 :       if(theta<fThetaMin || theta>fThetaMax) continue;
     653           0 :       ptot=TMath::Sqrt(pt*pt+pl*pl);
     654             :       // Cut on momentum
     655           0 :       if(ptot<fPMin || ptot>fPMax) continue;
     656             :       //
     657           0 :       p[0]=pt*TMath::Cos(phi);
     658           0 :       p[1]=pt*TMath::Sin(phi);
     659             :       p[2]=pl;
     660           0 :       energy=TMath::Sqrt(ptot*ptot+am*am);
     661             : 
     662           0 :       if(fVertexSmear==kPerTrack) {
     663           0 :         Rndm(random,6);
     664           0 :         for (j=0;j<3;j++) {
     665           0 :           origin0[j]=
     666           0 :             fOrigin[j]+fOsigma[j]*TMath::Cos(2*random[2*j]*TMath::Pi())*
     667           0 :             TMath::Sqrt(-2*TMath::Log(random[2*j+1]));
     668             :         }
     669           0 :         Rndm(random,2);
     670           0 :         time0 = fTimeOrigin + fOsigma[2]/TMath::Ccgs()*
     671           0 :           TMath::Cos(2*random[0]*TMath::Pi())*
     672           0 :           TMath::Sqrt(-2*TMath::Log(random[1]));
     673           0 :       }
     674             :           
     675             :       // Looking at fForceDecay : 
     676             :       // if fForceDecay != none Primary particle decays using 
     677             :       // AliPythia and children are tracked by GEANT
     678             :       //
     679             :       // if fForceDecay == none Primary particle is tracked by GEANT 
     680             :       // (In the latest, make sure that GEANT actually does all the decays you want)      
     681             :       //
     682             :       Bool_t decayed = kFALSE;
     683             :           
     684             : 
     685           0 :       if (fForceDecay != kNoDecay) {
     686             :         // Using lujet to decay particle
     687           0 :         TLorentzVector pmom(p[0], p[1], p[2], energy);
     688           0 :         fDecayer->Decay(iPart,&pmom);
     689             :         //
     690             :         // select decay particles
     691           0 :         Int_t np=fDecayer->ImportParticles(particles);
     692             : 
     693             :         iPart=iTemp;
     694           0 :         if(iPart>=220000 & iPart<=220001){
     695           0 :           TParticle *gamma = (TParticle *)particles->At(0);
     696           0 :           gamma->SetPdgCode(iPart);
     697           0 :           np=VirtualGammaPairProduction(particles,np);
     698           0 :         }
     699           0 :         if(fForceConv) np=ForceGammaConversion(particles,np);
     700             : 
     701             :         //  Selecting  GeometryAcceptance for particles fPdgCodeParticleforAcceptanceCut;
     702           0 :         if (fGeometryAcceptance) 
     703           0 :           if (!CheckAcceptanceGeometry(np,particles)) continue;
     704             :         Int_t ncsel=0;
     705           0 :         Int_t pFlag    [np];
     706           0 :         Int_t pParent  [np];
     707           0 :         Int_t pSelected[np];
     708           0 :         Int_t trackIt  [np];
     709             : 
     710           0 :         for (i=0; i<np; i++) {
     711           0 :           pFlag[i]     =  0;
     712           0 :           pSelected[i] =  0;
     713           0 :           pParent[i]   = -1;
     714             :         }
     715             :               
     716           0 :         if (np >1) {
     717             :           decayed = kTRUE;
     718             :           TParticle* iparticle =  0;
     719             :           Int_t ipF, ipL;
     720           0 :           for (i = 1; i<np ; i++) {
     721           0 :             trackIt[i] = 1;
     722           0 :             iparticle = (TParticle *) particles->At(i);
     723           0 :             Int_t kf = iparticle->GetPdgCode();
     724           0 :             Int_t ks = iparticle->GetStatusCode();
     725             :             // flagged particle
     726             : 
     727           0 :             if(!fPreserveFullDecayChain){
     728           0 :               if (pFlag[i] == 1) {
     729           0 :                 ipF = iparticle->GetFirstDaughter();
     730           0 :                 ipL = iparticle->GetLastDaughter();
     731           0 :                 if (ipF > 0) for (j=ipF-1; j<ipL; j++) pFlag[j]=1;
     732           0 :                 continue;
     733             :               }
     734             :             }
     735             :             // flag decay products of particles with long life-time (c tau > .3 mum)               
     736             :                       
     737           0 :             if (ks != 1) { 
     738             :               //                          TParticlePDG *particle = pDataBase->GetParticle(kf);
     739             :                           
     740           0 :               Double_t lifeTime = fDecayer->GetLifetime(kf);
     741             :               //                          Double_t mass     = particle->Mass();
     742             :               //                          Double_t width    = particle->Width();
     743           0 :               if (lifeTime > (Double_t) fMaxLifeTime) {
     744           0 :                 ipF = iparticle->GetFirstDaughter();
     745           0 :                 ipL = iparticle->GetLastDaughter();  
     746           0 :                 if (ipF > 0) for (j=ipF-1; j<ipL; j++) pFlag[j]=1;
     747             :               } else{
     748           0 :                 trackIt[i]     = 0;
     749           0 :                 pSelected[i]   = 1;
     750             :               }
     751           0 :             } // ks==1 ?
     752             :             //
     753             :             // children
     754             :                       
     755           0 :             if ((ChildSelected(TMath::Abs(kf)) || fForceDecay == kAll || fSelectAll) && trackIt[i])
     756             :               {
     757           0 :                 if (fCutOnChild) {
     758           0 :                   pc[0]=iparticle->Px();
     759           0 :                   pc[1]=iparticle->Py();
     760           0 :                   pc[2]=iparticle->Pz();
     761           0 :                   Bool_t  childok = KinematicSelection(iparticle, 1);
     762           0 :                   if(childok) {
     763           0 :                     pSelected[i]  = 1;
     764           0 :                     ncsel++;
     765           0 :                   } else {
     766           0 :                     if(!fKeepIfOneChildSelected){
     767             :                       ncsel=-1;
     768           0 :                       break;
     769             :                     }
     770             :                   } // child kine cuts
     771           0 :                 } else {
     772           0 :                   pSelected[i]  = 1;
     773           0 :                   ncsel++;
     774             :                 } // if child selection
     775             :               } // select muon
     776           0 :           } // decay particle loop
     777           0 :         } // if decay products
     778             :               
     779             :         Int_t iparent;
     780             :               
     781           0 :         if (fKeepParent || (fCutOnChild && ncsel >0) || !fCutOnChild){
     782             :           //
     783             :           // Parent
     784             :                   
     785             : // --- For Exodus --------------------------------//
     786             :           //PushTrack(0, -1, iPart, p, origin0, polar, time0, kPPrimary, nt, wgtp, ((decayed)? 11 : 1));
     787           0 : PushTrack(0, -1, iPart, p[0],p[1],p[2],energy,origin0[0],origin0[1],origin0[2],time0,polar[0],polar[1],polar[2],kPPrimary, nt, wgtp, ((decayed)? 11 : 1));
     788             : // -----------------------------------------------//
     789             : 
     790           0 :           pParent[0] = nt;
     791           0 :           KeepTrack(nt); 
     792           0 :           fNprimaries++;
     793             :                   
     794             :           //but count is as "generated" particle" only if it produced child(s) within cut
     795           0 :           if ((fCutOnChild && ncsel >0) || !fCutOnChild) {
     796           0 :             ipa++;
     797           0 :           }
     798             :                   
     799             :           //
     800             :           // Decay Products
     801             :           //              
     802           0 :           for (i = 1; i < np; i++) {
     803           0 :             if (pSelected[i]) {
     804           0 :               TParticle* iparticle = (TParticle *) particles->At(i);
     805           0 :               Int_t kf   = iparticle->GetPdgCode();
     806           0 :               Int_t ksc  = iparticle->GetStatusCode();
     807           0 :               Int_t jpa  = iparticle->GetFirstMother()-1;
     808           0 :               Double_t weight = iparticle->GetWeight();  
     809           0 :               och[0] = origin0[0]+iparticle->Vx();
     810           0 :               och[1] = origin0[1]+iparticle->Vy();
     811           0 :               och[2] = origin0[2]+iparticle->Vz();
     812           0 :               pc[0]  = iparticle->Px();
     813           0 :               pc[1]  = iparticle->Py();
     814           0 :               pc[2]  = iparticle->Pz();
     815           0 :               Double_t ec   = iparticle->Energy();
     816             :               
     817           0 :               if (jpa > -1) {
     818           0 :                 iparent = pParent[jpa];
     819           0 :               } else {
     820             :                 iparent = -1;
     821             :               }
     822             :               
     823           0 :               PushTrack(fTrackIt * trackIt[i], iparent, kf, pc[0], pc[1], pc[2], ec, 
     824           0 :                         och[0], och[1], och[2], time0 + iparticle->T(), 
     825           0 :                         polar[0], polar[1], polar[2], kPDecay, nt, weight*wgtch, ksc);
     826             : 
     827             :               //              PushTrack(fTrackIt * trackIt[i], iparent, kf,
     828             :               //                pc, och, polar,
     829             :               //        time0 + iparticle->T(), kPDecay, nt, weight*wgtch, ksc);
     830             : 
     831             : 
     832           0 :               pParent[i] = nt;
     833           0 :               KeepTrack(nt); 
     834           0 :               fNprimaries++;
     835           0 :             } // Selected
     836             :           } // Particle loop 
     837             :         }  // Decays by Lujet
     838           0 :         particles->Clear();
     839           0 :       } // kinematic selection
     840             :       else  // nodecay option, so parent will be tracked by GEANT (pions, kaons, eta, omegas, baryons)
     841             :         {
     842           0 :           PushTrack(fTrackIt, -1, iPart, p[0], p[1], p[2], energy, 
     843           0 :                     origin0[0], origin0[1], origin0[2], time0, 
     844             :                     polar[0], polar[1], polar[2], 
     845             :                     kPPrimary, nt, wgtp, 1);
     846             : 
     847             :           //      gAlice->GetMCApp()->
     848             :           //  PushTrack(fTrackIt,-1,iPart,p,origin0,polar,time0,kPPrimary,nt,wgtp, 1);
     849             : 
     850           0 :           ipa++; 
     851           0 :           fNprimaries++;
     852             :         }
     853           0 :       break;
     854             :     } // while
     855             :   } // event loop
     856             :   
     857           0 :   SetHighWaterMark(nt);
     858             : 
     859           0 :   AliGenEventHeader* header = new AliGenEventHeader("PARAM");
     860           0 :   header->SetPrimaryVertex(fVertex);
     861           0 :   header->SetInteractionTime(fTime);
     862           0 :   header->SetNProduced(fNprimaries);
     863           0 :   AddHeader(header);
     864           0 : }
     865             : //____________________________________________________________________________________
     866             : Float_t AliGenParam::GetRelativeArea(Float_t ptMin, Float_t ptMax, Float_t yMin, Float_t yMax, Float_t phiMin, Float_t phiMax)
     867             : {
     868             :   //
     869             :   // Normalisation for selected kinematic region
     870             :   //
     871             : #if ROOT_VERSION_CODE < ROOT_VERSION(5,99,0)
     872             :   Float_t ratio =
     873           0 :     fPtPara->Integral(ptMin,ptMax,(Double_t *)0,1.e-6) / fPtPara->Integral( fPtPara->GetXmin(), fPtPara->GetXmax(),(Double_t *)0,1.e-6) *
     874           0 :     fYPara->Integral(yMin,yMax,(Double_t *)0,1.e-6)/fYPara->Integral(fYPara->GetXmin(),fYPara->GetXmax(),(Double_t *)0,1.e-6)   *
     875           0 :     (phiMax-phiMin)/360.;
     876             : #else
     877             :   Float_t ratio =
     878             :     fPtPara->Integral(ptMin,ptMax,1.e-6) / fPtPara->Integral( fPtPara->GetXmin(), fPtPara->GetXmax(),1.e-6) *
     879             :     fYPara->Integral(yMin,yMax,1.e-6)/fYPara->Integral(fYPara->GetXmin(),fYPara->GetXmax(),1.e-6)   *
     880             :     (phiMax-phiMin)/360.;
     881             : #endif
     882           0 :   return TMath::Abs(ratio);
     883             : }
     884             : 
     885             : //____________________________________________________________________________________
     886             : 
     887             : void AliGenParam::Draw( const char * /*opt*/)
     888             : {
     889             :   //
     890             :   // Draw the pT and y Distributions
     891             :   //
     892           0 :   TCanvas *c0 = new TCanvas("c0","Canvas 0",400,10,600,700);
     893           0 :   c0->Divide(2,1);
     894           0 :   c0->cd(1);
     895           0 :   fPtPara->Draw();
     896           0 :   fPtPara->GetHistogram()->SetXTitle("p_{T} (GeV)");     
     897           0 :   c0->cd(2);
     898           0 :   fYPara->Draw();
     899           0 :   fYPara->GetHistogram()->SetXTitle("y");     
     900           0 : }
     901             : 
     902             : 
     903             : 
     904             : 

Generated by: LCOV version 1.11