]> git.uio.no Git - u/mrichter/AliRoot.git/blob - TRD/AliTRDv1.cxx
Removing AliMC and AliMCProcess
[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.35  2002/10/14 14:57:44  hristov
19 Merging the VirtualMC branch to the main development branch (HEAD)
20
21 Revision 1.33.6.2  2002/07/24 10:09:31  alibrary
22 Updating VirtualMC
23
24 Revision 1.34  2002/06/13 08:11:56  cblume
25 Add the track references
26
27 Revision 1.33  2002/02/20 14:01:40  hristov
28 Compare a TString with a string, otherwise the conversion cannot be done on Sun
29
30 Revision 1.32  2002/02/13 16:58:37  cblume
31 Bug fix reported by Jiri. Make atoi input zero terminated in StepManager()
32
33 Revision 1.31  2002/02/11 14:25:27  cblume
34 Geometry update, compressed hit structure
35
36 Revision 1.30  2001/05/21 16:45:47  hristov
37 Last minute changes (C.Blume)
38
39 Revision 1.29  2001/05/16 14:57:28  alibrary
40 New files for folders and Stack
41
42 Revision 1.28  2001/05/07 08:03:22  cblume
43 Generate also hits in the amplification region
44
45 Revision 1.27  2001/03/30 14:40:15  cblume
46 Update of the digitization parameter
47
48 Revision 1.26  2000/11/30 17:38:08  cblume
49 Changes to get in line with new STEER and EVGEN
50
51 Revision 1.25  2000/11/15 14:30:16  cblume
52 Fixed bug in calculating detector no. of extra hit
53
54 Revision 1.24  2000/11/10 14:58:36  cblume
55 Introduce additional hit with amplitude 0 at the chamber borders
56
57 Revision 1.23  2000/11/01 14:53:21  cblume
58 Merge with TRD-develop
59
60 Revision 1.17.2.5  2000/10/15 23:40:01  cblume
61 Remove AliTRDconst
62
63 Revision 1.17.2.4  2000/10/06 16:49:46  cblume
64 Made Getters const
65
66 Revision 1.17.2.3  2000/10/04 16:34:58  cblume
67 Replace include files by forward declarations
68
69 Revision 1.17.2.2  2000/09/18 13:50:17  cblume
70 Include TR photon generation and adapt to new AliTRDhit
71
72 Revision 1.22  2000/06/27 13:08:50  cblume
73 Changed to Copy(TObject &A) to appease the HP-compiler
74
75 Revision 1.21  2000/06/09 11:10:07  cblume
76 Compiler warnings and coding conventions, next round
77
78 Revision 1.20  2000/06/08 18:32:58  cblume
79 Make code compliant to coding conventions
80
81 Revision 1.19  2000/06/07 16:27:32  cblume
82 Try to remove compiler warnings on Sun and HP
83
84 Revision 1.18  2000/05/08 16:17:27  cblume
85 Merge TRD-develop
86
87 Revision 1.17.2.1  2000/05/08 14:59:16  cblume
88 Made inline function non-virtual. Bug fix in setting sensitive chamber
89
90 Revision 1.17  2000/02/28 19:10:26  cblume
91 Include the new TRD classes
92
93 Revision 1.16.4.1  2000/02/28 18:04:35  cblume
94 Change to new hit version, introduce geometry class, and move digitization and clustering to AliTRDdigitizer/AliTRDclusterizerV1
95
96 Revision 1.16  1999/11/05 22:50:28  fca
97 Do not use Atan, removed from ROOT too
98
99 Revision 1.15  1999/11/02 17:20:19  fca
100 initialise nbytes before using it
101
102 Revision 1.14  1999/11/02 17:15:54  fca
103 Correct ansi scoping not accepted by HP compilers
104
105 Revision 1.13  1999/11/02 17:14:51  fca
106 Correct ansi scoping not accepted by HP compilers
107
108 Revision 1.12  1999/11/02 16:35:56  fca
109 New version of TRD introduced
110
111 Revision 1.11  1999/11/01 20:41:51  fca
112 Added protections against using the wrong version of FRAME
113
114 Revision 1.10  1999/09/29 09:24:35  fca
115 Introduction of the Copyright and cvs Log
116
117 */
118
119 ///////////////////////////////////////////////////////////////////////////////
120 //                                                                           //
121 //  Transition Radiation Detector version 1 -- slow simulator                //
122 //                                                                           //
123 //Begin_Html
124 /*
125 <img src="picts/AliTRDfullClass.gif">
126 */
127 //End_Html
128 //                                                                           //
129 //                                                                           //
130 ///////////////////////////////////////////////////////////////////////////////
131
132 #include <stdlib.h> 
133
134 #include <TMath.h>
135 #include <TVector.h>
136 #include <TRandom.h>
137 #include <TF1.h>
138 #include <TLorentzVector.h>
139
140 #include "AliRun.h"
141 #include "AliConst.h"
142
143 #include "AliTRDv1.h"
144 #include "AliTRDhit.h"
145 #include "AliTRDmatrix.h"
146 #include "AliTRDgeometry.h"
147 #include "AliTRDsim.h"
148
149 ClassImp(AliTRDv1)
150  
151 //_____________________________________________________________________________
152 AliTRDv1::AliTRDv1():AliTRD()
153 {
154   //
155   // Default constructor
156   //
157
158   fSensSelect      =  0;
159   fSensPlane       = -1;
160   fSensChamber     = -1;
161   fSensSector      = -1;
162   fSensSectorRange =  0;
163
164   fDeltaE          = NULL;
165   fTR              = NULL;
166
167 }
168
169 //_____________________________________________________________________________
170 AliTRDv1::AliTRDv1(const char *name, const char *title) 
171          :AliTRD(name, title) 
172 {
173   //
174   // Standard constructor for Transition Radiation Detector version 1
175   //
176
177   fSensSelect      =  0;
178   fSensPlane       = -1;
179   fSensChamber     = -1;
180   fSensSector      = -1;
181   fSensSectorRange =  0;
182
183   fDeltaE          = NULL;
184   fTR              = NULL;
185
186   SetBufferSize(128000);
187
188 }
189
190 //_____________________________________________________________________________
191 AliTRDv1::AliTRDv1(const AliTRDv1 &trd)
192 {
193   //
194   // Copy constructor
195   //
196
197   ((AliTRDv1 &) trd).Copy(*this);
198
199 }
200
201 //_____________________________________________________________________________
202 AliTRDv1::~AliTRDv1()
203 {
204   //
205   // AliTRDv1 destructor
206   //
207
208   if (fDeltaE) delete fDeltaE;
209   if (fTR)     delete fTR;
210
211 }
212  
213 //_____________________________________________________________________________
214 AliTRDv1 &AliTRDv1::operator=(const AliTRDv1 &trd)
215 {
216   //
217   // Assignment operator
218   //
219
220   if (this != &trd) ((AliTRDv1 &) trd).Copy(*this);
221   return *this;
222
223 }
224  
225 //_____________________________________________________________________________
226 void AliTRDv1::Copy(TObject &trd)
227 {
228   //
229   // Copy function
230   //
231
232   ((AliTRDv1 &) trd).fSensSelect      = fSensSelect;
233   ((AliTRDv1 &) trd).fSensPlane       = fSensPlane;
234   ((AliTRDv1 &) trd).fSensChamber     = fSensChamber;
235   ((AliTRDv1 &) trd).fSensSector      = fSensSector;
236   ((AliTRDv1 &) trd).fSensSectorRange = fSensSectorRange;
237
238   fDeltaE->Copy(*((AliTRDv1 &) trd).fDeltaE);
239   fTR->Copy(*((AliTRDv1 &) trd).fTR);
240
241 }
242
243 //_____________________________________________________________________________
244 void AliTRDv1::CreateGeometry()
245 {
246   //
247   // Create the GEANT geometry for the Transition Radiation Detector - Version 1
248   // This version covers the full azimuth. 
249   //
250
251   // Check that FRAME is there otherwise we have no place where to put the TRD
252   AliModule* frame = gAlice->GetModule("FRAME");
253   if (!frame) return;
254
255   // Define the chambers
256   AliTRD::CreateGeometry();
257
258 }
259
260 //_____________________________________________________________________________
261 void AliTRDv1::CreateMaterials()
262 {
263   //
264   // Create materials for the Transition Radiation Detector version 1
265   //
266
267   AliTRD::CreateMaterials();
268
269 }
270
271 //_____________________________________________________________________________
272 void AliTRDv1::CreateTRhit(Int_t det)
273 {
274   //
275   // Creates an electron cluster from a TR photon.
276   // The photon is assumed to be created a the end of the radiator. The 
277   // distance after which it deposits its energy takes into account the 
278   // absorbtion of the entrance window and of the gas mixture in drift
279   // volume.
280   //
281
282   // PDG code electron
283   const Int_t   kPdgElectron = 11;
284
285   // Ionization energy
286   const Float_t kWion        = 22.04;
287
288   // Maximum number of TR photons per track
289   const Int_t   kNTR         = 50;
290
291   TLorentzVector mom, pos;
292
293   // Create TR at the entrance of the chamber
294   if (gMC->IsTrackEntering()) {
295
296     // Create TR only for electrons 
297     Int_t iPdg = gMC->TrackPid();
298     if (TMath::Abs(iPdg) != kPdgElectron) return;
299
300     Float_t eTR[kNTR];
301     Int_t   nTR;
302
303     // Create TR photons
304     gMC->TrackMomentum(mom);
305     Float_t pTot = mom.Rho();
306     fTR->CreatePhotons(iPdg,pTot,nTR,eTR);
307     if (nTR > kNTR) {
308       printf("AliTRDv1::CreateTRhit -- ");
309       printf("Boundary error: nTR = %d, kNTR = %d\n",nTR,kNTR);
310       exit(1);
311     }
312
313     // Loop through the TR photons
314     for (Int_t iTR = 0; iTR < nTR; iTR++) {
315
316       Float_t energyMeV = eTR[iTR] * 0.001;
317       Float_t energyeV  = eTR[iTR] * 1000.0;
318       Float_t absLength = 0;
319       Float_t sigma     = 0;
320
321       // Take the absorbtion in the entrance window into account
322       Double_t muMy = fTR->GetMuMy(energyMeV);
323       sigma = muMy * fFoilDensity;
324       absLength = gRandom->Exp(sigma);
325       if (absLength < AliTRDgeometry::MyThick()) continue;
326
327       // The absorbtion cross sections in the drift gas
328       if (fGasMix == 1) {
329         // Gas-mixture (Xe/CO2)
330         Double_t muXe = fTR->GetMuXe(energyMeV);
331         Double_t muCO = fTR->GetMuCO(energyMeV);
332         sigma = (0.85 * muXe + 0.15 * muCO) * fGasDensity;
333       }
334       else {
335         // Gas-mixture (Xe/Isobutane) 
336         Double_t muXe = fTR->GetMuXe(energyMeV);
337         Double_t muBu = fTR->GetMuBu(energyMeV);
338         sigma = (0.97 * muXe + 0.03 * muBu) * fGasDensity;
339       }
340
341       // The distance after which the energy of the TR photon
342       // is deposited.
343       absLength = gRandom->Exp(sigma);
344       if (absLength > AliTRDgeometry::DrThick()) continue;
345
346       // The position of the absorbtion
347       Float_t posHit[3];
348       gMC->TrackPosition(pos);
349       posHit[0] = pos[0] + mom[0] / pTot * absLength;
350       posHit[1] = pos[1] + mom[1] / pTot * absLength;
351       posHit[2] = pos[2] + mom[2] / pTot * absLength;      
352
353       // Create the charge 
354       Int_t q = ((Int_t) (energyeV / kWion));
355
356       // Add the hit to the array. TR photon hits are marked 
357       // by negative charge
358       AddHit(gAlice->CurrentTrack(),det,posHit,-q,kTRUE); 
359
360     }
361
362   }
363
364 }
365
366 //_____________________________________________________________________________
367 void AliTRDv1::Init() 
368 {
369   //
370   // Initialise Transition Radiation Detector after geometry has been built.
371   //
372
373   AliTRD::Init();
374
375   if(fDebug) printf("%s: Slow simulator\n",ClassName());
376   if (fSensSelect) {
377     if (fSensPlane   >= 0)
378       printf("          Only plane %d is sensitive\n",fSensPlane);
379     if (fSensChamber >= 0)   
380       printf("          Only chamber %d is sensitive\n",fSensChamber);
381     if (fSensSector  >= 0) {
382       Int_t sens1  = fSensSector;
383       Int_t sens2  = fSensSector + fSensSectorRange;
384             sens2 -= ((Int_t) (sens2 / AliTRDgeometry::Nsect())) 
385                    * AliTRDgeometry::Nsect();
386       printf("          Only sectors %d - %d are sensitive\n",sens1,sens2-1);
387     }
388   }
389   if (fTR) 
390     printf("%s: TR simulation on\n",ClassName());
391   else
392     printf("%s: TR simulation off\n",ClassName());
393   printf("\n");
394
395   // First ionization potential (eV) for the gas mixture (90% Xe + 10% CO2)
396   const Float_t kPoti = 12.1;
397   // Maximum energy (50 keV);
398   const Float_t kEend = 50000.0;
399   // Ermilova distribution for the delta-ray spectrum
400   Float_t poti = TMath::Log(kPoti);
401   Float_t eEnd = TMath::Log(kEend);
402   fDeltaE = new TF1("deltae",Ermilova,poti,eEnd,0);
403
404   if(fDebug) {
405     printf("%s: ",ClassName());
406     for (Int_t i = 0; i < 80; i++) printf("*");
407     printf("\n");
408   }
409
410 }
411
412 //_____________________________________________________________________________
413 AliTRDsim *AliTRDv1::CreateTR()
414 {
415   //
416   // Enables the simulation of TR
417   //
418
419   fTR = new AliTRDsim();
420   return fTR;
421
422 }
423
424 //_____________________________________________________________________________
425 void AliTRDv1::SetSensPlane(Int_t iplane)
426 {
427   //
428   // Defines the hit-sensitive plane (0-5)
429   //
430
431   if ((iplane < 0) || (iplane > 5)) {
432     printf("Wrong input value: %d\n",iplane);
433     printf("Use standard setting\n");
434     fSensPlane  = -1;
435     fSensSelect =  0;
436     return;
437   }
438
439   fSensSelect = 1;
440   fSensPlane  = iplane;
441
442 }
443
444 //_____________________________________________________________________________
445 void AliTRDv1::SetSensChamber(Int_t ichamber)
446 {
447   //
448   // Defines the hit-sensitive chamber (0-4)
449   //
450
451   if ((ichamber < 0) || (ichamber > 4)) {
452     printf("Wrong input value: %d\n",ichamber);
453     printf("Use standard setting\n");
454     fSensChamber = -1;
455     fSensSelect  =  0;
456     return;
457   }
458
459   fSensSelect  = 1;
460   fSensChamber = ichamber;
461
462 }
463
464 //_____________________________________________________________________________
465 void AliTRDv1::SetSensSector(Int_t isector)
466 {
467   //
468   // Defines the hit-sensitive sector (0-17)
469   //
470
471   SetSensSector(isector,1);
472
473 }
474
475 //_____________________________________________________________________________
476 void AliTRDv1::SetSensSector(Int_t isector, Int_t nsector)
477 {
478   //
479   // Defines a range of hit-sensitive sectors. The range is defined by
480   // <isector> (0-17) as the starting point and <nsector> as the number 
481   // of sectors to be included.
482   //
483
484   if ((isector < 0) || (isector > 17)) {
485     printf("Wrong input value <isector>: %d\n",isector);
486     printf("Use standard setting\n");
487     fSensSector      = -1;
488     fSensSectorRange =  0;
489     fSensSelect      =  0;
490     return;
491   }
492
493   if ((nsector < 1) || (nsector > 18)) {
494     printf("Wrong input value <nsector>: %d\n",nsector);
495     printf("Use standard setting\n");
496     fSensSector      = -1;
497     fSensSectorRange =  0;
498     fSensSelect      =  0;
499     return;
500   }
501
502   fSensSelect      = 1;
503   fSensSector      = isector;
504   fSensSectorRange = nsector;
505
506 }
507
508 //_____________________________________________________________________________
509 void AliTRDv1::StepManager()
510 {
511   //
512   // Slow simulator. Every charged track produces electron cluster as hits 
513   // along its path across the drift volume. The step size is set acording
514   // to Bethe-Bloch. The energy distribution of the delta electrons follows
515   // a spectrum taken from Ermilova et al.
516   //
517
518   Int_t    pla = 0;
519   Int_t    cha = 0;
520   Int_t    sec = 0;
521   Int_t    det = 0;
522   Int_t    iPdg;
523   Int_t    qTot;
524
525   Float_t  hits[3];
526   Double_t  random[1];
527   Float_t  charge;
528   Float_t  aMass;
529
530   Double_t pTot = 0;
531   Double_t eDelta;
532   Double_t betaGamma, pp;
533   Double_t stepSize;
534
535   Bool_t   drRegion = kFALSE;
536   Bool_t   amRegion = kFALSE;
537
538   TString  cIdCurrent;
539   TString  cIdSensDr = "J";
540   TString  cIdSensAm = "K";
541   Char_t   cIdChamber[3];
542            cIdChamber[2] = 0;
543
544   TLorentzVector pos, mom;
545
546   const Int_t    kNplan       = AliTRDgeometry::Nplan();
547   const Double_t kBig         = 1.0E+12;
548
549   // Ionization energy
550   const Float_t  kWion        = 22.04;
551   // Maximum momentum for e+ e- g 
552   const Float_t  kPTotMaxEl   = 0.002;
553   // Minimum energy for the step size adjustment
554   const Float_t  kEkinMinStep = 1.0e-5;
555   // Plateau value of the energy-loss for electron in xenon
556   // taken from: Allison + Comb, Ann. Rev. Nucl. Sci. (1980), 30, 253
557   //const Double_t kPlateau = 1.70;
558   // the averaged value (26/3/99)
559   const Float_t  kPlateau     = 1.55;
560   // dN1/dx|min for the gas mixture (90% Xe + 10% CO2)
561   const Float_t  kPrim        = 48.0;
562   // First ionization potential (eV) for the gas mixture (90% Xe + 10% CO2)
563   const Float_t  kPoti        = 12.1;
564
565   // PDG code electron
566   const Int_t    kPdgElectron = 11;
567
568   // Set the maximum step size to a very large number for all 
569   // neutral particles and those outside the driftvolume
570   gMC->SetMaxStep(kBig); 
571
572   // Use only charged tracks 
573   if (( gMC->TrackCharge()       ) &&
574       (!gMC->IsTrackStop()       ) && 
575       (!gMC->IsTrackDisappeared())) {
576
577     // Inside a sensitive volume?
578     drRegion = kFALSE;
579     amRegion = kFALSE;
580     cIdCurrent = gMC->CurrentVolName();
581     if (cIdSensDr == cIdCurrent[1]) {
582       drRegion = kTRUE;
583     }
584     if (cIdSensAm == cIdCurrent[1]) {
585       amRegion = kTRUE;
586     }
587     if (drRegion || amRegion) {
588
589       // The hit coordinates and charge
590       gMC->TrackPosition(pos);
591       hits[0] = pos[0];
592       hits[1] = pos[1];
593       hits[2] = pos[2];
594
595       // The sector number (0 - 17)
596       // The numbering goes clockwise and starts at y = 0
597       Float_t phi = kRaddeg*TMath::ATan2(pos[0],pos[1]);
598       if (phi < 90.) 
599         phi = phi + 270.;
600       else
601         phi = phi -  90.;
602       sec = ((Int_t) (phi / 20));
603
604       // The plane and chamber number
605       cIdChamber[0] = cIdCurrent[2];
606       cIdChamber[1] = cIdCurrent[3];
607       Int_t idChamber = atoi(cIdChamber);
608       cha = ((Int_t) idChamber / kNplan);
609       pla = ((Int_t) idChamber % kNplan);
610
611       // Check on selected volumes
612       Int_t addthishit = 1;
613       if (fSensSelect) {
614         if ((fSensPlane   >= 0) && (pla != fSensPlane  )) addthishit = 0;
615         if ((fSensChamber >= 0) && (cha != fSensChamber)) addthishit = 0;
616         if (fSensSector  >= 0) {
617           Int_t sens1  = fSensSector;
618           Int_t sens2  = fSensSector + fSensSectorRange;
619                 sens2 -= ((Int_t) (sens2 / AliTRDgeometry::Nsect())) 
620                        * AliTRDgeometry::Nsect();
621           if (sens1 < sens2) {
622             if ((sec < sens1) || (sec >= sens2)) addthishit = 0;
623           }
624           else {
625             if ((sec < sens1) && (sec >= sens2)) addthishit = 0;
626           }
627         }
628       }
629
630       // Add this hit
631       if (addthishit) {
632
633         // The detector number
634         det = fGeometry->GetDetector(pla,cha,sec);
635
636         // Special hits and TR photons only in the drift region
637         if (drRegion) {
638
639           // Create a track reference at the entrance and
640           // exit of each chamber that contain the 
641           // momentum components of the particle
642           if (gMC->IsTrackEntering() || gMC->IsTrackExiting()) {
643             gMC->TrackMomentum(mom);
644             AddTrackReference(gAlice->CurrentTrack(),mom,pos);
645           }
646
647           // Create the hits from TR photons
648           if (fTR) CreateTRhit(det);
649
650         }
651
652         // Calculate the energy of the delta-electrons
653         eDelta = TMath::Exp(fDeltaE->GetRandom()) - kPoti;
654         eDelta = TMath::Max(eDelta,0.0);
655
656         // The number of secondary electrons created
657         qTot = ((Int_t) (eDelta / kWion) + 1);
658
659         // Create a new dEdx hit
660         if (drRegion) {
661           AddHit(gAlice->CurrentTrack(),det,hits,qTot,kTRUE);       
662         }
663         else {
664           AddHit(gAlice->CurrentTrack(),det,hits,qTot,kFALSE);      
665         }
666
667         // Calculate the maximum step size for the next tracking step
668         // Produce only one hit if Ekin is below cutoff 
669         aMass = gMC->TrackMass();
670         if ((gMC->Etot() - aMass) > kEkinMinStep) {
671
672           // The energy loss according to Bethe Bloch
673           iPdg  = TMath::Abs(gMC->TrackPid());
674           if ( (iPdg != kPdgElectron) ||
675               ((iPdg == kPdgElectron) && (pTot < kPTotMaxEl))) {
676             gMC->TrackMomentum(mom);
677             pTot      = mom.Rho();
678             betaGamma = pTot / aMass;
679             pp        = kPrim * BetheBloch(betaGamma);
680             // Take charge > 1 into account
681             charge = gMC->TrackCharge();
682             if (TMath::Abs(charge) > 1) pp = pp * charge*charge;
683           }
684           // Electrons above 20 Mev/c are at the plateau
685           else {
686             pp = kPrim * kPlateau;
687           }
688       
689           if (pp > 0) {
690             do 
691             gMC->GetRandom()->RndmArray(1, random);
692             while ((random[0] == 1.) || (random[0] == 0.));
693             stepSize = - TMath::Log(random[0]) / pp; 
694             gMC->SetMaxStep(stepSize);
695           }
696
697         }
698
699       }
700
701     }
702
703   }
704
705 }
706
707 //_____________________________________________________________________________
708 Double_t AliTRDv1::BetheBloch(Double_t bg) 
709 {
710   //
711   // Parametrization of the Bethe-Bloch-curve
712   // The parametrization is the same as for the TPC and is taken from Lehrhaus.
713   //
714
715   // This parameters have been adjusted to averaged values from GEANT
716   const Double_t kP1 = 7.17960e-02;
717   const Double_t kP2 = 8.54196;
718   const Double_t kP3 = 1.38065e-06;
719   const Double_t kP4 = 5.30972;
720   const Double_t kP5 = 2.83798;
721
722   // This parameters have been adjusted to Xe-data found in:
723   // Allison & Cobb, Ann. Rev. Nucl. Sci. (1980), 30, 253
724   //const Double_t kP1 = 0.76176E-1;
725   //const Double_t kP2 = 10.632;
726   //const Double_t kP3 = 3.17983E-6;
727   //const Double_t kP4 = 1.8631;
728   //const Double_t kP5 = 1.9479;
729
730   // Lower cutoff of the Bethe-Bloch-curve to limit step sizes
731   const Double_t kBgMin = 0.8;
732   const Double_t kBBMax = 6.83298;
733   //const Double_t kBgMin = 0.6;
734   //const Double_t kBBMax = 17.2809;
735   //const Double_t kBgMin = 0.4;
736   //const Double_t kBBMax = 82.0;
737
738   if (bg > kBgMin) {
739     Double_t yy = bg / TMath::Sqrt(1. + bg*bg);
740     Double_t aa = TMath::Power(yy,kP4);
741     Double_t bb = TMath::Power((1./bg),kP5);
742              bb = TMath::Log(kP3 + bb);
743     return ((kP2 - aa - bb)*kP1 / aa);
744   }
745   else {
746     return kBBMax;
747   }
748
749 }
750
751 //_____________________________________________________________________________
752 Double_t Ermilova(Double_t *x, Double_t *)
753 {
754   //
755   // Calculates the delta-ray energy distribution according to Ermilova.
756   // Logarithmic scale !
757   //
758
759   Double_t energy;
760   Double_t dpos;
761   Double_t dnde;
762
763   Int_t    pos1, pos2;
764
765   const Int_t kNv = 31;
766
767   Float_t vxe[kNv] = { 2.3026, 2.9957, 3.4012, 3.6889, 3.9120  
768                      , 4.0943, 4.2485, 4.3820, 4.4998, 4.6052
769                      , 4.7005, 5.0752, 5.2983, 5.7038, 5.9915
770                      , 6.2146, 6.5221, 6.9078, 7.3132, 7.6009
771                      , 8.0064, 8.5172, 8.6995, 8.9872, 9.2103
772                      , 9.4727, 9.9035,10.3735,10.5966,10.8198
773                      ,11.5129 };
774
775   Float_t vye[kNv] = { 80.0  , 31.0  , 23.3  , 21.1  , 21.0
776                      , 20.9  , 20.8  , 20.0  , 16.0  , 11.0
777                      ,  8.0  ,  6.0  ,  5.2  ,  4.6  ,  4.0
778                      ,  3.5  ,  3.0  ,  1.4  ,  0.67 ,  0.44
779                      ,  0.3  ,  0.18 ,  0.12 ,  0.08 ,  0.056
780                      ,  0.04 ,  0.023,  0.015,  0.011,  0.01
781                      ,  0.004 };
782
783   energy = x[0];
784
785   // Find the position 
786   pos1 = pos2 = 0;
787   dpos = 0;
788   do {
789     dpos = energy - vxe[pos2++];
790   } 
791   while (dpos > 0);
792   pos2--; 
793   if (pos2 > kNv) pos2 = kNv - 1;
794   pos1 = pos2 - 1;
795
796   // Differentiate between the sampling points
797   dnde = (vye[pos1] - vye[pos2]) / (vxe[pos2] - vxe[pos1]);
798
799   return dnde;
800
801 }