]> git.uio.no Git - u/mrichter/AliRoot.git/blob - ITS/AliITSNeuralTrack.cxx
Neural ITS standalone tracking revisited
[u/mrichter/AliRoot.git] / ITS / AliITSNeuralTrack.cxx
1 #include <Riostream.h>
2 #include <cstdlib>
3 #include <cstring>
4
5 #include <TObject.h>
6 #include <TROOT.h>
7 #include <TMath.h>
8 #include <TString.h>
9 #include <TObjArray.h>
10 #include <TH1.h>
11 #include <TMatrixD.h>
12
13 //#include "AliITSVertex.h"
14 #include "AliITSIOTrack.h"
15 #include "AliITSNeuralPoint.h"
16
17 #include "AliITSNeuralTrack.h"
18
19
20
21 ClassImp(AliITSNeuralTrack)
22 //
23 //
24 //
25 AliITSNeuralTrack::AliITSNeuralTrack() : fMatrix(5,5), fVertex()
26 {
27         Int_t i;
28
29         fMass  = 0.1396;   // default assumption: pion
30         fField = 2.0;      // default assumption: B = 0.4 Tesla
31
32         fXC = fYC = fR = fC = 0.0;
33         fTanL = fG0 = fDt = fDz = 0.0;
34         fStateR = fStatePhi = fStateZ = fChi2 = fNSteps = 0.0;
35
36         fLabel = 0;
37         fCount = 0;
38         for (i = 0; i < 6; i++) fPoint[i] = 0;
39
40         fVertex.X() = 0.0;
41         fVertex.Y() = 0.0;
42         fVertex.Z() = 0.0;
43         fVertex.ErrX() = 0.0;
44         fVertex.ErrY() = 0.0;
45         fVertex.ErrZ() = 0.0;
46 }
47 //
48 //
49 //
50 AliITSNeuralTrack::~AliITSNeuralTrack()
51 {
52         Int_t l;
53         for (l = 0; l < 6; l++) fPoint[l] = 0;
54 }
55 //
56 //
57 //
58 void AliITSNeuralTrack::AssignLabel()
59 // Assigns a GEANT label to the found track. 
60 // Every cluster has up to three labels (it can have less). Then each label is 
61 // recorded for each point. Then, counts are made to check if some of the labels
62 // appear more than once. Finally, the label which appears most times is assigned
63 // to the track in the field fLabel.
64 // The number of points containing that label is counted in the fCount data-member. 
65 {       
66         Bool_t found;
67         Int_t i, j, l, lab, max = 0;
68         
69         // We have up to 6 points for 3 labels each => up to 18 possible different values
70         Int_t idx[18] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
71         Int_t count[18] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
72         
73         for (l = 0; l < 6; l++) {
74                 if (!fPoint[l]) continue;
75                 // Sometimes the same label appears two times in the same recpoint.
76                 // With these if statements, such problem is solved by turning
77                 // one of them to -1.
78                 if (fPoint[l]->GetLabel(1) >= 0 && fPoint[l]->GetLabel(1) == fPoint[l]->GetLabel(0))
79                         fPoint[l]->SetLabel(1, -1);
80                 if (fPoint[l]->GetLabel(2) >= 0 && fPoint[l]->GetLabel(2) == fPoint[l]->GetLabel(0))
81                         fPoint[l]->SetLabel(2, -1);
82                 if (fPoint[l]->GetLabel(2) >= 0 && fPoint[l]->GetLabel(2) == fPoint[l]->GetLabel(1))
83                         fPoint[l]->SetLabel(2, -1);
84                 for (i = 0; i < 3; i++) {
85                         lab = fPoint[l]->GetLabel(i);
86                         if (lab < 0) continue;
87                         found = kFALSE;
88                         for (j = 0; j < max; j++) {
89                                 if (idx[j] == lab) {
90                                         count[j]++;
91                                         found = kTRUE;
92                                 }
93                         }
94                         if(!found) {
95                                 max++;
96                                 idx[max - 1] = lab;
97                                 count[max - 1] = 1;
98                         }
99                 }
100         }
101         
102         j = 0, max = count[0];
103         for (i = 0; i < 18; i++) {
104                 if (count[i] > max) {
105                         j = i;
106                         max = count[i];
107                 }
108         }
109         fLabel = idx[j];
110         fCount = count[j];
111 }
112 //
113 //
114 //
115 void AliITSNeuralTrack::CleanSlot(Int_t i, Bool_t del)
116 // Removes a point from the corresponding layer slot in the found track.
117 // If the argument is TRUE, the point object is also deleted from heap.
118 {
119         if (i >= 0 && i < 6) {
120                 if (del) delete fPoint[i];
121                 fPoint[i] = 0;
122         }
123 }
124 //
125 //
126 //
127 void AliITSNeuralTrack::GetModuleData(Int_t layer, Int_t &mod, Int_t &pos)
128 // Returns the point coordinates according to the TreeR philosophy in galice.root files
129 // that consist in the module number (mod) and the position in the TClonesArray of
130 // the points reconstructed in that module for the run being examined.
131 {
132         if (layer < 0 || layer > 5) {
133                 Error("GetModuleData", "Layer out of range: %d", layer);
134                 return;
135         }
136         mod = fPoint[layer]->GetModule();
137         pos = fPoint[layer]->GetIndex();
138 }
139 //
140 //
141 //
142 void AliITSNeuralTrack::Insert(AliITSNeuralPoint *point)
143 // A trivial method to insert a point in the tracks;
144 // the point is inserted to the slot corresponding to its ITS layer.
145 {
146         if (!point) return;
147         
148         Int_t layer = point->GetLayer();
149         if (layer < 0 || layer > 6) {
150                 Error("Insert", "Layer index %d out of range", layer);
151                 return;
152         } 
153         
154         fPoint[layer] = point;
155 }
156 //
157 //
158 //
159 Int_t AliITSNeuralTrack::OccupationMask()
160 // Returns a byte which maps the occupied slots. 
161 // Each bit represents a layer going from the less significant on.
162 {
163         Int_t i, check, mask = 0;
164         for (i = 0; i < 6; i++) {
165                 check = 1 << i;
166                 if (fPoint[i]) mask |= check;
167         }
168         return mask;
169 }
170 //
171 //
172 //
173 void AliITSNeuralTrack::PrintLabels()
174 // Prints the results of the AssignLabel() method, together with
175 // the GEANT labels assigned to each point, in order to evaluate 
176 // how the assigned label is distributed among points.
177 {
178         cout << "Assigned label = " << fLabel << " -- counted " << fCount << " times: " << endl << endl;
179         for (Int_t i = 0; i < 6; i++) {
180                 cout << "Point #" << i + 1 << " --> ";
181                 if (fPoint[i]) {
182                         cout << "labels = " << fPoint[i]->GetLabel(0) << ", ";
183                         cout << fPoint[i]->GetLabel(1) << ", ";
184                         cout << fPoint[i]->GetLabel(2) << endl;
185                 }
186                 else {
187                         cout << "not assigned" << endl;
188                 }
189         }
190         cout << endl;
191 }
192 //
193 //
194 //
195 Bool_t AliITSNeuralTrack::AddEL(Int_t layer, Double_t sign)
196 {
197         Double_t width = 0.0;
198         switch (layer) {
199                 case 0: width = 0.00260 + 0.00283; break;
200                 case 1: width = 0.0180; break;
201                 case 2: width = 0.0094; break;
202                 case 3: width = 0.0095; break;
203                 case 4: width = 0.0091; break;
204                 case 5: width = 0.0087; break;
205                 default:
206                         Error("AddEL", "Layer value %d out of range!", layer);
207                         return kFALSE;
208         }
209         width *= 1.7;
210
211         if((layer == 5) && (fStatePhi < 0.174 || fStatePhi > 6.100 || (fStatePhi > 2.960 && fStatePhi < 3.31))) {
212                 width += 0.012;
213         }
214
215         Double_t invSqCosL = 1. + fTanL * fTanL;            // = 1 / (cos(lambda)^2) = 1 + tan(lambda)^2
216         Double_t invCosL   = TMath::Sqrt(invSqCosL);        // = 1  / cos(lambda)
217         Double_t pt = GetPt();                              // = transverse momentum
218         Double_t p2 = pt *pt * invSqCosL;                   // = square modulus of momentum
219         Double_t energy = TMath::Sqrt(p2 + fMass * fMass);  // = energy
220         Double_t beta2 = p2 / (p2 + fMass * fMass);         // = (v / c) ^ 2
221         if (beta2 == 0.0) {
222                 printf("Anomaly in AddEL: pt=%8.6f invSqCosL=%8.6f fMass=%8.7f --> beta2 = %8.7f\n", pt, invSqCosL, fMass, beta2);
223                 return kFALSE;
224         }
225
226         Double_t dE = 0.153 / beta2 * (log(5940. * beta2 / (1. - beta2)) - beta2) * width * 21.82 * invCosL;
227         dE = sign * dE * 0.001;
228
229         energy += dE;
230         p2 = energy * energy - fMass * fMass;
231         pt = TMath::Sqrt(p2) / invCosL;
232         if (fC < 0.) pt = -pt;
233         fC = (0.299792458 * 0.2 * fField) / (pt * 100.);
234
235         return kTRUE;
236 }
237 //
238 //
239 //
240 Bool_t AliITSNeuralTrack::AddMS(Int_t layer)
241 {
242         Double_t width = 0.0;
243         switch (layer) {
244                 case 0: width = 0.00260 + 0.00283; break;
245                 case 1: width = 0.0180; break;
246                 case 2: width = 0.0094; break;
247                 case 3: width = 0.0095; break;
248                 case 4: width = 0.0091; break;
249                 case 5: width = 0.0087; break;
250                 default:
251                         Error("AddEL", "Layer value %d out of range!", layer);
252                         return kFALSE;
253         }
254         width *= 1.7;
255
256         if((layer == 5) && (fStatePhi < 0.174 || fStatePhi > 6.100 || (fStatePhi > 2.960 && fStatePhi < 3.31))) {
257                 width += 0.012;
258         }
259
260         Double_t cosL = TMath::Cos(TMath::ATan(fTanL));
261         Double_t halfC = fC / 2.;
262         Double_t q20 = 1. / (cosL * cosL);
263         Double_t q30 = fC * fTanL;
264
265         Double_t q40 = halfC * (fStateR * fStateR - fDt * fDt) / (1. + 2. * halfC * fDt);
266         Double_t dd  = fDt + halfC * fDt * fDt - halfC * fStateR * fStateR;
267         Double_t dprova = fStateR * fStateR - dd * dd;
268         Double_t q41 = 0.;
269         if(dprova > 0.) q41 = -1. / cosL * TMath::Sqrt(dprova) / (1. + 2. * halfC *fDt);
270
271         Double_t p2 = (GetPt()*GetPt()) / (cosL * cosL);
272         Double_t beta2 = p2 / (p2 + fMass * fMass);
273         Double_t theta2 = 14.1 * 14.1 / (beta2 * p2 * 1.e6) * (width / TMath::Abs(cosL));
274
275         fMatrix(2,2) += theta2 * (q40 * q40 + q41 * q41);
276         fMatrix(3,2) += theta2 * q20 * q40;
277         fMatrix(2,3) += theta2 * q20 * q40;
278         fMatrix(3,3) += theta2 * q20 * q20;
279         fMatrix(4,2) += theta2 * q30 * q40;
280         fMatrix(2,4) += theta2 * q30 * q40;
281         fMatrix(4,3) += theta2 * q30 * q20;
282         fMatrix(3,4) += theta2 * q30 * q20;
283         fMatrix(4,4) += theta2 * q30 * q30;
284         
285         return kTRUE;
286 }
287 //
288 //
289 //
290 Int_t AliITSNeuralTrack::PropagateTo(Double_t rk)
291 {
292         // Propagation method.
293         // Changes the state vector according to a new radial position
294         // which is specified by the passed 'r' value (in cylindircal coordinates).
295         // The covariance matrix is also propagated (and enlarged) according to
296         // the FCFt technique, where F is the jacobian of the new parameters
297         // w.r.t. their old values.
298         // The option argument forces the method to add also the energy loss
299         // and the multiple scattering effects, which respectively have the effect
300         // of changing the curvature and widening the covariance matrix.
301
302         if (rk < fabs(fDt)) {
303                 Error("PropagateTo", Form("Impossible propagation to r (=%17.15g) < Dt (=%17.15g)", rk, fDt));
304                 return 0;
305         }
306         
307         Double_t duepi = 2. * TMath::Pi();
308         Double_t rkm1 = fStateR;
309         Double_t aAk = ArgPhi(rk), aAkm1 = ArgPhi(rkm1);
310         Double_t ak = ArgZ(rk), akm1 = ArgZ(rkm1);
311
312         fStatePhi += TMath::ASin(aAk) - TMath::ASin(aAkm1);
313         if(fStatePhi > duepi) fStatePhi -= duepi;
314         if(fStatePhi < 0.) fStatePhi += duepi;
315
316         Double_t halfC = 0.5 * fC;
317         fStateZ += fTanL / halfC * (TMath::ASin(ak)-TMath::ASin(akm1));
318         
319         Double_t bk = ArgB(rk), bkm1 = ArgB(rkm1);
320         Double_t ck = ArgC(rk), ckm1 = ArgC(rkm1);
321         
322         Double_t f02 = ck / TMath::Sqrt(1. - aAk * aAk) - ckm1 / TMath::Sqrt(1. - aAkm1 * aAkm1);
323         Double_t f04 = bk / TMath::Sqrt(1. - aAk * aAk) - bkm1 / TMath::Sqrt(1. - aAkm1 * aAkm1);
324         Double_t f12 = fTanL * fDt * (1. / rk - 1. / rkm1);
325         Double_t f13 = rk - rkm1;
326         
327         Double_t c00 = fMatrix(0,0);
328         Double_t c10 = fMatrix(1,0);
329         Double_t c11 = fMatrix(1,1);
330         Double_t c20 = fMatrix(2,0);
331         Double_t c21 = fMatrix(2,1);
332         Double_t c22 = fMatrix(2,2);
333         Double_t c30 = fMatrix(3,0);
334         Double_t c31 = fMatrix(3,1);
335         Double_t c32 = fMatrix(3,2);
336         Double_t c33 = fMatrix(3,3);
337         Double_t c40 = fMatrix(4,0);
338         Double_t c41 = fMatrix(4,1);
339         Double_t c42 = fMatrix(4,2);
340         Double_t c43 = fMatrix(4,3);
341         Double_t c44 = fMatrix(4,4);
342
343         Double_t r10 = c10 + c21*f02 + c41*f04;
344         Double_t r20 = c20 + c22*f02 + c42*f04;
345         Double_t r30 = c30 + c32*f02 + c43*f04;
346         Double_t r40 = c40 + c42*f02 + c44*f04;
347         Double_t r21 = c21 + c22*f12 + c32*f13;
348         Double_t r31 = c31 + c32*f12 + c33*f13;
349         Double_t r41 = c41 + c42*f12 + c43*f13;
350
351         fMatrix(0,0) = c00 + c20*f02 + c40*f04 + f02*r20 + f04*r40;
352         fMatrix(1,0) = fMatrix(0,1) = r10 + f12*r20 + f13*r30;
353         fMatrix(1,1) = c11 + c21*f12 + c31*f13 + f12*r21 + f13*r31;
354         fMatrix(2,0) = fMatrix(0,2) = r20;
355         fMatrix(2,1) = fMatrix(1,2) = r21;
356         fMatrix(3,0) = fMatrix(0,3) = r30;
357         fMatrix(3,1) = fMatrix(1,3) = r31;
358         fMatrix(4,0) = fMatrix(0,4) = r40;
359         fMatrix(4,1) = fMatrix(1,4) = r41;
360
361         fStateR = rk;
362
363         if (rkm1 < fStateR)  // going to greater R --> energy LOSS
364                 return -1;
365         else                 // going to smaller R --> energy GAIN
366                 return 1;
367 }
368 //
369 //
370 //
371 Bool_t AliITSNeuralTrack::SeedCovariance()
372 {
373         // generate a covariance matrix depending on the results obtained from
374         // the preliminary seeding fit procedure.
375         // It calculates the variances for C, D ans TanL, according to the
376         // differences of the fitted values from the requested ones necessary
377         // to make the curve exactly pass through each point.
378
379         /*
380         Int_t i, j;
381         AliITSNeuralPoint *p = 0;
382         Double_t r, argPhi, phiC, phiD, argZ, zL;
383         Double_t sumC = 0.0, sumD = 0.0, sumphi = 0., sumz = 0., sumL = 0.;
384         for (i = 0; i < fNum; i++) {
385                 p = At(i);
386                 if (!p) continue;
387                 r = p->GetR2();
388                 // weight and derivatives of phi and zeta w.r.t. various params
389                 sumphi += 1./ p->ErrorGetPhi();
390                 argPhi = ArgPhi(r);
391                 argZ = ArgZ(r);
392                 if (argPhi > 100.0 || argZ > 100.0) {
393                         Error("InitCovariance", "Argument error");
394                         return kFALSE;
395                 }
396                 phiC = DerArgPhiC(r) / TMath::Sqrt(1.0 - argPhi * argPhi);
397                 phiD = DerArgPhiD(r) / TMath::Sqrt(1.0 - argPhi * argPhi);
398                 if (phiC > 100.0 || phiD > 100.0) {
399                         Error("InitCovariance", "Argument error");
400                         return kFALSE;
401                 }
402                 zL = asin(argZ) / fC;
403                 sumL += zL * zL;
404                 sumC += phiC * phiC;
405                 sumD += phiD * phiD;
406                 sumz += 1.0 / (p->fError[2] * p->fError[2]);
407         }
408
409         for (i = 0; i < 5; i++) for (j = 0; j < 5; j++) fMatrix(i,j) = 0.;
410         fMatrix(0,0) = 1. / sumphi;
411         fMatrix(1,1) = 1. / sumz;
412         fMatrix(2,2) = 1. / sumD;
413         fMatrix(3,3) = 1. / sumL;
414         fMatrix(4,4) = 1. / sumC;
415         fMatrix.Print();
416         */
417         
418         AliITSNeuralPoint *p = 0;
419         Double_t delta, cs, sn, r, argz;
420         Double_t diffC, diffD, diffL, calcC, calcD, calcL;
421
422         Int_t l;
423         for (l = 0; l < 6; l++) {
424                 p = fPoint[l];
425                 if (!p) break;
426                 sn = TMath::Sin(p->GetPhi() - fG0);
427                 cs = TMath::Cos(p->GetPhi() - fG0);
428                 r  = p->GetR2();
429                 calcC = (fDt/r - sn) / (2.*fDt*sn - r - fDt*fDt/r);
430                 argz = ArgZ(r);
431                 if (argz > 1000.0) {
432                         Error("Covariance", "Value too high");
433                         return kFALSE;
434                 }
435                 calcL = (p->Z() - fDz) * fC / asin(argz);
436                 delta = fR*fR + r*r + 2.0*fR*r*sin(p->GetPhi() - fG0);
437                 if (delta < 0.E0) {
438                         if (delta >= -0.5)
439                                 delta = 0.;
440                         else {
441                                 Error("Covariance", Form("Discriminant = %g --- Dt = %g", delta, fDt));
442                                 return kFALSE;
443                         }
444                 }
445                 delta = sqrt(delta);
446                 if (fC >= 0)
447                         calcD = delta - fR;
448                 else
449                         calcD = fR - delta;
450                 diffD = calcD - fDt;
451                 diffL = calcL - fTanL;
452                 diffC = fC - calcC;
453                 fMatrix(0,0) += 100000000.0 * p->GetError("phi") * p->GetError("phi");
454                 fMatrix(1,1) += 10000.0 * p->ErrZ() * p->ErrZ();
455                 fMatrix(2,2) += 100000.0 * diffD * diffD;
456                 fMatrix(3,3) += diffL * diffL;
457                 fMatrix(4,4) += 100000000.0 * diffC * diffC;
458         }
459         Double_t N = 0.;
460         for (l = 0; l < 6; l++) if (fPoint[l]) N++;
461         fMatrix *= 1./(N++ * N);
462         return kTRUE;
463 }
464 //
465 //
466 //
467 Bool_t AliITSNeuralTrack::Filter(AliITSNeuralPoint *test)
468 {
469         // Makes all calculations which apply the Kalman filter to the
470         // stored guess of the state vector, after propagation to a new layer
471
472         if (!test) {
473                 Error("Filter", "Null pointer passed");
474                 return kFALSE;
475         }
476         
477         Double_t m[2];
478         Double_t rk, phik, zk;
479         rk = test->GetR2();
480         phik = test->GetPhi();
481         zk = test->Z();
482         m[0]=phik;
483         m[1]=zk;
484         
485         //////////////////////// Evaluation of the error matrix V  /////////
486         Double_t v00 = test->GetError("phi") * rk;
487         Double_t v11 = test->ErrZ();
488         ////////////////////////////////////////////////////////////////////  
489         
490         // Get the covariance matrix
491         Double_t cin00, cin10, cin20, cin30, cin40;
492         Double_t cin11, cin21, cin31, cin41, cin22;
493         Double_t cin32, cin42, cin33, cin43, cin44;
494         cin00 = fMatrix(0,0);
495         cin10 = fMatrix(1,0);
496         cin20 = fMatrix(2,0);
497         cin30 = fMatrix(3,0);
498         cin40 = fMatrix(4,0);
499         cin11 = fMatrix(1,1);
500         cin21 = fMatrix(2,1);
501         cin31 = fMatrix(3,1);
502         cin41 = fMatrix(4,1);
503         cin22 = fMatrix(2,2);
504         cin32 = fMatrix(3,2);
505         cin42 = fMatrix(4,2);
506         cin33 = fMatrix(3,3);
507         cin43 = fMatrix(4,3);
508         cin44 = fMatrix(4,4);
509         
510         // Calculate R matrix
511         Double_t rold00 = cin00 + v00;
512         Double_t rold10 = cin10;
513         Double_t rold11 = cin11 + v11;
514         
515         ////////////////////// R matrix inversion  /////////////////////////
516         Double_t det = rold00*rold11 - rold10*rold10;
517         Double_t r00 = rold11/det;
518         Double_t r10 = -rold10/det;
519         Double_t r11 = rold00/det;
520         ////////////////////////////////////////////////////////////////////
521         
522         // Calculate Kalman matrix
523         Double_t k00 = cin00*r00 + cin10*r10;
524         Double_t k01 = cin00*r10 + cin10*r11;
525         Double_t k10 = cin10*r00 + cin11*r10;  
526         Double_t k11 = cin10*r10 + cin11*r11;
527         Double_t k20 = cin20*r00 + cin21*r10;  
528         Double_t k21 = cin20*r10 + cin21*r11;  
529         Double_t k30 = cin30*r00 + cin31*r10;  
530         Double_t k31 = cin30*r10 + cin31*r11;  
531         Double_t k40 = cin40*r00 + cin41*r10;
532         Double_t k41 = cin40*r10 + cin41*r11;
533         
534         // Get state vector (will keep the old values for phi and z)
535         Double_t x0, x1, x2, x3, x4, savex0, savex1;
536         x0 = savex0 = fStatePhi;
537         x1 = savex1 = fStateZ;
538         x2 = fDt;
539         x3 = fTanL;
540         x4 = fC;
541
542         // Update the state vector
543         x0 += k00*(m[0]-savex0) + k01*(m[1]-savex1);
544         x1 += k10*(m[0]-savex0) + k11*(m[1]-savex1);
545         x2 += k20*(m[0]-savex0) + k21*(m[1]-savex1);
546         x3 += k30*(m[0]-savex0) + k31*(m[1]-savex1);
547         x4 += k40*(m[0]-savex0) + k41*(m[1]-savex1);
548         
549         // Update the covariance matrix
550         Double_t cout00, cout10, cout20, cout30, cout40;
551         Double_t cout11, cout21, cout31, cout41, cout22;
552         Double_t cout32, cout42, cout33, cout43, cout44;
553         
554         cout00 = cin00 - k00*cin00 - k01*cin10;
555         cout10 = cin10 - k00*cin10 - k01*cin11;
556         cout20 = cin20 - k00*cin20 - k01*cin21;
557         cout30 = cin30 - k00*cin30 - k01*cin31;
558         cout40 = cin40 - k00*cin40 - k01*cin41;
559         cout11 = cin11 - k10*cin10 - k11*cin11;
560         cout21 = cin21 - k10*cin20 - k11*cin21;
561         cout31 = cin31 - k10*cin30 - k11*cin31;
562         cout41 = cin41 - k10*cin40 - k11*cin41;
563         cout22 = cin22 - k20*cin20 - k21*cin21;
564         cout32 = cin32 - k20*cin30 - k21*cin31;
565         cout42 = cin42 - k20*cin40 - k21*cin41;
566         cout33 = cin33 - k30*cin30 - k31*cin31;
567         cout43 = cin43 - k30*cin40 - k31*cin41;
568         cout44 = cin44 - k40*cin40 - k41*cin41;
569         
570         // Store the new covariance matrix
571         fMatrix(0,0) = cout00;
572         fMatrix(1,0) = fMatrix(0,1) = cout10;
573         fMatrix(2,0) = fMatrix(0,2) = cout20;
574         fMatrix(3,0) = fMatrix(0,3) = cout30;
575         fMatrix(4,0) = fMatrix(0,4) = cout40;
576         fMatrix(1,1) = cout11;
577         fMatrix(2,1) = fMatrix(1,2) = cout21;
578         fMatrix(3,1) = fMatrix(1,3) = cout31;
579         fMatrix(4,1) = fMatrix(1,4) = cout41;
580         fMatrix(2,2) = cout22;
581         fMatrix(3,2) = fMatrix(2,3) = cout32;
582         fMatrix(4,2) = fMatrix(2,4) = cout42;
583         fMatrix(3,3) = cout33;
584         fMatrix(4,3) = fMatrix(3,4) = cout43;
585         fMatrix(4,4) = cout44;
586         
587         // Calculation of the chi2 increment
588         Double_t vmcold00 = v00 - cout00;
589         Double_t vmcold10 = -cout10;
590         Double_t vmcold11 = v11 - cout11;
591         ////////////////////// Matrix vmc inversion  ///////////////////////
592         det = vmcold00*vmcold11 - vmcold10*vmcold10;
593         Double_t vmc00=vmcold11/det;
594         Double_t vmc10 = -vmcold10/det;
595         Double_t vmc11 = vmcold00/det;
596         ////////////////////////////////////////////////////////////////////
597         Double_t chi2 = (m[0] - x0)*( vmc00*(m[0] - x0) + 2.*vmc10*(m[1] - x1) ) + (m[1] - x1)*vmc11*(m[1] - x1);
598         fChi2 += chi2;
599         fNSteps++;
600         
601         return kTRUE;
602 }
603 //
604 //
605 //
606 Bool_t AliITSNeuralTrack::KalmanFit()
607 // Applies the Kalman Filter to improve the track parameters resolution.
608 // First, thre point which lies closer to the estimated helix is chosen.
609 // Then, a fit is performed towards the 6th layer
610 // Finally, the track is refitted to the 1st layer
611 {
612         Double_t rho;
613         Int_t l, layer, sign;
614         
615         fStateR = fPoint[0]->GetR2();
616         fStatePhi = fPoint[0]->GetPhi();
617         fStateZ = fPoint[0]->Z();
618         
619         if (!PropagateTo(3.0)) {
620                 Error("KalmanFit", "Unsuccessful initialization");
621                 return kFALSE;
622         }
623         l=0;
624
625         // Performs a Kalman filter going from the actual state position
626         // towards layer 6 position
627         // Now, the propagation + filtering operations can be performed
628         Double_t argPhi = 0.0, argZ = 0.0;
629         while (l <= 5) {
630                 if (!fPoint[l]) {
631                         Error("KalmanFit", "Not six points!");
632                         return kFALSE;
633                 }
634                 layer = fPoint[l]->GetLayer();
635                 rho = fPoint[l]->GetR2();
636                 sign = PropagateTo(rho);
637                 if (!sign) return kFALSE;
638                 AddEL(layer, -1.0);
639                 AddMS(layer);
640                 if (!Filter(fPoint[l])) return kFALSE;
641                 // these two parameters are update according to the filtered values
642                 argPhi = ArgPhi(fStateR);
643                 argZ = ArgZ(fStateR);
644                 if (argPhi > 1.0 || argPhi < -1.0 || argZ > 1.0 || argZ < -1.0) {
645                         Error("Filter", Form("Filtering returns too large values: %g, %g", argPhi, argZ));
646                         return kFALSE;
647                 }
648                 fG0 = fStatePhi - asin(argPhi);
649                 fDz = fStateZ - (2.0 * fTanL / fC) * asin(argZ);
650                 l++;
651         }
652
653         // Now a Kalman filter i performed going from the actual state position
654         // towards layer 1 position and then propagates to vertex
655         if (l >= 5) l = 5;
656         while (l >= 1) {
657                 layer = fPoint[l]->GetLayer();
658                 rho = fPoint[l]->GetR2();
659                 AddEL(layer, 1.0);
660                 sign = PropagateTo(rho);
661                 if (!sign) return kFALSE;
662                 AddMS(layer);
663                 if (!Filter(fPoint[l])) return kFALSE;
664                 // these two parameters are update according to the filtered values
665                 argPhi = ArgPhi(fStateR);
666                 argZ = ArgZ(fStateR);
667                 if (argPhi > 1.0 || argPhi < -1.0 || argZ > 1.0 || argZ < -1.0) {
668                         Error("Filter", Form("Filtering returns too large values: %g, %g", argPhi, argZ));
669                         return kFALSE;
670                 }
671                 fG0 = fStatePhi - asin(argPhi);
672                 fDz = fStateZ - (2.0 * fTanL / fC) * asin(argZ);
673                 l--;
674         }
675         return kTRUE;
676 }
677 //
678 //
679 //
680 Bool_t AliITSNeuralTrack::RiemannFit()
681 {
682         // Method which executes the circle fit via a Riemann Sphere projection
683         // with the only improvement of a weighted mean, due to different errors
684         // over different point measurements.
685         // As an output, it returns kTRUE or kFALSE respectively if the fit succeeded or not
686         // in fact, if some variables assume strange values, the fit is aborted,
687         // in order to prevent the class from raising a floating point error;
688
689         Int_t i, j;
690
691         // M1 - matrix of ones
692         TMatrixD m1(6,1);
693         for (i = 0; i < 6; i++) m1(i,0) = 1.0;
694
695         // X - matrix of Rieman projection coordinates
696         TMatrixD X(6,3);
697         for (i = 0; i < 6; i++) {
698                 X(i,0) = fPoint[i]->X();
699                 X(i,1) = fPoint[i]->Y();
700                 X(i,2) = fPoint[i]->GetR2sq();
701         }
702
703         // W - matrix of weights
704         Double_t xterm, yterm, ex, ey;
705         TMatrixD W(6,6);
706         for (i = 0; i < 6; i++) {
707                 xterm = fPoint[i]->X() * fPoint[i]->GetPhi() - fPoint[i]->Y() / fPoint[i]->GetR2();
708                 ex = fPoint[i]->ErrX();
709                 yterm = fPoint[i]->Y() * fPoint[i]->GetPhi() + fPoint[i]->X() / fPoint[i]->GetR2();
710                 ey = fPoint[i]->ErrY();
711                 W(i,i) = fPoint[i]->GetR2sq() / (xterm * xterm * ex * ex + yterm * yterm * ey * ey);
712         }
713
714         // Xm - weighted sample mean
715         Double_t Xm = 0.0, Ym = 0.0, Wm = 0.0, sw = 0.0;
716         for (i = 0; i < 6; i++) {
717                 Xm += W(i,i) * X(i,0);
718                 Ym += W(i,i) * X(i,1);
719                 Wm += W(i,i) * X(i,2);
720                 sw += W(i,i);
721         }
722         Xm /= sw;
723         Ym /= sw;
724         Wm /= sw;
725
726         // V - sample covariance matrix
727         for (i = 0; i < 6; i++) {
728                 X(i,0) -= Xm;
729                 X(i,1) -= Ym;
730                 X(i,2) -= Wm;
731         }
732         TMatrixD Xt(TMatrixD::kTransposed, X);
733         TMatrixD WX(W, TMatrixD::kMult, X);
734         TMatrixD V(Xt, TMatrixD::kMult, WX);
735         for (i = 0; i < 3; i++) {
736                 for (j = i + 1; j < 3; j++) {
737                         V(i,j)  = V(j,i)  = (V(i,j) + V(j,i)) * 0.5;
738                 }
739         }
740
741         // Eigenvalue problem solving for V matrix
742         Int_t ileast = 0;
743         TVectorD Eval(3), n(3);
744         TMatrixD Evec = V.EigenVectors(Eval);
745         if (Eval(1) < Eval(ileast)) ileast = 1;
746         if (Eval(2) < Eval(ileast)) ileast = 2;
747         n(0) = Evec(0, ileast);
748         n(1) = Evec(1, ileast);
749         n(2) = Evec(2, ileast);
750
751         // c - known term in the plane intersection with Riemann axes
752         Double_t c = -(Xm * n(0) + Ym * n(1) + Wm * n(2));
753
754         fXC = -n(0) / (2. * n(2));
755         fYC = -n(1) / (2. * n(2));
756         fR  = (1. - n(2)*n(2) - 4.*c*n(2)) / (4. * n(2) * n(2));
757
758         if (fR <= 0.E0) {
759                 Error("RiemannFit", "Radius comed less than zero!!!");
760                 return kFALSE;
761         }
762         fR = TMath::Sqrt(fR);
763         fC = 1.0 / fR;
764
765         // evaluating signs for curvature and others
766         Double_t phi1 = 0.0, phi2, temp1, temp2, sumdphi = 0.0, ref = TMath::Pi();
767         AliITSNeuralPoint *p = fPoint[0];
768         phi1 = p->GetPhi();
769         for (i = 1; i < 6; i++) {
770                 p = (AliITSNeuralPoint*)fPoint[i];
771                 if (!p) break;
772                 phi2 = p->GetPhi();
773                 temp1 = phi1;
774                 temp2 = phi2;
775                 if (temp1 > ref && temp2 < ref)
776                         temp2 += 2.0 * ref;
777                 else if (temp1 < ref && temp2 > ref)
778                         temp1 += 2.0 * ref;
779                 sumdphi += temp2 - temp1;
780                 phi1 = phi2;
781         }
782         if (sumdphi < 0.E0) fC = -fC;
783         Double_t diff, angle = TMath::ATan2(fYC, fXC);
784         if (fC < 0.E0)
785                 fG0 = angle + 0.5 * TMath::Pi();
786         else
787                 fG0 = angle - 0.5 * TMath::Pi();
788         diff = angle - fG0;
789
790         Double_t D = TMath::Sqrt(fXC*fXC + fYC*fYC) - fR;
791         if (fC >= 0.E0)
792                 fDt = D;
793         else
794                 fDt = -D;
795
796         Int_t N = 6;
797         Double_t halfC = 0.5 * fC;
798         Double_t *s = new Double_t[N], *z = new Double_t[N], *ws = new Double_t[N];
799         for (j = 0; j < 6; j++) {
800                 p = fPoint[j];
801                 if (!p) break;
802                 s[j] = ArgZ(p->GetR2());
803                 if (s[j] > 100.0) return kFALSE;
804                 z[j] = p->Z();
805                 s[j] = asin(s[j]) / halfC;
806                 ws[j] = 1.0 / (p->ErrZ()*p->ErrZ());
807         }
808
809         // second tep final fit
810         Double_t Ss2 = 0.0, Sz = 0.0, Ssz = 0.0, Ss = 0.0, sumw = 0.0;
811         for (i = 0; i < N; i++) {
812                 Ss2 += ws[i] * s[i] * s[i];
813                 Sz  += ws[i] * z[i];
814                 Ss  += ws[i] * s[i];
815                 Ssz += ws[i] * s[i] * z[i];
816                 sumw += ws[i];
817         }
818         Ss2 /= sumw;
819         Sz /= sumw;
820         Ss /= sumw;
821         Ssz /= sumw;
822         D = Ss2 - Ss*Ss;
823
824         fDz = (Ss2*Sz - Ss*Ssz) / D;
825         fTanL = (Ssz - Ss*Sz) / D;
826
827         delete [] s;
828         delete [] z;
829         delete [] ws;
830
831         return kTRUE;
832 }
833 //
834 //
835 //
836 void AliITSNeuralTrack::PrintState(Bool_t matrix)
837 // Prints the state vector values.
838 // The argument switches on or off the printing of the covariance matrix.
839 {
840         cout << "\nState vector: " << endl;
841         cout << " Rho = " << fStateR << "\n";
842         cout << " Phi = " << fStatePhi << "\n";
843         cout << "   Z = " << fStateZ << "\n";
844         cout << "  Dt = " << fDt << "\n";
845         cout << "  Dz = " << fDz << "\n";
846         cout << "TanL = " << fTanL << "\n";
847         cout << "   C = " << fC << "\n";
848         cout << "  G0 = " << fG0 << "\n";
849         cout << "  XC = " << fXC << "\n";
850         cout << "  YC = " << fYC << "\n";
851         if (matrix) {
852                 cout << "\nCovariance Matrix: " << endl;
853                 fMatrix.Print();
854         }
855         cout << "Actual square chi = " << fChi2;
856 }
857 //
858 //
859 //
860 Double_t AliITSNeuralTrack::GetDz()
861 {
862 //      Double_t argZ = ArgZ(fStateR);
863 //      if (argZ > 9.9) {
864 //              Error("GetDz", "Too large value: %g", argZ);
865 //              return 0.0;
866 //      }
867 //      fDz = fStateZ - (2.0 * fTanL / fC) * asin(argZ);
868         return fDz;
869 }
870 //
871 //
872 //
873 Double_t AliITSNeuralTrack::GetGamma()
874 {
875 // these two parameters are update according to the filtered values
876 //      Double_t argPhi = ArgPhi(fStateR);
877 //      if (argPhi > 9.9) {
878 //              Error("Filter", "Too large value: %g", argPhi);
879 //              return kFALSE;
880 //      }
881 //      fG0 = fStatePhi - asin(argPhi);
882         return fG0;
883 }
884 //
885 //
886 //
887 Double_t AliITSNeuralTrack::GetPhi(Double_t r)
888 // Gives the value of azymuthal coordinate in the helix
889 // as a function of cylindric radius
890 {
891         Double_t arg = ArgPhi(r);
892         if (arg > 0.9) return 0.0;
893         arg = fG0 + asin(arg);
894         while (arg >= 2.0 * TMath::Pi()) { arg -= 2.0 * TMath::Pi(); }
895         while (arg < 0.0) { arg += 2.0 * TMath::Pi(); }
896         return arg;
897 }
898 //
899 //
900 //
901 Double_t AliITSNeuralTrack::GetZ(Double_t r)
902 // gives the value of Z in the helix
903 // as a function of cylindric radius
904 {
905         Double_t arg = ArgZ(r);
906         if (arg > 0.9) return 0.0;
907         return fDz + fTanL * asin(arg) / fC;
908 }
909 //
910 //
911 //
912 Double_t AliITSNeuralTrack::GetdEdX()
913 {
914         Double_t q[4] = {0., 0., 0., 0.}, dedx = 0.0;
915         Int_t i = 0, swap = 0;
916         for (i = 2; i < 6; i++) {
917                 if (!fPoint[i]) continue;
918                 q[i - 2] = (Double_t)fPoint[i]->GetCharge();
919                 q[i - 2] /= (1 + fTanL*fTanL);
920         }
921         q[0] /= 280.;
922         q[1] /= 280.;
923         q[2] /= 38.;
924         q[3] /= 38.;
925         do {
926                 swap = 0;
927                 for (i = 0; i < 3; i++) {
928                         if (q[i] <= q[i + 1]) continue;
929                         Double_t tmp = q[i];
930                         q[i] = q[i + 1]; 
931                         q[i+1] = tmp;
932                         swap++;
933                 }
934         } while(swap); 
935         if(q[0] < 0.) {
936                 q[0] = q[1];
937                 q[1] = q[2];
938                 q[2] = q[3];
939                 q[3] = -1.;
940         } 
941         dedx = (q[0] + q[1]) / 2.;
942         return dedx;
943 }
944 //
945 //
946 //
947 void AliITSNeuralTrack::SetVertex(Double_t *pos, Double_t *err)
948 {
949         // Stores vertex data
950
951         if (!pos || !err) return;
952         fVertex.ErrX() = err[0];
953         fVertex.ErrY() = err[1];
954         fVertex.ErrZ() = err[2];
955         fVertex.SetLayer(0);
956         fVertex.SetModule(0);
957         fVertex.SetIndex(0);
958         fVertex.SetLabel(0, -1);
959         fVertex.SetLabel(1, -1);
960         fVertex.SetLabel(2, -1);
961         fVertex.SetUser(1);
962 }
963 //
964 //
965 //
966 AliITSIOTrack* AliITSNeuralTrack::ExportIOtrack(Int_t min)
967 // Exports an object in the standard format for reconstructed tracks
968 {
969         Int_t layer = 0;
970         AliITSIOTrack *track = new AliITSIOTrack;
971
972         // covariance matrix
973         track->SetCovMatrix(fMatrix(0,0), fMatrix(1,0), fMatrix(1,1),
974                             fMatrix(2,0), fMatrix(2,1), fMatrix(2,2),
975                             fMatrix(3,0), fMatrix(3,1), fMatrix(3,2),
976                             fMatrix(3,3), fMatrix(4,0), fMatrix(4,1),
977                             fMatrix(4,2), fMatrix(4,3), fMatrix(4,4));
978         
979         // labels
980         track->SetLabel(IsGood(min) ? fLabel : -fLabel);
981         track->SetTPCLabel(-1);
982
983         // points characteristics
984         for (layer = 0; layer < 6; layer++) {
985                 if (fPoint[layer]) {
986                         track->SetIdModule(layer, fPoint[layer]->GetModule());
987                         track->SetIdPoint(layer, fPoint[layer]->GetIndex());
988                 }
989         }
990         
991         // state vector
992         track->SetStatePhi(fStatePhi);
993         track->SetStateZ(fStateZ);
994         track->SetStateD(fDt);
995         track->SetStateTgl(fTanL);
996         track->SetStateC(fC);
997         track->SetRadius(fStateR);
998         track->SetCharge((fC > 0.0) ? -1 : 1);
999         track->SetDz(fDz);
1000
1001         // track parameters in the closest point
1002         track->SetX(fStateR * cos(fStatePhi));
1003         track->SetY(fStateR * cos(fStatePhi));
1004         track->SetZ(fStateZ);
1005         track->SetPx(GetPt() * cos(fG0));
1006         track->SetPy(GetPt() * sin(fG0));
1007         track->SetPz(GetPt() * fTanL);
1008
1009         // PID
1010         track->SetPid(fPDG);
1011         track->SetMass(fMass);
1012
1013         return track;
1014 }
1015 //
1016 //
1017 //====================================================================================
1018 //============================       PRIVATE METHODS      ============================
1019 //====================================================================================
1020 //
1021 //
1022 Double_t AliITSNeuralTrack::ArgPhi(Double_t r) const
1023 {
1024         // calculates the expression ((1/2)Cr + (1 + (1/2)CD) D/r) / (1 + CD)
1025
1026         Double_t arg, num, den;
1027         num = (0.5 * fC * r) + (1. + (0.5 * fC * fDt)) * (fDt / r);
1028         den = 1. + fC * fDt;
1029         if (den == 0.) {
1030                 Error("ArgPhi", "Denominator = 0!");
1031                 return 10.0;
1032         }
1033         arg = num / den;
1034         if (TMath::Abs(arg) < 1.) return arg;
1035         if (TMath::Abs(arg) <= 1.00001) return (arg > 0.) ? 0.99999999999 : -0.9999999999;
1036         Error("ArgPhi", "Value too large: %17.15g", arg);
1037         return 10.0;
1038 }
1039 //
1040 //
1041 //
1042 Double_t AliITSNeuralTrack::ArgZ(Double_t r) const
1043 {
1044         // calculates the expression (1/2)C * sqrt( (r^2 - Dt^2) / (1 + CD) )
1045
1046         Double_t arg;
1047         arg = (r * r - fDt * fDt) / (1. + fC * fDt);
1048         if (arg < 0.) {
1049                 if (fabs(arg) < 1.E-6) arg = 0.;
1050                 else {
1051                         Error("ArgZ", "Square root argument error: %17.15g < 0", arg);
1052                         return 10.;
1053                 }
1054         }
1055         arg = 0.5 * fC * TMath::Sqrt(arg);
1056         if (TMath::Abs(arg) < 1.) return arg;
1057         if (TMath::Abs(arg) <= 1.00001) return (arg > 0.) ? 0.99999999999 : -0.9999999999;
1058         Error("ArgZ", "Value too large: %17.15g", arg);
1059         return 10.0;
1060 }
1061 //
1062 //
1063 //
1064 Double_t AliITSNeuralTrack::ArgB(Double_t r) const 
1065 {
1066         Double_t arg;
1067         arg = (r*r - fDt*fDt);
1068         arg /= (r*(1.+ fC*fDt)*(1.+ fC*fDt));
1069         return arg;
1070 }
1071 //
1072 //
1073 //
1074 Double_t AliITSNeuralTrack::ArgC(Double_t r) const 
1075 {
1076         Double_t arg;
1077         arg = (1./r - fC * ArgPhi(r));
1078         arg /= 1.+ fC*fDt;
1079         return arg;
1080 }