d1ace1b2ca82432d7b83581b71819f9bd0fc1b40
[u/mrichter/AliRoot.git] / MUON / AliMUONv1.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *      SigmaEffect_thetadegrees                                                                  *
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 purpeateose. It is      *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15
16 /* $Id$ */
17
18 /////////////////////////////////////////////////////////
19 //  Manager and hits classes for set:MUON version 1    //
20 /////////////////////////////////////////////////////////
21
22 #include <TRandom.h>
23 #include <TF1.h>
24 #include <TClonesArray.h>
25 #include <TRandom.h> 
26 #include <TVirtualMC.h>
27
28 #include "AliMUONv1.h"
29 #include "AliConst.h" 
30 #include "AliMUONChamber.h"
31 #include "AliMUONConstants.h"
32 #include "AliMUONFactory.h"
33 #include "AliMUONHit.h"
34 #include "AliMUONTriggerCircuit.h"
35 #include "AliMUONGeometryBuilder.h"     
36 #include "AliMagF.h"
37 #include "AliRun.h"
38 #include "AliMC.h"
39
40 ClassImp(AliMUONv1)
41  
42 //___________________________________________
43 AliMUONv1::AliMUONv1() 
44   : AliMUON(),
45     fStepManagerVersionOld(kFALSE),
46     fAngleEffect(kTRUE),
47     fStepMaxInActiveGas(0.6),
48     fStepSum(0x0),
49     fDestepSum(0x0),
50     fTrackMomentum(), 
51     fTrackPosition(),
52     fElossRatio(0x0),
53     fAngleEffect10(0x0),
54     fAngleEffectNorma(0x0)
55 {
56 // Default constructor
57
58
59 //___________________________________________
60 AliMUONv1::AliMUONv1(const char *name, const char *title)
61   : AliMUON(name,title), 
62     fStepManagerVersionOld(kFALSE),
63     fAngleEffect(kTRUE),
64     fStepMaxInActiveGas(0.6),
65     fStepSum(0x0),
66     fDestepSum(0x0),
67     fTrackMomentum(), 
68     fTrackPosition(),
69     fElossRatio(0x0),
70     fAngleEffect10(0x0),
71     fAngleEffectNorma(0x0)
72 {
73 // Standard onstructor
74
75     // By default include all stations
76     AliMUONFactory factory;
77     factory.Build(this, title);
78
79     fStepSum   = new Float_t [AliMUONConstants::NCh()];
80     fDestepSum = new Float_t [AliMUONConstants::NCh()];
81     for (Int_t i=0; i<AliMUONConstants::NCh(); i++) {
82       fStepSum[i] =0.0;
83       fDestepSum[i]=0.0;
84     }
85     // Ratio of particle mean eloss with respect MIP's Khalil Boudjemline, sep 2003, PhD.Thesis and Particle Data Book
86     fElossRatio = new TF1("ElossRatio","[0]+[1]*x+[2]*x*x+[3]*x*x*x+[4]*x*x*x*x",0.5,5.); 
87     fElossRatio->SetParameter(0,1.02138);
88     fElossRatio->SetParameter(1,-9.54149e-02);
89     fElossRatio->SetParameter(2,+7.83433e-02); 
90     fElossRatio->SetParameter(3,-9.98208e-03);
91     fElossRatio->SetParameter(4,+3.83279e-04);
92
93     // Angle effect in tracking chambers at theta =10 degres as a function of ElossRatio (Khalil BOUDJEMLINE sep 2003 Ph.D Thesis) (in micrometers)
94     fAngleEffect10 = new TF1("AngleEffect10","[0]+[1]*x+[2]*x*x",0.5,3.0);
95     fAngleEffect10->SetParameter(0, 1.90691e+02);
96     fAngleEffect10->SetParameter(1,-6.62258e+01);
97     fAngleEffect10->SetParameter(2,+1.28247e+01);
98     // Angle effect: Normalisation form theta=10 degres to theta between 0 and 10 (Khalil BOUDJEMLINE sep 2003 Ph.D Thesis)  
99     // Angle with respect to the wires assuming that chambers are perpendicular to the z axis.
100     fAngleEffectNorma = new TF1("AngleEffectNorma","[0]+[1]*x+[2]*x*x+[3]*x*x*x",0.0,10.0);
101     fAngleEffectNorma->SetParameter(0,4.148);
102     fAngleEffectNorma->SetParameter(1,-6.809e-01);
103     fAngleEffectNorma->SetParameter(2,5.151e-02);
104     fAngleEffectNorma->SetParameter(3,-1.490e-03);
105 }
106
107 //_____________________________________________________________________________
108 AliMUONv1::AliMUONv1(const AliMUONv1& right) 
109   : AliMUON(right) 
110 {  
111   // copy constructor (not implemented)
112
113   Fatal("AliMUONv1", "Copy constructor not provided.");
114 }
115
116 //___________________________________________
117 AliMUONv1::~AliMUONv1()
118 {
119 // Destructor
120
121   delete [] fStepSum;
122   delete [] fDestepSum;
123   delete fElossRatio;
124   delete fAngleEffect10;
125   delete fAngleEffectNorma;  
126 }
127
128 //_____________________________________________________________________________
129 AliMUONv1& AliMUONv1::operator=(const AliMUONv1& right)
130 {
131   // assignement operator (not implemented)
132
133   // check assignement to self
134   if (this == &right) return *this;
135
136   Fatal("operator =", "Assignement operator not provided.");
137     
138   return *this;  
139 }    
140
141 //__________________________________________________
142 void AliMUONv1::CreateGeometry()
143 {
144 //
145 // Construct geometry using geometry builder
146 //
147
148   fGeometryBuilder->CreateGeometry();
149 }
150
151 //________________________________________________________________
152 void AliMUONv1::CreateMaterials()
153 {
154 //
155 // Construct materials using geometry builder
156 //
157
158   fGeometryBuilder->CreateMaterials();
159 }
160
161 //___________________________________________
162 void AliMUONv1::Init()
163 {
164    // 
165    // Initialize Tracking Chambers
166    //
167
168    if(fDebug) printf("\n%s: Start Init for version 1 - CPC chamber type\n\n",ClassName());
169    Int_t i;
170    for (i=0; i<AliMUONConstants::NCh(); i++) {
171        ( (AliMUONChamber*) (*fChambers)[i])->Init();
172    }
173    
174    //
175    // Initialize geometry
176    //
177    fGeometryBuilder->InitGeometry();
178    if(fDebug) printf("\n%s: Finished Init for version 1 - CPC chamber type\n",ClassName());
179
180    //cp 
181    if(fDebug) printf("\n%s: Start Init for Trigger Circuits\n",ClassName());
182    for (i=0; i<AliMUONConstants::NTriggerCircuit(); i++) {
183      ( (AliMUONTriggerCircuit*) (*fTriggerCircuits)[i])->Init(i);
184    }
185    if(fDebug) printf("%s: Finished Init for Trigger Circuits\n",ClassName());
186    //cp
187 }
188
189 //__________________________________________________________________
190 Int_t  AliMUONv1::GetChamberId(Int_t volId) const
191 {
192 // Check if the volume with specified  volId is a sensitive volume (gas) 
193 // of some chamber and returns the chamber number;
194 // if not sensitive volume - return 0.
195 // ---
196
197 /*
198   for (Int_t i = 1; i <= AliMUONConstants::NCh(); i++)
199     if (volId==((AliMUONChamber*)(*fChambers)[i-1])->GetGid()) return i;
200 */
201   for (Int_t i = 1; i <= AliMUONConstants::NCh(); i++)
202     if ( ((AliMUONChamber*)(*fChambers)[i-1])->IsSensId(volId) ) return i;
203
204   return 0;
205 }
206 //_______________________________________________________________________________
207 void AliMUONv1::StepManager()
208 {
209   // Stepmanager for the chambers
210
211  if (fStepManagerVersionOld) {
212     StepManagerOld();
213     return;
214   }
215
216   // Only charged tracks
217   if( !(gMC->TrackCharge()) ) return; 
218   // Only charged tracks
219   
220   // Only gas gap inside chamber
221   // Tag chambers and record hits when track enters 
222   static Int_t   idvol=-1;
223   Int_t   iChamber=0;
224   Int_t   id=0;
225   Int_t   copy;
226   const  Float_t kBig = 1.e10;
227
228
229   //
230   // Only gas gap inside chamber
231   // Tag chambers and record hits when track enters 
232   id=gMC->CurrentVolID(copy);
233   iChamber = GetChamberId(id);
234   idvol = iChamber -1;
235
236   if (idvol == -1) return;
237
238   // Filling TrackRefs file for MUON. Our Track references are the active volume of the chambers
239   if ( (gMC->IsTrackEntering() || gMC->IsTrackExiting() ) )     
240     AddTrackReference(gAlice->GetMCApp()->GetCurrentTrackNumber());
241   
242    if( gMC->IsTrackEntering() ) {
243      Float_t theta = fTrackMomentum.Theta();
244      if ((TMath::Pi()-theta)*kRaddeg>=15.) gMC->SetMaxStep(fStepMaxInActiveGas); // We use Pi-theta because z is negative
245   }
246
247 //  if (GetDebug()) {
248 //     Float_t z = ( (AliMUONChamber*)(*fChambers)[idvol])->Z() ;
249 //      Info("StepManager Step","Active volume found %d chamber %d Z chamber is %f ",idvol,iChamber, z);
250 //   }  
251   // Particule id and mass, 
252   Int_t     ipart = gMC->TrackPid();
253   Float_t   mass  = gMC->TrackMass();
254
255   fDestepSum[idvol]+=gMC->Edep();
256   // Get current particle id (ipart), track position (pos)  and momentum (mom)
257   if ( fStepSum[idvol]==0.0 )  gMC->TrackMomentum(fTrackMomentum);
258   fStepSum[idvol]+=gMC->TrackStep();
259   
260 //   if (GetDebug()) {
261 //     Info("StepManager Step","iChamber %d, Particle %d, theta %f phi %f mass %f StepSum %f eloss %g",
262 //       iChamber,ipart, fTrackMomentum.Theta()*kRaddeg, fTrackMomentum.Phi()*kRaddeg, mass, fStepSum[idvol], gMC->Edep());
263 //     Info("StepManager Step","Track Momentum %f %f %f", fTrackMomentum.X(), fTrackMomentum.Y(), fTrackMomentum.Z()) ;
264 //     gMC->TrackPosition(fTrackPosition);
265 //     Info("StepManager Step","Track Position %f %f %f",fTrackPosition.X(),fTrackPosition.Y(),fTrackPosition.Z()) ;
266 //   }
267
268   // Track left chamber or StepSum larger than fStepMaxInActiveGas
269   if ( gMC->IsTrackExiting() || 
270        gMC->IsTrackStop() || 
271        gMC->IsTrackDisappeared()||
272        (fStepSum[idvol]>fStepMaxInActiveGas) ) {
273     
274     if   ( gMC->IsTrackExiting() || 
275            gMC->IsTrackStop() || 
276            gMC->IsTrackDisappeared() ) gMC->SetMaxStep(kBig);
277
278     gMC->TrackPosition(fTrackPosition);
279     Float_t theta = fTrackMomentum.Theta();
280     Float_t phi   = fTrackMomentum.Phi();
281     
282     TLorentzVector backToWire( fStepSum[idvol]/2.*sin(theta)*cos(phi),
283                                fStepSum[idvol]/2.*sin(theta)*sin(phi),
284                                fStepSum[idvol]/2.*cos(theta),0.0       );
285     //     if (GetDebug()) 
286     //       Info("StepManager Exit","Track Position %f %f %f",fTrackPosition.X(),fTrackPosition.Y(),fTrackPosition.Z()) ;
287     //     if (GetDebug()) 
288     //        Info("StepManager Exit ","Track backToWire %f %f %f",backToWire.X(),backToWire.Y(),backToWire.Z()) ;
289     fTrackPosition-=backToWire;
290     
291     //-------------- Angle effect 
292     // Ratio between energy loss of particle and Mip as a function of BetaGamma of particle (Energy/Mass)
293     
294     Float_t betaxGamma    = fTrackMomentum.P()/mass;//  pc/mc2
295     Float_t sigmaEffect10degrees;
296     Float_t sigmaEffectThetadegrees;
297     Float_t eLossParticleELossMip;
298     Float_t yAngleEffect=0.;
299     Float_t thetawires      =  TMath::Abs( TMath::ASin( TMath::Sin(TMath::Pi()-theta) * TMath::Sin(phi) ) );// We use Pi-theta because z is negative
300
301
302     if (fAngleEffect){
303     if ( (betaxGamma >3.2)   &&  (thetawires*kRaddeg<=15.) ) {
304       betaxGamma=TMath::Log(betaxGamma);
305       eLossParticleELossMip = fElossRatio->Eval(betaxGamma);
306       // 10 degrees is a reference for a model (arbitrary)
307       sigmaEffect10degrees=fAngleEffect10->Eval(eLossParticleELossMip);// in micrometers
308       // Angle with respect to the wires assuming that chambers are perpendicular to the z axis.
309       sigmaEffectThetadegrees =  sigmaEffect10degrees/fAngleEffectNorma->Eval(thetawires*kRaddeg);  // For 5mm gap  
310       if ( (iChamber==1)  ||  (iChamber==2) )  
311         sigmaEffectThetadegrees/=(1.09833e+00+1.70000e-02*(thetawires*kRaddeg)); // The gap is different (4mm)
312       yAngleEffect=1.e-04*gRandom->Gaus(0,sigmaEffectThetadegrees); // Error due to the angle effect in cm
313     }
314     }
315     
316     // One hit per chamber
317     GetMUONData()->AddHit(fIshunt, 
318                           gAlice->GetMCApp()->GetCurrentTrackNumber(), 
319                           iChamber, ipart,
320                           fTrackPosition.X(), 
321                           fTrackPosition.Y()+yAngleEffect, 
322                           fTrackPosition.Z(), 
323                           gMC->TrackTime(),
324                           fTrackMomentum.P(),
325                           theta, 
326                           phi, 
327                           fStepSum[idvol], 
328                           fDestepSum[idvol],                        
329                           fTrackPosition.X(),
330                           fTrackPosition.Y(),
331                           fTrackPosition.Z());
332
333 //     if (GetDebug()){
334 //       Info("StepManager Exit","Particle exiting from chamber %d",iChamber);
335 //       Info("StepManager Exit","StepSum %f eloss geant %g ",fStepSum[idvol],fDestepSum[idvol]);
336 //       Info("StepManager Exit","Track Position %f %f %f",fTrackPosition.X(),fTrackPosition.Y(),fTrackPosition.Z()) ;
337 //     }
338     fStepSum[idvol]  =0; // Reset for the next event
339     fDestepSum[idvol]=0; // Reset for the next event
340   }
341 }
342
343 //__________________________________________
344 void AliMUONv1::StepManagerOld()
345 {
346   // Old Stepmanager for the chambers
347   Int_t          copy, id;
348   static Int_t   idvol =-1;
349   static Int_t   vol[2];
350   Int_t          ipart;
351   TLorentzVector pos;
352   TLorentzVector mom;
353   Float_t        theta,phi;
354   Float_t        destep, step;
355   
356   static Float_t sstep;
357   static Float_t eloss, eloss2, xhit, yhit, zhit, tof, tlength;
358   const  Float_t kBig = 1.e10;
359   static Float_t hits[15];
360
361   TClonesArray &lhits = *fHits;
362
363   //
364   //
365   // Only charged tracks
366   if( !(gMC->TrackCharge()) ) return; 
367   //
368   // Only gas gap inside chamber
369   // Tag chambers and record hits when track enters 
370   id=gMC->CurrentVolID(copy);
371   vol[0] = GetChamberId(id);
372   idvol = vol[0] -1;
373
374   if (idvol == -1) return;
375
376   //
377   // Get current particle id (ipart), track position (pos)  and momentum (mom) 
378   gMC->TrackPosition(pos);
379   gMC->TrackMomentum(mom);
380
381   ipart  = gMC->TrackPid();
382
383   //
384   // momentum loss and steplength in last step
385   destep = gMC->Edep();
386   step   = gMC->TrackStep();
387   // cout<<"------------"<<step<<endl;
388   //
389   // record hits when track enters ...
390   if( gMC->IsTrackEntering()) {
391
392       gMC->SetMaxStep(fMaxStepGas);
393       Double_t tc = mom[0]*mom[0]+mom[1]*mom[1];
394       Double_t rt = TMath::Sqrt(tc);
395       Double_t pmom = TMath::Sqrt(tc+mom[2]*mom[2]);
396       Double_t tx = mom[0]/pmom;
397       Double_t ty = mom[1]/pmom;
398       Double_t tz = mom[2]/pmom;
399       Double_t s  = ((AliMUONChamber*)(*fChambers)[idvol])
400           ->ResponseModel()
401           ->Pitch()/tz;
402       theta   = Float_t(TMath::ATan2(rt,Double_t(mom[2])))*kRaddeg;
403       phi     = Float_t(TMath::ATan2(Double_t(mom[1]),Double_t(mom[0])))*kRaddeg;
404       hits[0] = Float_t(ipart);         // Geant3 particle type
405       hits[1] = pos[0]+s*tx;            // X-position for hit
406       hits[2] = pos[1]+s*ty;            // Y-position for hit
407       hits[3] = pos[2]+s*tz;            // Z-position for hit
408       hits[4] = theta;                  // theta angle of incidence
409       hits[5] = phi;                    // phi angle of incidence 
410       hits[8] = 0;//PadHits does not exist anymore  (Float_t) fNPadHits;    // first padhit
411       hits[9] = -1;                     // last pad hit
412       hits[10] = mom[3];                // hit momentum P
413       hits[11] = mom[0];                // Px
414       hits[12] = mom[1];                // Py
415       hits[13] = mom[2];                // Pz
416       tof=gMC->TrackTime();
417       hits[14] = tof;                   // Time of flight
418       tlength  = 0;
419       eloss    = 0;
420       eloss2   = 0;
421       sstep=0;
422       xhit     = pos[0];
423       yhit     = pos[1];      
424       zhit     = pos[2];      
425       Chamber(idvol).ChargeCorrelationInit();
426       // Only if not trigger chamber
427
428 //       printf("---------------------------\n");
429 //       printf(">>>> Y =  %f \n",hits[2]);
430 //       printf("---------------------------\n");
431     
432       
433
434      //  if(idvol < AliMUONConstants::NTrackingCh()) {
435 //        //
436 //        //  Initialize hit position (cursor) in the segmentation model 
437 //        ((AliMUONChamber*) (*fChambers)[idvol])
438 //            ->SigGenInit(pos[0], pos[1], pos[2]);
439 //       } else {
440 //        //geant3->Gpcxyz();
441 //        //printf("In the Trigger Chamber #%d\n",idvol-9);
442 //       }
443   }
444   eloss2+=destep;
445   sstep+=step;
446
447   // cout<<sstep<<endl;
448
449   // 
450   // Calculate the charge induced on a pad (disintegration) in case 
451   //
452   // Mip left chamber ...
453   if( gMC->IsTrackExiting() || gMC->IsTrackStop() || gMC->IsTrackDisappeared()){
454       gMC->SetMaxStep(kBig);
455       eloss   += destep;
456       tlength += step;
457       
458       Float_t x0,y0,z0;
459       Float_t localPos[3];
460       Float_t globalPos[3] = {pos[0], pos[1], pos[2]};
461       gMC->Gmtod(globalPos,localPos,1); 
462
463       if(idvol < AliMUONConstants::NTrackingCh()) {
464 // tracking chambers
465           x0 = 0.5*(xhit+pos[0]);
466           y0 = 0.5*(yhit+pos[1]);
467           z0 = 0.5*(zhit+pos[2]);
468       } else {
469 // trigger chambers
470           x0 = xhit;
471           y0 = yhit;
472           z0 = 0.;
473       }
474       
475
476       //      if (eloss >0)  MakePadHits(x0,y0,z0,eloss,tof,idvol);
477       
478           
479       hits[6] = tlength;   // track length
480       hits[7] = eloss2;    // de/dx energy loss
481
482
483       //      if (fNPadHits > (Int_t)hits[8]) {
484       //          hits[8] = hits[8]+1;
485       //          hits[9] = 0: // PadHits does not exist anymore (Float_t) fNPadHits;
486       //}
487 //
488 //    new hit 
489       
490       new(lhits[fNhits++]) 
491           AliMUONHit(fIshunt, gAlice->GetMCApp()->GetCurrentTrackNumber(), vol,hits);
492       eloss = 0; 
493       //
494       // Check additional signal generation conditions 
495       // defined by the segmentation
496       // model (boundary crossing conditions)
497       // only for tracking chambers
498   } else if 
499       ((idvol < AliMUONConstants::NTrackingCh()) &&
500        ((AliMUONChamber*) (*fChambers)[idvol])->SigGenCond(pos[0], pos[1], pos[2]))
501   {
502       ((AliMUONChamber*) (*fChambers)[idvol])
503           ->SigGenInit(pos[0], pos[1], pos[2]);
504       
505       Float_t localPos[3];
506       Float_t globalPos[3] = {pos[0], pos[1], pos[2]};
507       gMC->Gmtod(globalPos,localPos,1); 
508
509       eloss    += destep;
510
511       // if (eloss > 0 && idvol < AliMUONConstants::NTrackingCh())
512       //        MakePadHits(0.5*(xhit+pos[0]),0.5*(yhit+pos[1]),pos[2],eloss,tof,idvol);
513       xhit     = pos[0];
514       yhit     = pos[1]; 
515       zhit     = pos[2];
516       eloss = 0;
517       tlength += step ;
518       //
519       // nothing special  happened, add up energy loss
520   } else {        
521       eloss   += destep;
522       tlength += step ;
523   }
524 }