Include the new TRD classes
[u/mrichter/AliRoot.git] / TRD / AliTRDv1.cxx
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 /*
17 $Log$
18 Revision 1.16.4.1  2000/02/28 18:04:35  cblume
19 Change to new hit version, introduce geometry class, and move digitization and clustering to AliTRDdigitizer/AliTRDclusterizerV1
20
21 Revision 1.16  1999/11/05 22:50:28  fca
22 Do not use Atan, removed from ROOT too
23
24 Revision 1.15  1999/11/02 17:20:19  fca
25 initialise nbytes before using it
26
27 Revision 1.14  1999/11/02 17:15:54  fca
28 Correct ansi scoping not accepted by HP compilers
29
30 Revision 1.13  1999/11/02 17:14:51  fca
31 Correct ansi scoping not accepted by HP compilers
32
33 Revision 1.12  1999/11/02 16:35:56  fca
34 New version of TRD introduced
35
36 Revision 1.11  1999/11/01 20:41:51  fca
37 Added protections against using the wrong version of FRAME
38
39 Revision 1.10  1999/09/29 09:24:35  fca
40 Introduction of the Copyright and cvs Log
41
42 */
43
44 ///////////////////////////////////////////////////////////////////////////////
45 //                                                                           //
46 //  Transition Radiation Detector version 2 -- slow simulator                //
47 //                                                                           //
48 //Begin_Html
49 /*
50 <img src="picts/AliTRDfullClass.gif">
51 */
52 //End_Html
53 //                                                                           //
54 //                                                                           //
55 ///////////////////////////////////////////////////////////////////////////////
56
57 #include <TMath.h>
58 #include <TVector.h>
59 #include <TRandom.h>
60
61 #include "AliRun.h"
62 #include "AliMC.h"
63 #include "AliConst.h"
64
65 #include "AliTRDv1.h"
66 #include "AliTRDmatrix.h"
67 #include "AliTRDgeometry.h"
68
69 ClassImp(AliTRDv1)
70
71 //_____________________________________________________________________________
72 AliTRDv1::AliTRDv1(const char *name, const char *title) 
73          :AliTRD(name, title) 
74 {
75   //
76   // Standard constructor for Transition Radiation Detector version 1
77   //
78
79   fIdSens        =  0;
80
81   fIdChamber1    =  0;
82   fIdChamber2    =  0;
83   fIdChamber3    =  0;
84
85   fSensSelect    =  0;
86   fSensPlane     = -1;
87   fSensChamber   = -1;
88   fSensSector    = -1;
89
90   fDeltaE        = NULL;
91
92   SetBufferSize(128000);
93
94 }
95
96 //_____________________________________________________________________________
97 AliTRDv1::~AliTRDv1()
98 {
99
100   if (fDeltaE) delete fDeltaE;
101
102 }
103  
104 //_____________________________________________________________________________
105 void AliTRDv1::CreateGeometry()
106 {
107   //
108   // Create the GEANT geometry for the Transition Radiation Detector - Version 1
109   // This version covers the full azimuth. 
110   //
111
112   // Check that FRAME is there otherwise we have no place where to put the TRD
113   AliModule* FRAME = gAlice->GetModule("FRAME");
114   if (!FRAME) return;
115
116   // Define the chambers
117   AliTRD::CreateGeometry();
118
119 }
120
121 //_____________________________________________________________________________
122 void AliTRDv1::CreateMaterials()
123 {
124   //
125   // Create materials for the Transition Radiation Detector version 1
126   //
127
128   AliTRD::CreateMaterials();
129
130 }
131
132 //_____________________________________________________________________________
133 void AliTRDv1::Init() 
134 {
135   //
136   // Initialise Transition Radiation Detector after geometry has been built.
137   //
138
139   AliTRD::Init();
140
141   printf("          Slow simulator\n\n");
142   if (fSensSelect) {
143     if (fSensPlane   >= 0)
144       printf("          Only plane %d is sensitive\n",fSensPlane);
145     if (fSensChamber >= 0)   
146       printf("          Only chamber %d is sensitive\n",fSensChamber);
147     if (fSensSector  >= 0)
148       printf("          Only sector %d is sensitive\n",fSensSector);
149   }
150   printf("\n");
151
152   // First ionization potential (eV) for the gas mixture (90% Xe + 10% CO2)
153   const Float_t kPoti = 12.1;
154   // Maximum energy (50 keV);
155   const Float_t kEend = 50000.0;
156   // Ermilova distribution for the delta-ray spectrum
157   Float_t Poti = TMath::Log(kPoti);
158   Float_t Eend = TMath::Log(kEend);
159   fDeltaE  = new TF1("deltae",Ermilova,Poti,Eend,0);
160
161   // Identifier of the sensitive volume (drift region)
162   fIdSens     = gMC->VolId("UL05");
163
164   // Identifier of the TRD-driftchambers
165   fIdChamber1 = gMC->VolId("UCIO");
166   fIdChamber2 = gMC->VolId("UCIM");
167   fIdChamber3 = gMC->VolId("UCII");
168
169   for (Int_t i = 0; i < 80; i++) printf("*");
170   printf("\n");
171
172 }
173
174 //_____________________________________________________________________________
175 void AliTRDv1::SetSensPlane(Int_t iplane)
176 {
177   //
178   // Defines the hit-sensitive plane (0-5)
179   //
180
181   if ((iplane < 0) || (iplane > 5)) {
182     printf("Wrong input value: %d\n",iplane);
183     printf("Use standard setting\n");
184     fSensPlane  = -1;
185     fSensSelect =  0;
186     return;
187   }
188
189   fSensSelect = 1;
190   fSensPlane  = iplane;
191
192 }
193
194 //_____________________________________________________________________________
195 void AliTRDv1::SetSensChamber(Int_t ichamber)
196 {
197   //
198   // Defines the hit-sensitive chamber (0-4)
199   //
200
201   if ((ichamber < 0) || (ichamber > 4)) {
202     printf("Wrong input value: %d\n",ichamber);
203     printf("Use standard setting\n");
204     fSensChamber = -1;
205     fSensSelect  =  0;
206     return;
207   }
208
209   fSensSelect  = 1;
210   fSensChamber = ichamber;
211
212 }
213
214 //_____________________________________________________________________________
215 void AliTRDv1::SetSensSector(Int_t isector)
216 {
217   //
218   // Defines the hit-sensitive sector (0-17)
219   //
220
221   if ((isector < 0) || (isector > 17)) {
222     printf("Wrong input value: %d\n",isector);
223     printf("Use standard setting\n");
224     fSensSector = -1;
225     fSensSelect =  0;
226     return;
227   }
228
229   fSensSelect = 1;
230   fSensSector = isector;
231
232 }
233
234 //_____________________________________________________________________________
235 void AliTRDv1::StepManager()
236 {
237   //
238   // Slow simulator. Every charged track produces electron cluster as hits 
239   // along its path across the drift volume. The step size is set acording
240   // to Bethe-Bloch. The energy distribution of the delta electrons follows
241   // a spectrum taken from Ermilova et al.
242   //
243
244   Int_t    iIdSens, icSens;
245   Int_t    iIdSpace, icSpace;
246   Int_t    iIdChamber, icChamber;
247   Int_t    pla = 0;
248   Int_t    cha = 0;
249   Int_t    sec = 0;
250   Int_t    iPdg;
251
252   Float_t  hits[4];
253   Float_t  random[1];
254   Float_t  charge;
255   Float_t  aMass;
256
257   Double_t pTot;
258   Double_t qTot;
259   Double_t eDelta;
260   Double_t betaGamma, pp;
261
262   TLorentzVector pos, mom;
263   TClonesArray  &lhits = *fHits;
264
265   const Double_t kBig     = 1.0E+12;
266
267   // Ionization energy
268   const Float_t  kWion    = 22.04;
269   // Maximum energy for e+ e- g for the step-size calculation
270   const Float_t  kPTotMax = 0.002;
271   // Plateau value of the energy-loss for electron in xenon
272   // taken from: Allison + Comb, Ann. Rev. Nucl. Sci. (1980), 30, 253
273   //const Double_t kPlateau = 1.70;
274   // the averaged value (26/3/99)
275   const Float_t  kPlateau = 1.55;
276   // dN1/dx|min for the gas mixture (90% Xe + 10% CO2)
277   const Float_t  kPrim    = 48.0;
278   // First ionization potential (eV) for the gas mixture (90% Xe + 10% CO2)
279   const Float_t  kPoti    = 12.1;
280
281   // PDG code electron
282   const Int_t    pdgElectron = 11;
283
284   // Set the maximum step size to a very large number for all 
285   // neutral particles and those outside the driftvolume
286   gMC->SetMaxStep(kBig); 
287
288   // Use only charged tracks 
289   if (( gMC->TrackCharge()       ) &&
290       (!gMC->IsTrackStop()       ) && 
291       (!gMC->IsTrackDisappeared())) {
292
293     // Inside a sensitive volume?
294     iIdSens = gMC->CurrentVolID(icSens);
295     if (iIdSens == fIdSens) { 
296
297       iIdSpace   = gMC->CurrentVolOffID(4,icSpace  );
298       iIdChamber = gMC->CurrentVolOffID(1,icChamber);
299
300       // Calculate the energy of the delta-electrons
301       eDelta = TMath::Exp(fDeltaE->GetRandom()) - kPoti;
302       eDelta = TMath::Max(eDelta,0.0);
303
304       // The number of secondary electrons created
305       qTot = (Double_t) ((Int_t) (eDelta / kWion) + 1);
306
307       // The hit coordinates and charge
308       gMC->TrackPosition(pos);
309       hits[0] = pos[0];
310       hits[1] = pos[1];
311       hits[2] = pos[2];
312       hits[3] = qTot;
313
314       // The sector number (0 - 17)
315       // The numbering goes clockwise and starts at y = 0
316       Float_t phi = kRaddeg*TMath::ATan2(pos[0],pos[1]);
317       if (phi < 90.) 
318         phi = phi + 270.;
319       else
320         phi = phi -  90.;
321       sec = ((Int_t) (phi / 20));
322
323       // The chamber number 
324       //   0: outer left
325       //   1: middle left
326       //   2: inner
327       //   3: middle right
328       //   4: outer right
329       if      (iIdChamber == fIdChamber1)
330         cha = (hits[2] < 0 ? 0 : 4);
331       else if (iIdChamber == fIdChamber2)       
332         cha = (hits[2] < 0 ? 1 : 3);
333       else if (iIdChamber == fIdChamber3)       
334         cha = 2;
335
336       // The plane number
337       // The numbering starts at the innermost plane
338       pla = icChamber - TMath::Nint((Float_t) (icChamber / 7)) * 6 - 1;
339
340       // Check on selected volumes
341       Int_t addthishit = 1;
342       if (fSensSelect) {
343         if ((fSensPlane)   && (pla != fSensPlane  )) addthishit = 0;
344         if ((fSensChamber) && (cha != fSensChamber)) addthishit = 0;
345         if ((fSensSector)  && (sec != fSensSector )) addthishit = 0;
346       }
347
348       // Add this hit
349       if (addthishit) {
350
351         new(lhits[fNhits++]) AliTRDhit(fIshunt
352                                       ,gAlice->CurrentTrack()
353                                       ,fGeometry->GetDetector(pla,cha,sec)
354                                       ,hits);
355
356         // The energy loss according to Bethe Bloch
357         gMC->TrackMomentum(mom);
358         pTot = mom.Rho();
359         iPdg = TMath::Abs(gMC->TrackPid());
360         if ( (iPdg != pdgElectron) ||
361             ((iPdg == pdgElectron) && (pTot < kPTotMax))) {
362           aMass     = gMC->TrackMass();
363           betaGamma = pTot / aMass;
364           pp        = kPrim * BetheBloch(betaGamma);
365           // Take charge > 1 into account
366           charge = gMC->TrackCharge();
367           if (TMath::Abs(charge) > 1) pp = pp * charge*charge;
368         }
369         // Electrons above 20 Mev/c are at the plateau
370         else {
371           pp = kPrim * kPlateau;
372         }
373       
374         // Calculate the maximum step size for the next tracking step
375         if (pp > 0) {
376           do 
377             gMC->Rndm(random,1);
378           while ((random[0] == 1.) || (random[0] == 0.));
379           gMC->SetMaxStep( - TMath::Log(random[0]) / pp);
380         }
381
382       }
383       else {
384         // set step size to maximal value
385         gMC->SetMaxStep(kBig); 
386       }
387
388     }
389
390   }
391
392 }
393
394 //_____________________________________________________________________________
395 Double_t AliTRDv1::BetheBloch(Double_t bg) 
396 {
397   //
398   // Parametrization of the Bethe-Bloch-curve
399   // The parametrization is the same as for the TPC and is taken from Lehrhaus.
400   //
401
402   // This parameters have been adjusted to averaged values from GEANT
403   const Double_t kP1 = 7.17960e-02;
404   const Double_t kP2 = 8.54196;
405   const Double_t kP3 = 1.38065e-06;
406   const Double_t kP4 = 5.30972;
407   const Double_t kP5 = 2.83798;
408
409   // This parameters have been adjusted to Xe-data found in:
410   // Allison & Cobb, Ann. Rev. Nucl. Sci. (1980), 30, 253
411   //const Double_t kP1 = 0.76176E-1;
412   //const Double_t kP2 = 10.632;
413   //const Double_t kP3 = 3.17983E-6;
414   //const Double_t kP4 = 1.8631;
415   //const Double_t kP5 = 1.9479;
416
417   if (bg > 0) {
418     Double_t yy = bg / TMath::Sqrt(1. + bg*bg);
419     Double_t aa = TMath::Power(yy,kP4);
420     Double_t bb = TMath::Power((1./bg),kP5);
421              bb = TMath::Log(kP3 + bb);
422     return ((kP2 - aa - bb)*kP1 / aa);
423   }
424   else
425     return 0;
426
427 }
428
429 //_____________________________________________________________________________
430 Double_t Ermilova(Double_t *x, Double_t *)
431 {
432   //
433   // Calculates the delta-ray energy distribution according to Ermilova.
434   // Logarithmic scale !
435   //
436
437   Double_t energy;
438   Double_t dpos;
439   Double_t dnde;
440
441   Int_t    pos1, pos2;
442
443   const Int_t nV = 31;
444
445   Float_t vxe[nV] = { 2.3026, 2.9957, 3.4012, 3.6889, 3.9120  
446                     , 4.0943, 4.2485, 4.3820, 4.4998, 4.6052
447                     , 4.7005, 5.0752, 5.2983, 5.7038, 5.9915
448                     , 6.2146, 6.5221, 6.9078, 7.3132, 7.6009
449                     , 8.0064, 8.5172, 8.6995, 8.9872, 9.2103
450                     , 9.4727, 9.9035,10.3735,10.5966,10.8198
451                     ,11.5129 };
452
453   Float_t vye[nV] = { 80.0  , 31.0  , 23.3  , 21.1  , 21.0
454                     , 20.9  , 20.8  , 20.0  , 16.0  , 11.0
455                     ,  8.0  ,  6.0  ,  5.2  ,  4.6  ,  4.0
456                     ,  3.5  ,  3.0  ,  1.4  ,  0.67 ,  0.44
457                     ,  0.3  ,  0.18 ,  0.12 ,  0.08 ,  0.056
458                     ,  0.04 ,  0.023,  0.015,  0.011,  0.01
459                     ,  0.004 };
460
461   energy = x[0];
462
463   // Find the position 
464   pos1 = pos2 = 0;
465   dpos = 0;
466   do {
467     dpos = energy - vxe[pos2++];
468   } 
469   while (dpos > 0);
470   pos2--; 
471   if (pos2 > nV) pos2 = nV;
472   pos1 = pos2 - 1;
473
474   // Differentiate between the sampling points
475   dnde = (vye[pos1] - vye[pos2]) / (vxe[pos2] - vxe[pos1]);
476
477   return dnde;
478
479 }