07a29789b074b42d1b832a078c245428561016f9
[u/mrichter/AliRoot.git] / EVGEN / AliGenCosmicsParam.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-2007, 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
17 // Generator for muons according to kinematic parametrizations at ALICE
18 // (not at the surface).
19 // Origin: andrea.dainese@lnl.infn.it
20
21 #include <TParticle.h>
22 #include <TF1.h>
23
24 #include "AliRun.h"
25 #include "AliESDtrack.h"
26 #include "AliESDVertex.h"
27 #include "AliGenCosmicsParam.h"
28
29 ClassImp(AliGenCosmicsParam)
30
31 //-----------------------------------------------------------------------------
32 AliGenCosmicsParam::AliGenCosmicsParam():
33 AliGenerator(),
34 fParamMI(kFALSE),
35 fParamACORDE(kFALSE),
36 fYOrigin(600.),
37 fMaxAngleWRTVertical(-99.),
38 fBkG(0.),
39 fTPC(kFALSE),
40 fITS(kFALSE),
41 fSPDinner(kFALSE),
42 fSPDouter(kFALSE),
43 fSDDinner(kFALSE),
44 fSDDouter(kFALSE),
45 fSSDinner(kFALSE),
46 fSSDouter(kFALSE),
47 fACORDE(kFALSE),
48 fACORDE4ITS(kFALSE)
49 {
50   //
51   // Default constructor
52   //
53   SetNumberParticles(1);
54 }
55 //-----------------------------------------------------------------------------
56 void AliGenCosmicsParam::Generate()
57 {
58   //
59   // Generate one muon
60   //
61   
62   //
63   Float_t origin[3];
64   Float_t p[3];
65   Int_t nt;
66   Double_t ptot=0,pt=0,angleWRTVertical=0;
67   Bool_t okMom=kFALSE,okAngle=kFALSE;
68   //
69   Float_t rtrigger=1000.0,ztrigger=600.0;
70   if(fTPC)      { rtrigger=250.0; ztrigger=250.0; }
71   if(fITS)      { rtrigger=50.0; ztrigger=50.0; }
72   if(fSPDinner) { rtrigger=3.5; ztrigger=14.0; }
73   if(fSPDouter) { rtrigger=6.5; ztrigger=14.0; }
74   if(fSDDinner) { rtrigger=14.0; ztrigger=21.0; }
75   if(fSDDouter) { rtrigger=23.0; ztrigger=29.0; }
76   if(fSSDinner) { rtrigger=37.0; ztrigger=42.0; }
77   if(fSSDouter) { rtrigger=42.0; ztrigger=48.0; }
78
79
80   // mu+ or mu-
81   Float_t muMinusFraction = 4./9.; // mu+/mu- = 1.25
82   Int_t ipart;
83
84   Int_t trials=0;
85   Int_t npart=0;
86
87   while (npart<fNpart) {
88
89     if(gRandom->Rndm()<muMinusFraction) {
90       ipart = 13; // mu-
91     } else {
92       ipart = -13; // mu+
93     }
94
95     if(fParamACORDE) { // extracted from AliGenACORDE events
96       // sample total momentum only once (to speed up)
97       TF1 *dNdpACORDE = new TF1("dNdpACORDE","x/(1.+(x/12.8)*(x/12.8))^1.96",fPMin,fPMax);
98       ptot = (Double_t)dNdpACORDE->GetRandom();
99       delete dNdpACORDE;
100       dNdpACORDE = 0;
101     }
102
103     while(1) {
104       trials++;
105       // origin
106       origin[0]  = (fYOrigin*TMath::Tan(fMaxAngleWRTVertical)+rtrigger)*(-1.+2.*gRandom->Rndm());
107       origin[1]  = fYOrigin;
108       origin[2]  = (fYOrigin*TMath::Tan(fMaxAngleWRTVertical)+ztrigger)*(-1.+2.*gRandom->Rndm());
109       
110       // momentum
111       while(1) {
112         okMom=kFALSE; okAngle=kFALSE;
113         
114         if(fParamMI) { // parametrization by M.Ivanov of LEP cosmics data
115           Float_t       pref  = 1. + gRandom->Exp(30.);
116           p[1] = -pref; 
117           p[0] = gRandom->Gaus(0.0,0.2)*pref;
118           p[2] = gRandom->Gaus(0.0,0.2)*pref;
119           if(gRandom->Rndm()>0.9) {
120             p[0] = gRandom->Gaus(0.0,0.4)*pref;
121             p[2] = gRandom->Gaus(0.0,0.4)*pref;
122           }
123           ptot=TMath::Sqrt(p[0]*p[0]+p[1]*p[1]+p[2]*p[2]);
124           pt=TMath::Sqrt(p[0]*p[0]+p[1]*p[1]);
125         } else if(fParamACORDE) { // extracted from AliGenACORDE events
126           Float_t theta,phi;
127           while(1) {
128             theta = gRandom->Gaus(0.5*TMath::Pi(),0.42);
129             if(TMath::Abs(theta-0.5*TMath::Pi())<fMaxAngleWRTVertical) break;
130           }
131           while(1) {
132             phi = gRandom->Gaus(-0.5*TMath::Pi(),0.42);
133             if(TMath::Abs(phi+0.5*TMath::Pi())<fMaxAngleWRTVertical) break;
134           }
135           pt = ptot*TMath::Sin(theta);
136           p[0] = pt*TMath::Cos(phi); 
137           p[1] = pt*TMath::Sin(phi); 
138           p[2] = ptot*TMath::Cos(theta);
139         } else {
140           AliFatal("Parametrization not set: use SetParamMI or SetParamACORDE");
141         }
142         
143         
144         // check kinematic cuts
145         if(TestBit(kMomentumRange)) {
146           if(ptot>fPMin && ptot<fPMax) okMom=kTRUE;
147         } else {
148           okMom=kTRUE;
149         }
150
151         angleWRTVertical=TMath::ACos(TMath::Abs(p[1])/ptot); // acos(|py|/ptot)
152         if(angleWRTVertical<fMaxAngleWRTVertical) okAngle=kTRUE;
153         
154         if(okAngle&&okMom) break;
155       }
156
157       // acceptance trigger
158       if(IntersectCylinder(rtrigger,ztrigger,ipart,origin,p)) {
159         if(!fACORDE) {
160           break; 
161         } else {
162           if(IntersectACORDE(ipart,origin,p)) break;
163         }
164       }
165       //
166     }
167
168     Float_t polarization[3]= {0,0,0};
169     PushTrack(fTrackIt,-1,ipart,p,origin,polarization,0,kPPrimary,nt);
170     npart++; 
171     //printf("TRIALS %d\n",trials);
172   }
173
174   return;
175 }
176 //-----------------------------------------------------------------------------
177 void AliGenCosmicsParam::Init()
178 {
179   // 
180   // Initialisation, check consistency of selected ranges
181   //
182   if(TestBit(kPtRange)) 
183     AliFatal("You cannot set the pt range for this generator! Only momentum range");
184   if(fPMin<8.) { 
185     fPMin=8.; 
186     if(TestBit(kMomentumRange)) 
187       AliWarning("Minimum momentum cannot be < 8 GeV/c"); 
188   }
189   if(fMaxAngleWRTVertical<0.) 
190     AliFatal("You must use SetMaxAngleWRTVertical() instead of SetThetaRange(), SetPhiRange()");
191
192   printf("************ AliGenCosmicsParam ****************\n");
193   printf("***** Muons generated at Y = %f cm\n",fYOrigin);
194   printf("************************************************\n");
195
196   return;
197 }
198 //-----------------------------------------------------------------------------
199 Bool_t AliGenCosmicsParam::IntersectCylinder(Float_t r,Float_t z,Int_t pdg,
200                                              Float_t o[3],Float_t p[3]) const
201 {
202   //
203   // Intersection between muon and cylinder [-z,+z] with radius r
204   //
205
206   Float_t en = TMath::Sqrt(0.105*0.105+p[0]*p[0]+p[1]*p[1]+p[2]*p[2]);
207   TParticle part(pdg,0,0,0,0,0,p[0],p[1],p[2],en,o[0],o[1],o[2],0);
208   AliESDtrack track(&part);
209   Double_t pos[3]={0.,0.,0.},sigma[3]={0.,0.,0.};
210   AliESDVertex origin(pos,sigma);
211
212   track.RelateToVertex(&origin,fBkG,10000.);
213
214   Float_t d0z0[2],covd0z0[3];
215   track.GetImpactParameters(d0z0,covd0z0);
216
217   // check rphi 
218   if(TMath::Abs(d0z0[0])>r) return kFALSE;
219   // check z
220   if(TMath::Abs(d0z0[1])>z) return kFALSE;
221
222   /*
223     if(TMath::Abs(fB)<0.01) {  // NO FIELD
224     Float_t drphi = TMath::Abs(o[1]-p[1]/p[0]*o[0])/
225     TMath::Sqrt(p[1]*p[1]/p[0]/p[0]+1.);
226     if(drphi>r) return kFALSE;
227     Float_t dz = o[2]-p[2]/p[0]*o[0]+p[2]/p[0]*
228     (p[1]*p[1]/p[0]/p[0]*o[0]-p[1]/p[0]*o[1])/(1.+p[1]*p[1]/p[0]/p[0]);
229     if(TMath::Abs(dz)>z) return kFALSE;
230     }
231   */
232
233   return kTRUE;
234 }
235 //-----------------------------------------------------------------------------
236 Bool_t AliGenCosmicsParam::IntersectACORDE(Int_t pdg,
237                                            Float_t o[3],Float_t p[3]) const
238 {
239   //
240   // Intersection between muon and ACORDE (very rough)
241   //
242
243   Float_t en = TMath::Sqrt(0.105*0.105+p[0]*p[0]+p[1]*p[1]+p[2]*p[2]);
244   TParticle part(pdg,0,0,0,0,0,p[0],p[1],p[2],en,o[0],o[1],o[2],0);
245   AliESDtrack track(&part);
246
247   Float_t rACORDE=800.0,xACORDE=750.0,zACORDE=500.0;
248   if(fACORDE4ITS) { xACORDE=100.0; zACORDE=100.0; }
249
250   Double_t xyz[3];
251   track.GetXYZAt(rACORDE,fBkG,xyz);
252
253   // check global x 
254   if(TMath::Abs(xyz[0]) > xACORDE) return kFALSE;
255   // check global z
256   if(TMath::Abs(xyz[2]) > zACORDE) return kFALSE;
257
258   return kTRUE;
259 }
260 //-----------------------------------------------------------------------------