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