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