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