Event server (Mihai)
[u/mrichter/AliRoot.git] / STEER / STEER / AliTrackFitterKalman.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 //
18 //                      Kalman-Filter-like fit 
19 //   to a straight-line crossing a set of arbitrarily oriented planes.
20 //   The resulting line is given by the equation:
21 //                  (x-x0)/vx = (y-y0)/1 = (z-z0)/vz
22 //   Parameters of the fit are:
23 //        x0,y0,z0 (a point on the line) and
24 //        vx,1,vz  (a vector collinear with the line)
25 //
26 //   LIMITATION:  The line must not be perpendicular to the Y axis. 
27 //
28 //          Origin: Iouri Belikov, CERN, Jouri.Belikov@cern.ch
29 //
30 //////////////////////////////////////////////////////////////////////////////
31
32 #include <TMatrixD.h>
33 #include <TMatrixDSym.h>
34
35 #include "AliLog.h"
36 #include "AliTrackFitterKalman.h"
37
38 ClassImp(AliTrackFitterKalman)
39
40 const Double_t AliTrackFitterKalman::fgkMaxChi2=33.;
41
42 AliTrackFitterKalman::
43 AliTrackFitterKalman(AliTrackPointArray *array, Bool_t owner):
44   AliTrackFitter(array,owner),
45   fMaxChi2(fgkMaxChi2)
46 {
47   //
48   // Constructor
49   //
50 }
51
52 Bool_t AliTrackFitterKalman::Begin(Int_t first, Int_t last) {
53   //
54   // Make a seed out of the track points with the indices "first" and "last". 
55   // This is the "default" seed.
56   //
57   fPoints->Sort();
58   AliTrackPoint fp,lp;
59   fPoints->GetPoint(fp,first); fPoints->GetPoint(lp,last);
60   return MakeSeed(&fp,&lp);
61 }
62
63
64 Bool_t AliTrackFitterKalman::
65 MakeSeed(const AliTrackPoint *p0, const AliTrackPoint *p1) {
66   //
67   // Make a seed out of the two track points 
68   //
69   Double_t x0=p0->GetX(), y0=p0->GetY(), z0=p0->GetZ();
70   Double_t dx=p1->GetX()-x0, dy=p1->GetY()-y0, dz=p1->GetZ()-z0;
71   if (dy==0.) { 
72      AliError("Seeds perpendicular to Y axis are not allowed !"); 
73      return kFALSE; 
74   }
75   Double_t vx=dx/dy;
76   Double_t vz=dz/dy;
77   Double_t par[5]={x0,y0,z0,vx,vz};
78
79   const Float_t *cv0=p0->GetCov();
80   const Float_t *cv1=p1->GetCov();
81   Double_t rdy2=(cv0[3]+cv1[3])/dy/dy;
82   Double_t svx2=(cv0[0]+cv1[0])/dy/dy + vx*vx*rdy2;     
83   Double_t svz2=(cv0[5]+cv1[5])/dy/dy + vz*vz*rdy2;     
84   Double_t cov[15]={
85      cv0[0],
86      cv0[1],cv0[3],
87      cv0[2],cv0[4],cv0[5],
88      0.,0.,0.,svx2,
89      0.,0.,0.,0.,svz2
90   };
91
92   SetSeed(par,cov);
93
94   return kTRUE;
95 }
96
97 Bool_t AliTrackFitterKalman::AddPoint(const AliTrackPoint *p)
98 {
99   //
100   // Add a point to the fit
101   //
102
103   if (!Propagate(p))   return kFALSE;
104   Double_t chi2=GetPredictedChi2(p);
105   if (chi2>fMaxChi2)   return kFALSE;
106   if (!Update(p,chi2)) return kFALSE;
107   
108   return kTRUE;
109 }
110
111
112 Double_t AliTrackFitterKalman::GetPredictedChi2(const AliTrackPoint *p) const {
113   //
114   // Calculate the predicted chi2 increment.
115   //
116
117   Float_t txyz[3]={static_cast<Float_t>(GetParam()[0]),static_cast<Float_t>(GetParam()[1]),static_cast<Float_t>(GetParam()[2])};
118   TMatrixDSym &cv=*fCov;
119   Float_t tcov[6]={
120     static_cast<Float_t>(cv(0,0)),static_cast<Float_t>(cv(1,0)),static_cast<Float_t>(cv(2,0)),
121             static_cast<Float_t>(cv(1,1)),static_cast<Float_t>(cv(2,1)),
122                     static_cast<Float_t>(cv(2,2))
123   };
124   AliTrackPoint tp(txyz,tcov,p->GetVolumeID());
125
126   Double_t chi2=p->GetResidual(tp,kTRUE);
127
128   return chi2;
129 }
130
131
132 Bool_t AliTrackFitterKalman::Propagate(const AliTrackPoint *p) {
133   //
134   // Propagate the track towards the measured point "p"
135   //
136
137   TMatrixDSym &cv=*fCov;
138   Double_t s=p->GetY() - fParams[1];
139   Double_t sig2=s*s/12.; 
140
141   Double_t vx=fParams[3], vz=fParams[4];
142   fParams[0] += s*vx;
143   fParams[1] += s;
144   fParams[2] += s*vz;
145
146   Double_t 
147   c00 = cv(0,0) + 2*s*cv(3,0) + s*s*cv(3,3) + vx*vx*sig2,
148
149   c10 = cv(1,0) + s*cv(1,3) + vx*sig2, c11=cv(1,1) + sig2,
150   
151   c20 = cv(2,0) + s*(cv(4,0) + cv(2,3)) + s*s*cv(4,3) + vx*vz*sig2,
152   c21 = cv(2,1) + s*cv(4,1) + vz*sig2,
153   c22 = cv(2,2) + 2*s*cv(4,2) + s*s*cv(4,4) + vz*vz*sig2,
154
155   c30 = cv(3,0) + s*cv(3,3), c31 = cv(3,1),
156   c32 = cv(3,2) + s*cv(3,4), c33 = cv(3,3),
157
158   c40 = cv(4,0) + s*cv(4,3), c41 = cv(4,1),
159   c42 = cv(4,2) + s*cv(4,4), c43 = cv(4,3), c44 = cv(4,4);
160
161
162   cv(0,0)=c00; cv(0,1)=c10; cv(0,2)=c20; cv(0,3)=c30; cv(0,4)=c40;
163   cv(1,0)=c10; cv(1,1)=c11; cv(1,2)=c21; cv(1,3)=c31; cv(1,4)=c41;
164   cv(2,0)=c20; cv(2,1)=c21; cv(2,2)=c22; cv(2,3)=c32; cv(2,4)=c42;
165   cv(3,0)=c30; cv(3,1)=c31; cv(3,2)=c32; cv(3,3)=c33; cv(3,4)=c43;
166   cv(4,0)=c40; cv(4,1)=c41; cv(4,2)=c42; cv(4,3)=c43; cv(4,4)=c44;
167
168   return kTRUE;
169 }
170
171 Bool_t AliTrackFitterKalman::Update(const AliTrackPoint *p, Double_t chi2) {
172   //
173   // Update the track params using the measured point "p"
174   //
175
176   TMatrixDSym &c=*fCov;
177   const Float_t *cov=p->GetCov();
178
179   TMatrixDSym v(3);
180   v(0,0)=cov[0]+c(0,0); v(0,1)=cov[1]+c(0,1); v(0,2)=cov[2]+c(0,2);
181   v(1,0)=cov[1]+c(1,0); v(1,1)=cov[3]+c(1,1); v(1,2)=cov[4]+c(1,2);
182   v(2,0)=cov[2]+c(2,0); v(2,1)=cov[4]+c(2,1); v(2,2)=cov[5]+c(2,2);
183   if (TMath::Abs(v.Determinant()) < 1.e-33) return kFALSE;
184   v.Invert();
185
186   TMatrixD ch(5,3);
187   ch(0,0)=c(0,0); ch(0,1)=c(0,1); ch(0,2)=c(0,2);
188   ch(1,0)=c(1,0); ch(1,1)=c(1,1); ch(1,2)=c(1,2);
189   ch(2,0)=c(2,0); ch(2,1)=c(2,1); ch(2,2)=c(2,2);
190   ch(3,0)=c(3,0); ch(3,1)=c(3,1); ch(3,2)=c(3,2);
191   ch(4,0)=c(4,0); ch(4,1)=c(4,1); ch(4,2)=c(4,2);
192
193   TMatrixD k(ch,TMatrixD::kMult,v);
194
195   TMatrixD d(3,1);
196   d(0,0) = p->GetX() - fParams[0];
197   d(1,0) = p->GetY() - fParams[1];
198   d(2,0) = p->GetZ() - fParams[2];
199
200   TMatrixD x(k,TMatrixD::kMult,d);
201
202   fParams[0]+=x(0,0);
203   fParams[1]+=x(1,0);
204   fParams[2]+=x(2,0);
205   fParams[3]+=x(3,0);
206   fParams[4]+=x(4,0);
207
208   TMatrixD hc(3,5);
209   hc(0,0)=c(0,0);hc(0,1)=c(0,1);hc(0,2)=c(0,2);hc(0,3)=c(0,3);hc(0,4)=c(0,4);
210   hc(1,0)=c(1,0);hc(1,1)=c(1,1);hc(1,2)=c(1,2);hc(1,3)=c(1,3);hc(1,4)=c(1,4);
211   hc(2,0)=c(2,0);hc(2,1)=c(2,1);hc(2,2)=c(2,2);hc(2,3)=c(2,3);hc(2,4)=c(2,4);
212   
213   TMatrixD s(k,TMatrixD::kMult,hc);
214
215   c(0,0)-=s(0,0);c(0,1)-=s(0,1);c(0,2)-=s(0,2);c(0,3)-=s(0,3);c(0,4)-=s(0,4);
216   c(1,0)-=s(1,0);c(1,1)-=s(1,1);c(1,2)-=s(1,2);c(1,3)-=s(1,3);c(1,4)-=s(1,4);
217   c(2,0)-=s(2,0);c(2,1)-=s(2,1);c(2,2)-=s(2,2);c(2,3)-=s(2,3);c(2,4)-=s(2,4);
218   c(3,0)-=s(3,0);c(3,1)-=s(3,1);c(3,2)-=s(3,2);c(3,3)-=s(3,3);c(3,4)-=s(3,4);
219   c(4,0)-=s(4,0);c(4,1)-=s(4,1);c(4,2)-=s(4,2);c(4,3)-=s(4,3);c(4,4)-=s(4,4);
220
221   fChi2 += chi2;
222   fNdf  += 2;
223
224   return kTRUE;
225 }
226
227 //_____________________________________________________________________________
228 Bool_t AliTrackFitterKalman::GetPCA(const AliTrackPoint &p, AliTrackPoint &i) const
229 {
230   //
231   // Get the intersection point "i" between the track and the plane
232   // the point "p" belongs to.
233   //
234
235   TMatrixD t(3,1);
236   Double_t s=p.GetY() - fParams[1];
237   Double_t vx=fParams[3], vz=fParams[4];
238   t(0,0) = fParams[0] + s*vx;
239   t(1,0) = fParams[1] + s;
240   t(2,0) = fParams[2] + s*vz;
241   
242   TMatrixDSym tC(3);
243   {
244   Double_t sig2=s*s/12.;
245
246   tC(0,0) = vx*vx*sig2;
247   tC(1,0) = vx*sig2; 
248   tC(1,1) = sig2;
249   tC(2,0) = vx*vz*sig2;
250   tC(2,1) = vz*sig2;
251   tC(2,2) = vz*vz*sig2;
252
253   tC(0,1) = tC(1,0); tC(0,2) = tC(2,0);
254                      tC(1,2) = tC(2,1);
255   }
256
257   TMatrixD m(3,1);
258   m(0,0)=p.GetX();
259   m(1,0)=p.GetY();
260   m(2,0)=p.GetZ();
261  
262   TMatrixDSym mC(3);
263   {
264   const Float_t *cv=p.GetCov();
265   mC(0,0)=cv[0]; mC(0,1)=cv[1]; mC(0,2)=cv[2];
266   mC(1,0)=cv[1]; mC(1,1)=cv[3]; mC(1,2)=cv[4];
267   mC(2,0)=cv[2]; mC(2,1)=cv[4]; mC(2,2)=cv[5];
268   }
269
270   TMatrixDSym tmW(tC);
271   tmW+=mC;
272   if (TMath::Abs(tmW.Determinant()) < 1.e-33) return kFALSE;
273   tmW.Invert();
274
275   TMatrixD mW(tC,TMatrixD::kMult,tmW);
276   TMatrixD tW(mC,TMatrixD::kMult,tmW);
277
278   TMatrixD mi(mW,TMatrixD::kMult,m);
279   TMatrixD ti(tW,TMatrixD::kMult,t);
280   ti+=mi;
281
282   TMatrixD iC(tC,TMatrixD::kMult,tmW);
283   iC*=mC;
284   Double_t sig2=1.;  // Releasing the matrix by 1 cm along the track direction 
285   iC(0,0) += vx*vx*sig2;
286   iC(0,1) += vx*sig2; 
287   iC(1,1) += sig2;
288   iC(0,2) += vx*vz*sig2;
289   iC(1,2) += vz*sig2;
290   iC(2,2) += vz*vz*sig2;
291
292
293   Float_t cov[6]={
294     static_cast<Float_t>(iC(0,0)), static_cast<Float_t>(iC(0,1)), static_cast<Float_t>(iC(0,2)),
295              static_cast<Float_t>(iC(1,1)), static_cast<Float_t>(iC(1,2)),
296                       static_cast<Float_t>(iC(2,2))
297   };
298   i.SetXYZ(ti(0,0),ti(1,0),ti(2,0),cov);
299   UShort_t id=p.GetVolumeID();
300   i.SetVolumeID(id);
301
302   return kTRUE;
303 }
304
305
306 //_____________________________________________________________________________
307 void 
308 AliTrackFitterKalman::SetSeed(const Double_t par[5], const Double_t cov[15]) {
309   //
310   // Set the initial approximation for the track parameters
311   //
312   for (Int_t i=0; i<5; i++) fParams[i]=par[i];
313   fParams[5]=0.;
314
315   delete fCov;
316   fCov=new TMatrixDSym(5);
317   TMatrixDSym &cv=*fCov;
318
319   cv(0,0)=cov[0 ];
320   cv(1,0)=cov[1 ]; cv(1,1)=cov[2 ];
321   cv(2,0)=cov[3 ]; cv(2,1)=cov[4 ]; cv(2,2)=cov[5 ];
322   cv(3,0)=cov[6 ]; cv(3,1)=cov[7 ]; cv(3,2)=cov[8 ]; cv(3,3)=cov[9 ];
323   cv(4,0)=cov[10]; cv(4,1)=cov[11]; cv(4,2)=cov[12]; cv(4,3)=cov[13]; cv(4,4)=cov[14];
324  
325   cv(0,1)=cv(1,0);
326   cv(0,2)=cv(2,0); cv(1,2)=cv(2,1);
327   cv(0,3)=cv(3,0); cv(1,3)=cv(3,1); cv(2,3)=cv(3,2);
328   cv(0,4)=cv(4,0); cv(1,4)=cv(4,1); cv(2,4)=cv(4,2); cv(3,4)=cv(4,3);
329
330 }