]> git.uio.no Git - u/mrichter/AliRoot.git/blob - STEER/AliTracker.cxx
The total mult in V0 became float number.
[u/mrichter/AliRoot.git] / STEER / AliTracker.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 /* $Id$ */
17
18 //-------------------------------------------------------------------------
19 //               Implementation of the AliTracker class
20 //  that is the base for AliTPCtracker, AliITStrackerV2 and AliTRDtracker    
21 //        Origin: Iouri Belikov, CERN, Jouri.Belikov@cern.ch
22 //-------------------------------------------------------------------------
23 #include <TClass.h>
24 #include <TMath.h>
25 #include <TH1F.h>
26 #include <TGeoManager.h>
27 #include <TGeoMatrix.h>
28
29 #include "AliMagF.h"
30 #include "AliTracker.h"
31 #include "AliGeomManager.h"
32 #include "AliCluster.h"
33 #include "AliKalmanTrack.h"
34 #include "AliGlobalQADataMaker.h"
35
36 extern TGeoManager *gGeoManager;
37
38 Bool_t AliTracker::fFillResiduals=kFALSE;
39 TObjArray **AliTracker::fResiduals=NULL;
40 AliRecoParam::EventSpecie_t AliTracker::fEventSpecie=AliRecoParam::kDefault;
41
42 ClassImp(AliTracker)
43
44 AliTracker::AliTracker():
45   TObject(),
46   fX(0),
47   fY(0),
48   fZ(0),
49   fSigmaX(0.005),
50   fSigmaY(0.005),
51   fSigmaZ(0.010) 
52 {
53   //--------------------------------------------------------------------
54   // The default constructor.
55   //--------------------------------------------------------------------
56   if (!TGeoGlobalMagField::Instance()->GetField())
57     AliWarning("Field map is not set.");
58 }
59
60 //__________________________________________________________________________
61 AliTracker::AliTracker(const AliTracker &atr):
62   TObject(atr),
63   fX(atr.fX),
64   fY(atr.fY),
65   fZ(atr.fZ),
66   fSigmaX(atr.fSigmaX),
67   fSigmaY(atr.fSigmaY),
68   fSigmaZ(atr.fSigmaZ)
69 {
70   //--------------------------------------------------------------------
71   // The default constructor.
72   //--------------------------------------------------------------------
73   if (!TGeoGlobalMagField::Instance()->GetField())
74     AliWarning("Field map is not set.");
75 }
76
77 //__________________________________________________________________________
78 Double_t AliTracker::GetBz()
79 {
80   AliMagF* fld = (AliMagF*)TGeoGlobalMagField::Instance()->GetField();
81   if (!fld) return 0.5*kAlmost0Field;
82   Double_t bz = fld->SolenoidField();
83   return TMath::Sign(0.5*kAlmost0Field,bz) + bz;
84 }
85
86 //__________________________________________________________________________
87 Double_t AliTracker::GetBz(const Double_t *r) {
88   //------------------------------------------------------------------
89   // Returns Bz (kG) at the point "r" .
90   //------------------------------------------------------------------
91   AliMagF* fld = (AliMagF*)TGeoGlobalMagField::Instance()->GetField();
92   if (!fld) return  0.5*kAlmost0Field;
93   Double_t bz = fld->GetBz(r);
94   return  TMath::Sign(0.5*kAlmost0Field,bz) + bz;
95 }
96
97 //__________________________________________________________________________
98 void AliTracker::GetBxByBz(const Double_t r[3], Double_t b[3]) {
99   //------------------------------------------------------------------
100   // Returns Bx, By and Bz (kG) at the point "r" .
101   //------------------------------------------------------------------
102   AliMagF* fld = (AliMagF*)TGeoGlobalMagField::Instance()->GetField();
103   if (!fld) {
104      b[0] = b[1] = 0.;
105      b[2] = 0.5*kAlmost0Field;
106      return;
107   }
108
109   if (fld->IsUniform()) {
110      b[0] = b[1] = 0.;
111      b[2] = fld->SolenoidField();
112   }  else {
113      fld->Field(r,b);
114   }
115   b[2] = (TMath::Sign(0.5*kAlmost0Field,b[2]) + b[2]);
116   return;
117 }
118
119 //__________________________________________________________________________
120 void AliTracker::FillClusterArray(TObjArray* /*array*/) const
121 {
122   // Publishes all pointers to clusters known to the tracker into the
123   // passed object array.
124   // The ownership is not transfered - the caller is not expected to delete
125   // the clusters.
126
127   AliWarning("should be overriden by a sub-class.");
128 }
129
130 //__________________________________________________________________________
131 void AliTracker::CookLabel(AliKalmanTrack *t, Float_t wrong) const {
132   //--------------------------------------------------------------------
133   //This function "cooks" a track label. If label<0, this track is fake.
134   //--------------------------------------------------------------------
135   Int_t noc=t->GetNumberOfClusters();
136   if (noc<1) return;
137   Int_t *lb=new Int_t[noc];
138   Int_t *mx=new Int_t[noc];
139   AliCluster **clusters=new AliCluster*[noc];
140
141   Int_t i;
142   for (i=0; i<noc; i++) {
143      lb[i]=mx[i]=0;
144      Int_t index=t->GetClusterIndex(i);
145      clusters[i]=GetCluster(index);
146   }
147
148   Int_t lab=123456789;
149   for (i=0; i<noc; i++) {
150     AliCluster *c=clusters[i];
151     lab=TMath::Abs(c->GetLabel(0));
152     Int_t j;
153     for (j=0; j<noc; j++) if (lb[j]==lab || mx[j]==0) break;
154     lb[j]=lab;
155     (mx[j])++;
156   }
157
158   Int_t max=0;
159   for (i=0; i<noc; i++) if (mx[i]>max) {max=mx[i]; lab=lb[i];}
160     
161   for (i=0; i<noc; i++) {
162     AliCluster *c=clusters[i];
163     //if (TMath::Abs(c->GetLabel(1)) == lab ||
164     //    TMath::Abs(c->GetLabel(2)) == lab ) max++;
165     if (TMath::Abs(c->GetLabel(0)!=lab))
166         if (TMath::Abs(c->GetLabel(1)) == lab ||
167             TMath::Abs(c->GetLabel(2)) == lab ) max++;
168   }
169
170   if ((1.- Float_t(max)/noc) > wrong) lab=-lab;
171   t->SetFakeRatio((1.- Float_t(max)/noc));
172   t->SetLabel(lab);
173
174   delete[] lb;
175   delete[] mx;
176   delete[] clusters;
177 }
178
179 //____________________________________________________________________________
180 void AliTracker::UseClusters(const AliKalmanTrack *t, Int_t from) const {
181   //------------------------------------------------------------------
182   //This function marks clusters associated with the track.
183   //------------------------------------------------------------------
184   Int_t noc=t->GetNumberOfClusters();
185   for (Int_t i=from; i<noc; i++) {
186      Int_t index=t->GetClusterIndex(i);
187      AliCluster *c=GetCluster(index); 
188      c->Use();   
189   }
190 }
191
192 Double_t AliTracker::MeanMaterialBudget(const Double_t *start, const Double_t *end, Double_t *mparam)
193 {
194   // 
195   // Calculate mean material budget and material properties between 
196   //    the points "start" and "end".
197   //
198   // "mparam" - parameters used for the energy and multiple scattering
199   //  corrections: 
200   //
201   // mparam[0] - mean density: sum(x_i*rho_i)/sum(x_i) [g/cm3]
202   // mparam[1] - equivalent rad length fraction: sum(x_i/X0_i) [adimensional]
203   // mparam[2] - mean A: sum(x_i*A_i)/sum(x_i) [adimensional]
204   // mparam[3] - mean Z: sum(x_i*Z_i)/sum(x_i) [adimensional]
205   // mparam[4] - length: sum(x_i) [cm]
206   // mparam[5] - Z/A mean: sum(x_i*Z_i/A_i)/sum(x_i) [adimensional]
207   // mparam[6] - number of boundary crosses
208   //
209   //  Origin:  Marian Ivanov, Marian.Ivanov@cern.ch
210   //
211   //  Corrections and improvements by
212   //        Andrea Dainese, Andrea.Dainese@lnl.infn.it,
213   //        Andrei Gheata,  Andrei.Gheata@cern.ch
214   //
215
216   mparam[0]=0; mparam[1]=1; mparam[2] =0; mparam[3] =0;
217   mparam[4]=0; mparam[5]=0; mparam[6]=0;
218   //
219   Double_t bparam[6]; // total parameters
220   Double_t lparam[6]; // local parameters
221
222   for (Int_t i=0;i<6;i++) bparam[i]=0;
223
224   if (!gGeoManager) {
225     printf("ERROR: no TGeo\n");
226     return 0.;
227   }
228   //
229   Double_t length;
230   Double_t dir[3];
231   length = TMath::Sqrt((end[0]-start[0])*(end[0]-start[0])+
232                        (end[1]-start[1])*(end[1]-start[1])+
233                        (end[2]-start[2])*(end[2]-start[2]));
234   mparam[4]=length;
235   if (length<TGeoShape::Tolerance()) return 0.0;
236   Double_t invlen = 1./length;
237   dir[0] = (end[0]-start[0])*invlen;
238   dir[1] = (end[1]-start[1])*invlen;
239   dir[2] = (end[2]-start[2])*invlen;
240
241   // Initialize start point and direction
242   TGeoNode *currentnode = 0;
243   TGeoNode *startnode = gGeoManager->InitTrack(start, dir);
244   //printf("%s length=%f\n",gGeoManager->GetPath(),length);
245   if (!startnode) {
246     AliErrorClass(Form("start point out of geometry: x %f, y %f, z %f",
247                   start[0],start[1],start[2]));
248     return 0.0;
249   }
250   TGeoMaterial *material = startnode->GetVolume()->GetMedium()->GetMaterial();
251   lparam[0]   = material->GetDensity();
252   lparam[1]   = material->GetRadLen();
253   lparam[2]   = material->GetA();
254   lparam[3]   = material->GetZ();
255   lparam[4]   = length;
256   lparam[5]   = lparam[3]/lparam[2];
257   if (material->IsMixture()) {
258     TGeoMixture * mixture = (TGeoMixture*)material;
259     lparam[5] =0;
260     Double_t sum =0;
261     for (Int_t iel=0;iel<mixture->GetNelements();iel++){
262       sum  += mixture->GetWmixt()[iel];
263       lparam[5]+= mixture->GetZmixt()[iel]*mixture->GetWmixt()[iel]/mixture->GetAmixt()[iel];
264     }
265     lparam[5]/=sum;
266   }
267
268   // Locate next boundary within length without computing safety.
269   // Propagate either with length (if no boundary found) or just cross boundary
270   gGeoManager->FindNextBoundaryAndStep(length, kFALSE);
271   Double_t step = 0.0; // Step made
272   Double_t snext = gGeoManager->GetStep();
273   // If no boundary within proposed length, return current density
274   if (!gGeoManager->IsOnBoundary()) {
275     mparam[0] = lparam[0];
276     mparam[1] = lparam[4]/lparam[1];
277     mparam[2] = lparam[2];
278     mparam[3] = lparam[3];
279     mparam[4] = lparam[4];
280     return lparam[0];
281   }
282   // Try to cross the boundary and see what is next
283   Int_t nzero = 0;
284   while (length>TGeoShape::Tolerance()) {
285     currentnode = gGeoManager->GetCurrentNode();
286     if (snext<2.*TGeoShape::Tolerance()) nzero++;
287     else nzero = 0;
288     if (nzero>3) {
289       // This means navigation has problems on one boundary
290       // Try to cross by making a small step
291       printf("ERROR: cannot cross boundary\n");
292       mparam[0] = bparam[0]/step;
293       mparam[1] = bparam[1];
294       mparam[2] = bparam[2]/step;
295       mparam[3] = bparam[3]/step;
296       mparam[5] = bparam[5]/step;
297       mparam[4] = step;
298       mparam[0] = 0.;             // if crash of navigation take mean density 0
299       mparam[1] = 1000000;        // and infinite rad length
300       return bparam[0]/step;
301     }
302     mparam[6]+=1.;
303     step += snext;
304     bparam[1]    += snext/lparam[1];
305     bparam[2]    += snext*lparam[2];
306     bparam[3]    += snext*lparam[3];
307     bparam[5]    += snext*lparam[5];
308     bparam[0]    += snext*lparam[0];
309
310     if (snext>=length) break;
311     if (!currentnode) break;
312     length -= snext;
313     //printf("%s snext=%f length=%f\n", currentnode->GetName(),snext,length);
314     material = currentnode->GetVolume()->GetMedium()->GetMaterial();
315     lparam[0] = material->GetDensity();
316     lparam[1]  = material->GetRadLen();
317     lparam[2]  = material->GetA();
318     lparam[3]  = material->GetZ();
319     //printf("       %f %f %f %f\n",lparam[0],lparam[1],lparam[2],lparam[3]); 
320     lparam[5]   = lparam[3]/lparam[2];
321     if (material->IsMixture()) {
322       TGeoMixture * mixture = (TGeoMixture*)material;
323       lparam[5]=0;
324       Double_t sum =0;
325       for (Int_t iel=0;iel<mixture->GetNelements();iel++){
326         sum+= mixture->GetWmixt()[iel];
327         lparam[5]+= mixture->GetZmixt()[iel]*mixture->GetWmixt()[iel]/mixture->GetAmixt()[iel];
328       }
329       lparam[5]/=sum;
330     }
331     gGeoManager->FindNextBoundaryAndStep(length, kFALSE);
332     snext = gGeoManager->GetStep();
333     //printf("snext %f\n",snext);
334   }
335   mparam[0] = bparam[0]/step;
336   mparam[1] = bparam[1];
337   mparam[2] = bparam[2]/step;
338   mparam[3] = bparam[3]/step;
339   mparam[5] = bparam[5]/step;
340   return bparam[0]/step;
341 }
342
343
344 Bool_t 
345 AliTracker::PropagateTrackTo(AliExternalTrackParam *track, Double_t xToGo, 
346 Double_t mass, Double_t maxStep, Bool_t rotateTo, Double_t maxSnp){
347   //----------------------------------------------------------------
348   //
349   // Propagates the track to the plane X=xk (cm) using the magnetic field map 
350   // and correcting for the crossed material.
351   //
352   // mass     - mass used in propagation - used for energy loss correction
353   // maxStep  - maximal step for propagation
354   //
355   //  Origin: Marian Ivanov,  Marian.Ivanov@cern.ch
356   //
357   //----------------------------------------------------------------
358   const Double_t kEpsilon = 0.00001;
359   Double_t xpos     = track->GetX();
360   Double_t dir      = (xpos<xToGo) ? 1.:-1.;
361   //
362   while ( (xToGo-xpos)*dir > kEpsilon){
363     Double_t step = dir*TMath::Min(TMath::Abs(xToGo-xpos), maxStep);
364     Double_t x    = xpos+step;
365     Double_t xyz0[3],xyz1[3],param[7];
366     track->GetXYZ(xyz0);   //starting global position
367
368     Double_t bz=GetBz(xyz0); // getting the local Bz
369
370     if (!track->GetXYZAt(x,bz,xyz1)) return kFALSE;   // no prolongation
371     xyz1[2]+=kEpsilon; // waiting for bug correction in geo
372
373     if (TMath::Abs(track->GetSnpAt(x,bz)) >= maxSnp) return kFALSE;
374     if (!track->PropagateTo(x,bz))  return kFALSE;
375
376     MeanMaterialBudget(xyz0,xyz1,param);        
377     Double_t xrho=param[0]*param[4], xx0=param[1];
378
379     if (!track->CorrectForMeanMaterial(xx0,xrho,mass)) return kFALSE;
380     if (rotateTo){
381       if (TMath::Abs(track->GetSnp()) >= maxSnp) return kFALSE;
382       track->GetXYZ(xyz0);   // global position
383       Double_t alphan = TMath::ATan2(xyz0[1], xyz0[0]); 
384       //
385       Double_t ca=TMath::Cos(alphan-track->GetAlpha()), 
386                sa=TMath::Sin(alphan-track->GetAlpha());
387       Double_t sf=track->GetSnp(), cf=TMath::Sqrt((1.-sf)*(1.+sf));
388       Double_t sinNew =  sf*ca - cf*sa;
389       if (TMath::Abs(sinNew) >= maxSnp) return kFALSE;
390       if (!track->Rotate(alphan)) return kFALSE;
391     }
392     xpos = track->GetX();
393   }
394   return kTRUE;
395 }
396
397 Bool_t 
398 AliTracker::PropagateTrackToBxByBz(AliExternalTrackParam *track,
399 Double_t xToGo, 
400 Double_t mass, Double_t maxStep, Bool_t rotateTo, Double_t maxSnp){
401   //----------------------------------------------------------------
402   //
403   // Propagates the track to the plane X=xk (cm)
404   // taking into account all the three components of the magnetic field 
405   // and correcting for the crossed material.
406   //
407   // mass     - mass used in propagation - used for energy loss correction
408   // maxStep  - maximal step for propagation
409   //
410   //  Origin: Marian Ivanov,  Marian.Ivanov@cern.ch
411   //
412   //----------------------------------------------------------------
413   const Double_t kEpsilon = 0.00001;
414   Double_t xpos     = track->GetX();
415   Double_t dir      = (xpos<xToGo) ? 1.:-1.;
416   //
417   while ( (xToGo-xpos)*dir > kEpsilon){
418     Double_t step = dir*TMath::Min(TMath::Abs(xToGo-xpos), maxStep);
419     Double_t x    = xpos+step;
420     Double_t xyz0[3],xyz1[3],param[7];
421     track->GetXYZ(xyz0);   //starting global position
422
423     Double_t b[3]; GetBxByBz(xyz0,b); // getting the local Bx, By and Bz
424
425     if (!track->GetXYZAt(x,b[2],xyz1)) return kFALSE;   // no prolongation
426     xyz1[2]+=kEpsilon; // waiting for bug correction in geo
427
428     if (TMath::Abs(track->GetSnpAt(x,b[2])) >= maxSnp) return kFALSE;
429     if (!track->PropagateToBxByBz(x,b))  return kFALSE;
430
431     MeanMaterialBudget(xyz0,xyz1,param);        
432     Double_t xrho=param[0]*param[4], xx0=param[1];
433
434     if (!track->CorrectForMeanMaterial(xx0,xrho,mass)) return kFALSE;
435     if (rotateTo){
436       if (TMath::Abs(track->GetSnp()) >= maxSnp) return kFALSE;
437       track->GetXYZ(xyz0);   // global position
438       Double_t alphan = TMath::ATan2(xyz0[1], xyz0[0]); 
439       //
440       Double_t ca=TMath::Cos(alphan-track->GetAlpha()), 
441                sa=TMath::Sin(alphan-track->GetAlpha());
442       Double_t sf=track->GetSnp(), cf=TMath::Sqrt((1.-sf)*(1.+sf));
443       Double_t sinNew =  sf*ca - cf*sa;
444       if (TMath::Abs(sinNew) >= maxSnp) return kFALSE;
445       if (!track->Rotate(alphan)) return kFALSE;
446     }
447     xpos = track->GetX();
448   }
449   return kTRUE;
450 }
451
452 void AliTracker::FillResiduals(const AliExternalTrackParam *t,
453                               Double_t *p, Double_t *cov, 
454                               UShort_t id, Bool_t updated) {
455   //
456   // This function fills the histograms of residuals 
457   // The array of these histos is external for this AliTracker class.
458   // Normally, this array belong to AliGlobalQADataMaker class.  
459   // 
460   if (!fFillResiduals) return; 
461   if (!fResiduals) return; 
462
463   const Double_t *residuals=t->GetResiduals(p,cov,updated);
464   if (!residuals) return;
465
466   TH1F *h=0;
467   Int_t esIndex = AliRecoParam::AConvert(fEventSpecie) ; 
468   AliGeomManager::ELayerID layer=AliGeomManager::VolUIDToLayer(id);
469   h=(TH1F*)fResiduals[esIndex]->At(2*layer-2);
470   h->Fill(residuals[0]);
471   h=(TH1F*)fResiduals[esIndex]->At(2*layer-1);
472   h->Fill(residuals[1]);
473
474   if (layer==5) {
475     if (p[1]<0) {  // SSD1 absolute residuals
476        ((TH1F*)fResiduals[esIndex]->At(40))->Fill(t->GetY()-p[0]); //C side
477        ((TH1F*)fResiduals[esIndex]->At(41))->Fill(t->GetZ()-p[1]);
478     } else {             
479        ((TH1F*)fResiduals[esIndex]->At(42))->Fill(t->GetY()-p[0]); //A side
480        ((TH1F*)fResiduals[esIndex]->At(43))->Fill(t->GetZ()-p[1]);
481     }           
482   }
483   if (layer==6) {  // SSD2 absolute residuals
484     if (p[1]<0) {
485        ((TH1F*)fResiduals[esIndex]->At(44))->Fill(t->GetY()-p[0]); //C side
486        ((TH1F*)fResiduals[esIndex]->At(45))->Fill(t->GetZ()-p[1]);
487     } else {
488        ((TH1F*)fResiduals[esIndex]->At(46))->Fill(t->GetY()-p[0]); //A side
489        ((TH1F*)fResiduals[esIndex]->At(47))->Fill(t->GetZ()-p[1]);
490     }
491   }
492
493 }
494
495 void AliTracker::FillResiduals(const AliExternalTrackParam *t,
496                                const AliCluster *c, Bool_t /*updated*/) {
497   //
498   // This function fills the histograms of residuals 
499   // The array of these histos is external for this AliTracker class.
500   // Normally, this array belong to AliGlobalQADataMaker class.  
501   // 
502   // For the moment, the residuals are absolute !
503   //
504
505   if (!fFillResiduals) return; 
506   if (!fResiduals) return; 
507
508   UShort_t id=c->GetVolumeId();
509   const TGeoHMatrix *matrixT2L=AliGeomManager::GetTracking2LocalMatrix(id);
510
511   // Position of the cluster in the tracking c.s.
512   Double_t clsTrk[3]={c->GetX(), c->GetY(), c->GetZ()};
513   // Position of the cluster in the local module c.s.
514   Double_t clsLoc[3]={0.,0.,0.};
515   matrixT2L->LocalToMaster(clsTrk,clsLoc);
516
517
518   // Position of the intersection point in the tracking c.s.
519   Double_t trkTrk[3]={t->GetX(),t->GetY(),t->GetZ()};
520   // Position of the intersection point in the local module c.s.
521   Double_t trkLoc[3]={0.,0.,0.};
522   matrixT2L->LocalToMaster(trkTrk,trkLoc);
523
524   Double_t residuals[2]={trkLoc[0]-clsLoc[0], trkLoc[2]-clsLoc[2]};
525
526   TH1F *h=0;
527   Int_t esIndex = AliRecoParam::AConvert(fEventSpecie) ; 
528   AliGeomManager::ELayerID layer=AliGeomManager::VolUIDToLayer(id);
529   h=(TH1F*)fResiduals[esIndex]->At(2*layer-2);
530   h->Fill(residuals[0]);
531   h=(TH1F*)fResiduals[esIndex]->At(2*layer-1);
532   h->Fill(residuals[1]);
533
534 }