]> git.uio.no Git - u/mrichter/AliRoot.git/blob - MUON/AliMUONTrackK.cxx
Small bug fixed for some class of tracks (Sacha)
[u/mrichter/AliRoot.git] / MUON / AliMUONTrackK.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 #include <stdlib.h> // for exit()
19 #include <Riostream.h>
20 #include <TClonesArray.h>
21 #include <TArrayD.h>
22 #include <TMatrixD.h>
23
24 #include "AliMUONTrackK.h"
25 #include "AliCallf77.h"
26 #include "AliMUON.h"
27 #include "AliMUONChamber.h"
28 #include "AliMUONTrackReconstructor.h"
29 #include "AliMagF.h"
30 #include "AliMUONSegment.h"
31 #include "AliMUONHitForRec.h"
32 #include "AliMUONRawCluster.h"
33 #include "AliMUONTrackParam.h"
34 #include "AliRun.h"
35 #include "AliLog.h"
36
37 const Int_t AliMUONTrackK::fgkSize = 5;
38 const Int_t AliMUONTrackK::fgkNSigma = 12; 
39 const Double_t AliMUONTrackK::fgkChi2max = 100; 
40 const Int_t AliMUONTrackK::fgkTriesMax = 10000; 
41 const Double_t AliMUONTrackK::fgkEpsilon = 0.002; 
42
43 void mnvertLocal(Double_t* a, Int_t l, Int_t m, Int_t n, Int_t& ifail); // from AliMUONTrack
44 //void mnvertLocalK(Double_t* a, Int_t l, Int_t m, Int_t n, Int_t& ifail);
45
46 ClassImp(AliMUONTrackK) // Class implementation in ROOT context
47
48 Int_t AliMUONTrackK::fgDebug = -1;
49 Int_t AliMUONTrackK::fgNOfPoints = 0; 
50 AliMUON* AliMUONTrackK::fgMUON = NULL;
51 AliMUONTrackReconstructor* AliMUONTrackK::fgTrackReconstructor = NULL; 
52 TClonesArray* AliMUONTrackK::fgHitForRec = NULL; 
53 //FILE *lun1 = fopen("window.dat","w");
54
55   //__________________________________________________________________________
56 AliMUONTrackK::AliMUONTrackK()
57   //AZ: TObject()
58   : AliMUONTrack() 
59 {
60   // Default constructor
61
62   fgTrackReconstructor = NULL; // pointer to event reconstructor
63   fgMUON = NULL; // pointer to Muon module
64   fgHitForRec = NULL; // pointer to points
65   fgNOfPoints = 0; // number of points
66
67   fStartSegment = NULL;
68   fTrackHitsPtr = NULL;
69   fNTrackHits = 0;
70   fTrackPar = fTrackParNew = NULL;
71   fCovariance = fWeight = NULL;
72   fSkipHit = NULL;
73   fParExtrap = fParFilter = fParSmooth = NULL;
74   fCovExtrap = fCovFilter = NULL;
75   fJacob = NULL; 
76   fSteps = NULL; fNSteps = 0; 
77   fChi2Array = NULL;
78   fChi2Smooth = NULL;
79
80   return;
81 }
82
83   //__________________________________________________________________________
84 AliMUONTrackK::AliMUONTrackK(AliMUONTrackReconstructor *TrackReconstructor, TClonesArray *hitForRec)
85   //AZ: TObject()
86   : AliMUONTrack()
87 {
88   // Constructor
89
90   if (!TrackReconstructor) return;
91   fgTrackReconstructor = TrackReconstructor; // pointer to event reconstructor
92   fgMUON = (AliMUON*) gAlice->GetModule("MUON"); // pointer to Muon module
93   fgHitForRec = hitForRec; // pointer to points
94   fgNOfPoints = fgHitForRec->GetEntriesFast(); // number of points
95
96   fStartSegment = NULL;
97   fTrackHitsPtr = NULL;
98   fNTrackHits = 0;
99   fChi2 = 0;
100   fTrackPar = fTrackParNew = NULL;
101   fCovariance = fWeight = NULL;
102   fSkipHit = NULL;
103   fParExtrap = fParFilter = fParSmooth = NULL;
104   fCovExtrap = fCovFilter = NULL;
105   fJacob = NULL; 
106   fSteps = NULL; fNSteps = 0; 
107   fChi2Array = NULL;
108   fChi2Smooth = NULL;
109 }
110
111   //__________________________________________________________________________
112 AliMUONTrackK::AliMUONTrackK(AliMUONSegment *segment)
113   //AZ: TObject()
114   : AliMUONTrack(segment, segment, fgTrackReconstructor)
115 {
116   // Constructor from a segment
117   Double_t dX, dY, dZ;
118   AliMUONHitForRec *hit1, *hit2;
119   AliMUONRawCluster *clus;
120   TClonesArray *rawclusters;
121
122   fStartSegment = segment;
123   fRecover = 0;
124   fSkipHit = NULL;
125   // Pointers to hits from the segment
126   hit1 = segment->GetHitForRec1();
127   hit2 = segment->GetHitForRec2();
128   hit1->SetNTrackHits(hit1->GetNTrackHits()+1); // mark hit as being on track
129   hit2->SetNTrackHits(hit2->GetNTrackHits()+1); // mark hit as being on track
130   // check sorting in Z
131   if (TMath::Abs(hit1->GetZ()) > TMath::Abs(hit2->GetZ())) {
132     hit1 = hit2;
133     hit2 = segment->GetHitForRec1();
134   }
135   // memory allocation for the TObjArray of pointers to reconstructed TrackHit's
136   fTrackHitsPtr = new TObjArray(13);
137   fNTrackHits = 2;
138   fChi2 = 0;
139   fBPFlag = kFALSE;
140   fTrackPar = new TMatrixD(fgkSize,1); // track parameters
141   fTrackParNew = new TMatrixD(fgkSize,1); // track parameters
142   fCovariance = new TMatrixD(fgkSize,fgkSize); // covariance matrix
143   fWeight = new TMatrixD(fgkSize,fgkSize); // weight matrix (inverse of covariance)
144
145   // Fill array of track parameters
146   if (hit1->GetChamberNumber() > 7) {
147     // last tracking station
148     (*fTrackPar)(0,0) = hit1->GetBendingCoor(); // y
149     (*fTrackPar)(1,0) = hit1->GetNonBendingCoor(); // x
150     fPosition = hit1->GetZ(); // z
151     fTrackHitsPtr->Add(hit2); // add hit 2
152     fTrackHitsPtr->Add(hit1); // add hit 1
153     //AZ(Z->-Z) fTrackDir = -1;
154     fTrackDir = 1;
155   } else {
156     // last but one tracking station
157     (*fTrackPar)(0,0) = hit2->GetBendingCoor(); // y
158     (*fTrackPar)(1,0) = hit2->GetNonBendingCoor(); // x
159     fPosition = hit2->GetZ(); // z
160     fTrackHitsPtr->Add(hit1); // add hit 1
161     fTrackHitsPtr->Add(hit2); // add hit 2
162     //AZ(Z->-Z) fTrackDir = 1;
163     fTrackDir = -1;
164   }
165   dZ = hit2->GetZ() - hit1->GetZ();
166   dY = hit2->GetBendingCoor() - hit1->GetBendingCoor();
167   dX = hit2->GetNonBendingCoor() - hit1->GetNonBendingCoor();
168   (*fTrackPar)(2,0) = TMath::ATan2(dY,dZ); // alpha
169   if ((*fTrackPar)(2,0) < 0.) (*fTrackPar)(2,0) += 2*TMath::Pi(); // from 0 to 2*pi
170   (*fTrackPar)(3,0) = TMath::ATan2(-dX,dZ/TMath::Cos((*fTrackPar)(2,0))); // beta
171   (*fTrackPar)(2,0) -= TMath::Pi();
172   (*fTrackPar)(4,0) = 1/fgTrackReconstructor->GetBendingMomentumFromImpactParam(segment->GetBendingImpact()); // 1/Pt
173   (*fTrackPar)(4,0) *= TMath::Cos((*fTrackPar)(3,0)); // 1/p
174   // Evaluate covariance (and weight) matrix
175   EvalCovariance(dZ);
176
177   // For smoother
178   fParExtrap = new TObjArray(15);
179   fParFilter = new TObjArray(15);
180   fCovExtrap = new TObjArray(15);
181   fCovFilter = new TObjArray(15);
182   fJacob = new TObjArray(15);
183   fSteps = new TArrayD(15);
184   fNSteps = 0;
185   fChi2Array = new TArrayD(13);
186   fChi2Smooth = NULL;
187   fParSmooth = NULL;
188
189   if (fgDebug < 0 ) return;
190   cout << fgTrackReconstructor->GetBendingMomentumFromImpactParam(segment->GetBendingImpact()) << " " << 1/(*fTrackPar)(4,0) << " ";
191   if (fgTrackReconstructor->GetRecTrackRefHits()) { 
192     // from track ref. hits
193     cout << ((AliMUONHitForRec*)((*fTrackHitsPtr)[0]))->GetTTRTrack() << "<-->" << ((AliMUONHitForRec*)((*fTrackHitsPtr)[1]))->GetTTRTrack() << " @ " << fStartSegment->GetHitForRec1()->GetChamberNumber() << endl;
194   } else {
195     // from raw clusters
196     for (Int_t i=0; i<2; i++) {
197       hit1 = (AliMUONHitForRec*) ((*fTrackHitsPtr)[i]);
198       rawclusters = fgTrackReconstructor->GetMUONData()->RawClusters(hit1->GetChamberNumber());
199       clus = (AliMUONRawCluster*) rawclusters->UncheckedAt(hit1->GetHitNumber());
200       cout << clus->GetTrack(1);
201       if (clus->GetTrack(2) != -1) cout << " " << clus->GetTrack(2);
202       if (i == 0) cout << " <--> ";
203     }
204     cout << " @ " << fStartSegment->GetHitForRec1()->GetChamberNumber() << endl;
205   }
206 }
207
208   //__________________________________________________________________________
209 AliMUONTrackK::~AliMUONTrackK()
210 {
211   // Destructor
212
213   if (fTrackHitsPtr) {
214     delete fTrackHitsPtr; // delete the TObjArray of pointers to TrackHit's
215     fTrackHitsPtr = NULL;
216   }
217   if (fTrackPar) {
218     delete fTrackPar; delete fTrackParNew; delete fCovariance;
219     delete fWeight;
220   } 
221
222   if (fSteps) delete fSteps; 
223   if (fChi2Array) delete fChi2Array;
224   if (fChi2Smooth) delete fChi2Smooth;
225   if (fParSmooth) {fParSmooth->Delete(); delete fParSmooth; }
226   // Delete only matrices not shared by several tracks
227   if (!fParExtrap) return;
228
229   Int_t id = 0;
230   for (Int_t i=0; i<fNSteps; i++) {
231     //if (fParExtrap->UncheckedAt(i)->GetUniqueID() > 1) 
232     //  fParExtrap->UncheckedAt(i)->SetUniqueID(fParExtrap->RemoveAt(i)->GetUniqueID()-1);
233     id = fParExtrap->UncheckedAt(i)->GetUniqueID();
234     if (id > 1) { 
235       fParExtrap->UncheckedAt(i)->SetUniqueID(id-1);
236       fParExtrap->RemoveAt(i);
237     }
238     //if (fParFilter->UncheckedAt(i)->GetUniqueID() > 1) 
239     //  fParFilter->UncheckedAt(i)->SetUniqueID(fParFilter->RemoveAt(i)->GetUniqueID()-1);
240     id = fParFilter->UncheckedAt(i)->GetUniqueID();
241     if (id > 1) { 
242       fParFilter->UncheckedAt(i)->SetUniqueID(id-1);
243       fParFilter->RemoveAt(i);
244     }
245     //if (fCovExtrap->UncheckedAt(i)->GetUniqueID() > 1) 
246     //  fCovExtrap->UncheckedAt(i)->SetUniqueID(fCovExtrap->RemoveAt(i)->GetUniqueID()-1);
247     id = fCovExtrap->UncheckedAt(i)->GetUniqueID();
248     if (id > 1) { 
249       fCovExtrap->UncheckedAt(i)->SetUniqueID(id-1);
250       fCovExtrap->RemoveAt(i);
251     }
252
253     //if (fCovFilter->UncheckedAt(i)->GetUniqueID() > 1) 
254     //  fCovFilter->UncheckedAt(i)->SetUniqueID(fCovFilter->RemoveAt(i)->GetUniqueID()-1);
255     id = fCovFilter->UncheckedAt(i)->GetUniqueID();
256     if (id > 1) { 
257       fCovFilter->UncheckedAt(i)->SetUniqueID(id-1);
258       fCovFilter->RemoveAt(i);
259     }
260     //if (fJacob->UncheckedAt(i)->GetUniqueID() > 1) 
261     //  fJacob->UncheckedAt(i)->SetUniqueID(fJacob->RemoveAt(i)->GetUniqueID()-1);
262     id = fJacob->UncheckedAt(i)->GetUniqueID();
263     if (id > 1) { 
264       fJacob->UncheckedAt(i)->SetUniqueID(id-1);
265       fJacob->RemoveAt(i);
266     }
267   }
268   /*
269   for (Int_t i=0; i<fNSteps; i++) {
270     if (fParExtrap->UncheckedAt(i)) ((TMatrixD*)fParExtrap->UncheckedAt(i))->Delete();
271     if (fParFilter->UncheckedAt(i)) ((TMatrixD*)fParFilter->UncheckedAt(i))->Delete();
272     if (fCovExtrap->UncheckedAt(i)) ((TMatrixD*)fCovExtrap->UncheckedAt(i))->Delete();
273     cout << fCovFilter->UncheckedAt(i) << " " << (*fSteps)[i] << endl;
274     if (fCovFilter->UncheckedAt(i)) ((TMatrixD*)fCovFilter->UncheckedAt(i))->Delete();
275     if (fJacob->UncheckedAt(i)) ((TMatrixD*)fJacob->UncheckedAt(i))->Delete();
276   }
277   */
278   fParExtrap->Delete(); fParFilter->Delete();
279   fCovExtrap->Delete(); fCovFilter->Delete();
280   fJacob->Delete();
281   delete fParExtrap; delete fParFilter;
282   delete fCovExtrap; delete fCovFilter;
283   delete fJacob;
284 }
285
286   //__________________________________________________________________________
287 AliMUONTrackK::AliMUONTrackK (const AliMUONTrackK& source)
288   //AZ: TObject(source)
289   : AliMUONTrack(source)
290 {
291 // Protected copy constructor
292   AliFatal("Not implemented.");
293 }
294
295   //__________________________________________________________________________
296 AliMUONTrackK & AliMUONTrackK::operator=(const AliMUONTrackK& source)
297 {
298   // Assignment operator
299   // Members
300   if(&source == this) return *this;
301
302   // base class assignement
303   //AZ TObject::operator=(source);
304   AliMUONTrack::operator=(source);
305
306   fStartSegment = source.fStartSegment;
307   fNTrackHits = source.fNTrackHits;
308   fChi2 = source.fChi2;
309   fPosition = source.fPosition;
310   fPositionNew = source.fPositionNew;
311   fTrackDir = source.fTrackDir;
312   fBPFlag = source.fBPFlag;
313   fRecover = source.fRecover;
314   fSkipHit = source.fSkipHit;
315
316   // Pointers
317   fTrackHitsPtr = new TObjArray(*source.fTrackHitsPtr);
318   //source.fTrackHitsPtr->Dump();
319   //fTrackHitsPtr->Dump();
320   
321   fTrackPar = new TMatrixD(*source.fTrackPar); // track parameters
322   fTrackParNew = new TMatrixD(*source.fTrackParNew); // track parameters
323   fCovariance = new TMatrixD(*source.fCovariance); // covariance matrix
324   fWeight = new TMatrixD(*source.fWeight); // weight matrix (inverse of covariance)
325
326   // For smoother
327   fParExtrap = new TObjArray(*source.fParExtrap);
328   fParFilter = new TObjArray(*source.fParFilter);
329   fCovExtrap = new TObjArray(*source.fCovExtrap);
330   fCovFilter = new TObjArray(*source.fCovFilter);
331   fJacob = new TObjArray(*source.fJacob);
332   fSteps = new TArrayD(*source.fSteps);
333   fNSteps = source.fNSteps;
334   fChi2Array = NULL;
335   if (source.fChi2Array) fChi2Array = new TArrayD(*source.fChi2Array);
336   fChi2Smooth = NULL;
337   fParSmooth = NULL;
338
339   for (Int_t i=0; i<fParExtrap->GetEntriesFast(); i++) {
340     fParExtrap->UncheckedAt(i)->SetUniqueID(fParExtrap->UncheckedAt(i)->GetUniqueID()+1);
341     fParFilter->UncheckedAt(i)->SetUniqueID(fParFilter->UncheckedAt(i)->GetUniqueID()+1);
342     fCovExtrap->UncheckedAt(i)->SetUniqueID(fCovExtrap->UncheckedAt(i)->GetUniqueID()+1);
343     fCovFilter->UncheckedAt(i)->SetUniqueID(fCovFilter->UncheckedAt(i)->GetUniqueID()+1);
344     fJacob->UncheckedAt(i)->SetUniqueID(fJacob->UncheckedAt(i)->GetUniqueID()+1);
345   }
346   return *this;
347 }
348
349   //__________________________________________________________________________
350 void AliMUONTrackK::EvalCovariance(Double_t dZ)
351 {
352   // Evaluate covariance (and weight) matrix for track candidate
353   Double_t sigmaB, sigmaNonB, tanA, tanB, dAdY, rad, dBdX, dBdY;
354
355   dZ = -dZ;
356   sigmaB = fgTrackReconstructor->GetBendingResolution(); // bending resolution
357   sigmaNonB = fgTrackReconstructor->GetNonBendingResolution(); // non-bending resolution
358
359   (*fWeight)(0,0) = sigmaB*sigmaB; // <yy>
360
361   (*fWeight)(1,1) = sigmaNonB*sigmaNonB; // <xx>
362
363   tanA = TMath::Tan((*fTrackPar)(2,0));
364   dAdY = 1/(1+tanA*tanA)/dZ;
365   (*fWeight)(2,2) = dAdY*dAdY*(*fWeight)(0,0)*2; // <aa>
366   (*fWeight)(0,2) = dAdY*(*fWeight)(0,0); // <ya>
367   (*fWeight)(2,0) = (*fWeight)(0,2);
368
369   rad = dZ/TMath::Cos((*fTrackPar)(2,0));
370   tanB = TMath::Tan((*fTrackPar)(3,0));
371   dBdX = 1/(1+tanB*tanB)/rad;
372   dBdY = 0; // neglect
373   (*fWeight)(3,3) = dBdX*dBdX*(*fWeight)(1,1)*2; // <bb>
374   (*fWeight)(1,3) = dBdX*(*fWeight)(1,1); // <xb>
375   (*fWeight)(3,1) = (*fWeight)(1,3);
376
377   //(*fWeight)(4,4) = ((*fTrackPar)(4,0)*0.2)*((*fTrackPar)(4,0)*0.2); // error 20%
378   (*fWeight)(4,4) = ((*fTrackPar)(4,0)*0.5)*((*fTrackPar)(4,0)*0.5); // error 50%
379
380   // check whether the Invert method returns flag if matrix cannot be inverted,
381   // and do not calculate the Determinant in that case !!!!
382   if (fWeight->Determinant() != 0) {
383     // fWeight->Invert();
384     Int_t ifail;
385     //mnvertLocalK(&((*fWeight)(0,0)), fgkSize,fgkSize,fgkSize,ifailWeight);
386     mnvertLocal(&((*fWeight)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
387   } else {
388     AliWarning(" Determinant fWeight=0:");
389   }
390   return;
391 }
392
393   //__________________________________________________________________________
394 Bool_t AliMUONTrackK::KalmanFilter(Int_t ichamBeg, Int_t ichamEnd, Bool_t Back, Double_t zDipole1, Double_t zDipole2)
395 {
396   // Follows track through detector stations 
397   Bool_t miss, success;
398   Int_t ichamb, iFB, iMin, iMax, dChamb, ichambOK;
399   Int_t ihit, firstIndx, lastIndx, currIndx;
400   Double_t zEnd, dChi2;
401   AliMUONHitForRec *hitAdd, *firstHit, *lastHit, *hit;
402   AliMUONRawCluster *clus;
403   TClonesArray *rawclusters;
404   hit = 0; clus = 0; rawclusters = 0;
405
406   miss = success = kTRUE;
407   Int_t endOfProp = 0;
408   //iFB = (ichamEnd == ichamBeg) ? fTrackDir : TMath::Sign(1,ichamEnd-ichamBeg);
409   iFB = (ichamEnd == ichamBeg) ? -fTrackDir : TMath::Sign(1,ichamEnd-ichamBeg);
410   iMin = TMath::Min(ichamEnd,ichamBeg);
411   iMax = TMath::Max(ichamEnd,ichamBeg);
412   ichamb = ichamBeg;
413   ichambOK = ichamb;
414
415   if (Back) {
416     // backpropagation
417     currIndx = 1; 
418     if (((AliMUONHitForRec*)fTrackHitsPtr->First())->GetChamberNumber() != ichamb) currIndx = 0;
419   } else if (fRecover) {
420     hit = GetHitLastOk();
421     currIndx = fTrackHitsPtr->IndexOf(hit);
422     if (currIndx < 0) hit = fStartSegment->GetHitForRec1(); // for station 3
423     Back = kTRUE;
424     ichamb = hit->GetChamberNumber();
425     if (hit == fSkipHit || fRecover == 2 && currIndx >= 0) {
426       // start from the last point or outlier
427       // remove the skipped hit
428       fTrackHitsPtr->Remove(fSkipHit); // remove hit
429       fNTrackHits --;
430       fSkipHit->SetNTrackHits(fSkipHit->GetNTrackHits()-1); // unmark hit 
431       if (fRecover == 1) {
432         // recovery
433         Back = kFALSE;
434         fRecover = 0; 
435         ichambOK = ((AliMUONHitForRec*)((*fTrackHitsPtr)[fNTrackHits-1]))->GetChamberNumber();
436         //if (ichambOK >= 8 && ((AliMUONHitForRec*)((*fTrackHitsPtr)[0]))->GetChamberNumber() == 6) ichambOK = 6;
437         currIndx = fgHitForRec->IndexOf(fSkipHit);
438       } else {
439         // outlier
440         fTrackHitsPtr->Compress();
441       }
442     } // if (hit == fSkipHit)
443     else if (currIndx < 0) currIndx = fTrackHitsPtr->IndexOf(hit);
444   } // else if (fRecover) 
445   else {
446     // Get indices of the 1'st and last hits on the track candidate
447     firstHit = (AliMUONHitForRec*) fTrackHitsPtr->First();
448     lastHit = (AliMUONHitForRec*) fTrackHitsPtr->Last();
449     firstIndx = fgHitForRec->IndexOf(firstHit);
450     lastIndx = fgHitForRec->IndexOf(lastHit);
451     currIndx = TMath::Abs (TMath::Max(firstIndx*iFB,lastIndx*iFB));
452   }
453
454   while (ichamb>=iMin && ichamb<=iMax) {
455   // Find the closest hit in Z, not belonging to the current plane
456     if (Back) {
457       // backpropagation
458       if (currIndx < fNTrackHits) {
459         hitAdd = (AliMUONHitForRec*) fTrackHitsPtr->UncheckedAt(currIndx);
460         zEnd = hitAdd->GetZ();
461         //AZ(z->-z) } else zEnd = -9999;
462       } else zEnd = 9999;
463     } else {
464       //AZ(Z->-Z) zEnd = -9999;
465       zEnd = 9999;
466       for (ihit=currIndx+iFB; ihit>=0 && ihit<fgNOfPoints; ihit+=iFB) {
467         hitAdd = (AliMUONHitForRec*) ((*fgHitForRec)[ihit]);
468         //if (TMath::Abs(hitAdd->GetZ()-fPosition) > 0.1) {
469         if (TMath::Abs(hitAdd->GetZ()-fPosition) > 0.5) {
470           zEnd = hitAdd->GetZ();
471           currIndx = ihit;
472           break;
473         }
474       }
475     }
476     //AZ(Z->-Z) if (zEnd<-999 && ichamb==ichamEnd) endOfProp = 1; // end-of-propagation
477     if (zEnd>999 && ichamb==ichamEnd) endOfProp = 1; // end-of-propagation
478     else {
479       // Check if there is a chamber without hits
480       if (zEnd>999 || TMath::Abs(hitAdd->GetChamberNumber()-ichamb) > 1) {
481         if (!Back && zEnd<999) currIndx -= iFB;
482         ichamb += iFB;
483         zEnd = (&(fgMUON->Chamber(ichamb)))->Z();
484         miss = kTRUE;
485       } else {
486         ichamb = hitAdd->GetChamberNumber();
487         miss = kFALSE;
488       }
489     }
490     if (ichamb<iMin || ichamb>iMax) break;
491     // Check for missing station 
492     if (!Back) {
493       dChamb = TMath::Abs(ichamb-ichambOK); 
494       //cout << dChamb << " " << ichambOK << " " << fgNOfPoints << endl;
495       Int_t dStatMiss = TMath::Abs (ichamb/2 - ichambOK/2);
496       if (zEnd > 999) dStatMiss++;
497       if (dStatMiss > 1) {
498         // missing station - abandon track
499         //cout << dChamb << " " << ichambOK << " " << fgNOfPoints << " " << 1/(*fTrackPar)(4,0) << endl;
500         if (fgDebug >= 10) {
501           for (Int_t i1=0; i1<fgNOfPoints; i1++) {
502             cout << " Hit #" << ((AliMUONHitForRec*)((*fgHitForRec)[i1]))->GetChamberNumber() << " ";
503             cout << ((AliMUONHitForRec*)((*fgHitForRec)[i1]))->GetBendingCoor() << " ";
504             cout << ((AliMUONHitForRec*)((*fgHitForRec)[i1]))->GetNonBendingCoor() << " ";
505             cout << ((AliMUONHitForRec*)((*fgHitForRec)[i1]))->GetZ() << " " << " ";
506             cout << ((AliMUONHitForRec*)((*fgHitForRec)[i1]))->GetTTRTrack() << endl;
507           }
508           cout << endl;
509           cout << fNTrackHits << endl;
510           for (Int_t i1=0; i1<fNTrackHits; i1++) {
511             hit = (AliMUONHitForRec*) ((*fTrackHitsPtr)[i1]);
512             printf(" * %d %10.4f %10.4f %10.4f", 
513                    hit->GetChamberNumber(), hit->GetBendingCoor(), 
514                    hit->GetNonBendingCoor(), hit->GetZ());
515             if (fgTrackReconstructor->GetRecTrackRefHits()) { 
516               // from track ref. hits
517               printf(" %3d %3d \n", hit->GetTrackRefSignal(), hit->GetTTRTrack());
518             } else {
519               // from raw clusters
520               rawclusters = fgTrackReconstructor->GetMUONData()->RawClusters(hit->GetChamberNumber());
521               clus = (AliMUONRawCluster*) rawclusters->UncheckedAt(hit->GetHitNumber());
522               printf("%3d", clus->GetTrack(1)-1); 
523               if (clus->GetTrack(2) != 0) printf("%3d \n", clus->GetTrack(2)-1);
524               else printf("\n");
525             }
526           }
527         } // if (fgDebug >= 10) 
528         if (fNTrackHits>2 && fRecover==0) Recover(); // try to recover track later
529         return kFALSE;
530       } // if (dStatMiss > 1)
531     } // if (!Back)
532     if (endOfProp != 0) break;
533
534     // propagate to the found Z
535
536     // Check if track steps into dipole
537     //AZ(z->-z) if (fPosition>zDipole2 && zEnd<zDipole2) {
538     if (fPosition<zDipole2 && zEnd>zDipole2) {
539       //LinearPropagation(zDipole2-zBeg); 
540       ParPropagation(zDipole2); 
541       MSThin(1); // multiple scattering in the chamber
542       WeightPropagation(zDipole2, kTRUE); // propagate weight matrix
543       fPosition = fPositionNew;
544       *fTrackPar = *fTrackParNew; 
545       //MagnetPropagation(zEnd); 
546       ParPropagation(zEnd); 
547       WeightPropagation(zEnd, kTRUE);
548       fPosition = fPositionNew;
549     } 
550     // Check if track steps out of dipole
551     //AZ(z->-z) else if (fPosition>zDipole1 && zEnd<zDipole1) {
552     else if (fPosition<zDipole1 && zEnd>zDipole1) {
553       //MagnetPropagation(zDipole1-zBeg); 
554       ParPropagation(zDipole1); 
555       MSThin(1); // multiple scattering in the chamber
556       WeightPropagation(zDipole1, kTRUE);
557       fPosition = fPositionNew;
558       *fTrackPar = *fTrackParNew; 
559       //LinearPropagation(zEnd-zDipole1); 
560       ParPropagation(zEnd); 
561       WeightPropagation(zEnd, kTRUE);
562       fPosition = fPositionNew;
563     } else {
564       ParPropagation(zEnd);
565       //MSThin(1); // multiple scattering in the chamber
566       if (TMath::Abs(zEnd-fPosition) > 5) MSThin(1); // multiple scattering in the chamber
567       WeightPropagation(zEnd, kTRUE);
568       fPosition = fPositionNew;
569     }
570
571     // Add measurement
572     if (fRecover != 0 && hitAdd == fSkipHit && !miss) {
573       // recovered track - remove the hit
574       miss = kTRUE;
575       ichamb = fSkipHit->GetChamberNumber();
576       // remove the skipped hit
577       fTrackHitsPtr->Remove(fSkipHit); 
578       fNTrackHits --;
579       fSkipHit->SetNTrackHits(fSkipHit->GetNTrackHits()-1); // unmark hit 
580       Back = kFALSE;
581       fRecover =0;
582       ichambOK = ((AliMUONHitForRec*)((*fTrackHitsPtr)[fNTrackHits-1]))->GetChamberNumber();
583       currIndx = fgHitForRec->IndexOf(fSkipHit);
584     }
585
586     if (Back && !miss) {
587       // backward propagator
588       if (currIndx) {
589         TMatrixD pointWeight(fgkSize,fgkSize);
590         TMatrixD point(fgkSize,1);
591         TMatrixD trackParTmp = point;
592         point(0,0) = hitAdd->GetBendingCoor();
593         point(1,0) = hitAdd->GetNonBendingCoor();
594         pointWeight(0,0) = 1/hitAdd->GetBendingReso2();
595         pointWeight(1,1) = 1/hitAdd->GetNonBendingReso2();
596         TryPoint(point,pointWeight,trackParTmp,dChi2);
597         *fTrackPar = trackParTmp;
598         *fWeight += pointWeight; 
599         //AZ(z->-z) if (fTrackDir < 0) AddMatrices (this, dChi2, hitAdd);
600         if (fTrackDir > 0) AddMatrices (this, dChi2, hitAdd);
601         fChi2 += dChi2; // Chi2
602       } else *fTrackPar = *fTrackParNew; // adjust end point to the last hit
603       if (ichamb==ichamEnd) break; 
604       currIndx ++;
605     } else {
606       // forward propagator
607       if (miss || !FindPoint(ichamb,zEnd,currIndx,iFB,hitAdd)) {
608         // missing point
609         *fTrackPar = *fTrackParNew; 
610       } else {
611         //add point
612         fTrackHitsPtr->Add(hitAdd); // add hit
613         fNTrackHits ++;
614         hitAdd->SetNTrackHits(hitAdd->GetNTrackHits()+1); // mark hit as being on track
615         ichambOK = ichamb;
616         currIndx = fgHitForRec->IndexOf(hitAdd); // Check
617       }
618     }
619   } // while
620   if (fgDebug > 0) cout << fNTrackHits << " " << fChi2 << " " << 1/(*fTrackPar)(4,0) << " " << fPosition << endl;
621   if (1/TMath::Abs((*fTrackPar)(4,0)) < fgTrackReconstructor->GetMinBendingMomentum()) success = kFALSE; // p < p_min
622   return success;
623 }
624
625   //__________________________________________________________________________
626 void AliMUONTrackK::ParPropagation(Double_t zEnd)
627 {
628   // Propagation of track parameters to zEnd
629   Int_t iFB, nTries;
630   Double_t dZ, step, distance, charge;
631   Double_t vGeant3[7], vGeant3New[7];
632   AliMUONTrackParam trackParam;
633
634   nTries = 0;
635   // First step using linear extrapolation
636   dZ = zEnd - fPosition;
637   fPositionNew = fPosition;
638   *fTrackParNew = *fTrackPar;
639   if (dZ == 0) return; //AZ ???
640   iFB = (Int_t)TMath::Sign(Double_t(1.0),dZ);
641   step = dZ/TMath::Cos((*fTrackPar)(2,0))/TMath::Cos((*fTrackPar)(3,0)); // linear estimate
642   //AZ(z->-z) charge = iFB*TMath::Sign(Double_t(1.0),(*fTrackPar)(4,0));
643   charge = -iFB*TMath::Sign(Double_t(1.0),(*fTrackPar)(4,0));
644   SetGeantParam(vGeant3,iFB);
645   //fTrackParNew->Print();
646
647   // Check if overstep
648   do {
649     step = TMath::Abs(step);
650     // Propagate parameters
651     trackParam.ExtrapOneStepRungekutta(charge,step,vGeant3,vGeant3New);
652     //extrap_onestep_rungekutta(charge,step,vGeant3,vGeant3New);
653     distance = zEnd - vGeant3New[2];
654     step *= dZ/(vGeant3New[2]-fPositionNew);
655     nTries ++;
656   } while (distance*iFB < 0 && TMath::Abs(distance) > fgkEpsilon);
657
658   GetFromGeantParam(vGeant3New,iFB);
659   //fTrackParNew->Print();
660
661   // Position adjustment (until within tolerance)
662   while (TMath::Abs(distance) > fgkEpsilon) {
663     dZ = zEnd - fPositionNew;
664     iFB = (Int_t)TMath::Sign(Double_t(1.0),dZ);
665     step = dZ/TMath::Cos((*fTrackParNew)(2,0))/TMath::Cos((*fTrackParNew)(3,0));
666     step = TMath::Abs(step);
667     SetGeantParam(vGeant3,iFB);
668     do {
669       // binary search
670       // Propagate parameters
671       trackParam.ExtrapOneStepRungekutta(charge,step,vGeant3,vGeant3New);
672       //extrap_onestep_rungekutta(charge,step,vGeant3,vGeant3New);
673       distance = zEnd - vGeant3New[2];
674       step /= 2;
675       nTries ++;
676       if (nTries > fgkTriesMax) {
677         cout << " ***** ParPropagation: too many tries " << nTries << endl;
678         AliFatal("Too many tries.");
679       }
680     } while (distance*iFB < 0);
681
682     GetFromGeantParam(vGeant3New,iFB);
683   }
684   //cout << nTries << endl;
685   //fTrackParNew->Print();
686   return;
687 }
688 /*
689   //__________________________________________________________________________
690 void AliMUONTrackK::WeightPropagation(void)
691 {
692   // Propagation of the weight matrix
693   // W = DtWD, where D is Jacobian 
694
695   // !!! not implemented TMatrixD weight1(*fJacob,TMatrixD::kAtBA,*fWeight); // DtWD
696   TMatrixD weight1(*fWeight,TMatrixD::kMult,*fJacob); // WD
697   *fWeight = TMatrixD(*fJacob,TMatrixD::kTransposeMult,weight1); // DtWD
698   return;
699 }
700 */
701   //__________________________________________________________________________
702 void AliMUONTrackK::WeightPropagation(Double_t zEnd, Bool_t smooth)
703 {
704   // Propagation of the weight matrix
705   // W = DtWD, where D is Jacobian 
706   Int_t i, j;
707   Double_t dPar;
708
709   TMatrixD jacob(fgkSize,fgkSize);
710   jacob = 0;
711
712   // Save initial and propagated parameters
713   TMatrixD trackPar0 = *fTrackPar;
714   TMatrixD trackParNew0 = *fTrackParNew;
715
716   // Get covariance matrix
717   *fCovariance = *fWeight;
718   // check whether the Invert method returns flag if matrix cannot be inverted,
719   // and do not calculate the Determinant in that case !!!!
720   if (fCovariance->Determinant() != 0) {
721     //   fCovariance->Invert();
722     Int_t ifail;
723     mnvertLocal(&((*fCovariance)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
724     //fCovariance->Print();
725   } else {
726     AliWarning(" Determinant fCovariance=0:");
727   }
728
729   // Loop over parameters to find change of the propagated vs initial ones
730   for (i=0; i<fgkSize; i++) {
731     dPar = TMath::Sqrt((*fCovariance)(i,i));
732     *fTrackPar = trackPar0;
733     if (i == 4) dPar *= TMath::Sign(1.,-trackPar0(4,0)); // 1/p
734     (*fTrackPar)(i,0) += dPar;
735     ParPropagation(zEnd);
736     for (j=0; j<fgkSize; j++) {
737       jacob(j,i) = ((*fTrackParNew)(j,0)-trackParNew0(j,0))/dPar;
738     }
739   }
740
741   //trackParNew0.Print();
742   //TMatrixD par1(jacob,TMatrixD::kMult,trackPar0); //
743   //par1.Print();
744   TMatrixD jacob0 = jacob;
745   if (jacob.Determinant() != 0) {
746     jacob.Invert();
747   } else {
748     AliWarning(" Determinant jacob=0:");
749   }
750   TMatrixD weight1(*fWeight,TMatrixD::kMult,jacob); // WD
751   *fWeight = TMatrixD(jacob,TMatrixD::kTransposeMult,weight1); // DtWD
752
753   // Restore initial and propagated parameters
754   *fTrackPar = trackPar0;
755   *fTrackParNew = trackParNew0;
756
757   // Save for smoother
758   if (!smooth) return; // do not use smoother
759   //AZ(z->-z) if (fTrackDir > 0) return; // only for propagation towards int. point
760   if (fTrackDir < 0) return; // only for propagation towards int. point
761   TMatrixD *tmp = new TMatrixD(*fTrackParNew); // extrapolated parameters
762   fParExtrap->Add(tmp);
763   tmp->SetUniqueID(1);
764   tmp = new TMatrixD(*fTrackParNew); // filtered parameters (if no measurement will be found)
765   fParFilter->Add(tmp);
766   tmp->SetUniqueID(1);
767   *fCovariance = *fWeight;
768   if (fCovariance->Determinant() != 0) {
769     Int_t ifail;
770     mnvertLocal(&((*fCovariance)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
771   } else {
772     AliWarning(" Determinant fCovariance=0:");
773   }
774   tmp = new TMatrixD(*fCovariance); // extrapolated covariance
775   fCovExtrap->Add(tmp);
776   tmp->SetUniqueID(1);
777   tmp = new TMatrixD(*fCovariance); // filtered covariance (if no measurement will be found)
778   fCovFilter->Add(tmp);
779   tmp->SetUniqueID(1);
780   tmp = new TMatrixD(jacob0); // Jacobian
781   fJacob->Add(tmp);
782   tmp->SetUniqueID(1);
783   if (fSteps->fN <= fNSteps) fSteps->Set(fSteps->fN+10);
784   fSteps->AddAt(fPositionNew,fNSteps++); 
785   if (fgDebug > 0) cout << " WeightPropagation " << fNSteps << " " << fPositionNew << endl;
786   return;
787 }
788
789   //__________________________________________________________________________
790 Bool_t AliMUONTrackK::FindPoint(Int_t ichamb, Double_t zEnd, Int_t currIndx, Int_t iFB, AliMUONHitForRec *&hitAdd)
791 {
792   // Picks up point within a window for the chamber No ichamb 
793   // Split the track if there are more than 1 hit
794   Int_t ihit, nRecTracks;
795   Double_t windowB, windowNonB, dChi2Tmp=0, dChi2, y, x, savePosition=0;
796   TClonesArray *trackPtr;
797   AliMUONHitForRec *hit, *hitLoop;
798   AliMUONTrackK *trackK;
799
800   Bool_t ok = kFALSE;
801   //sigmaB = fgTrackReconstructor->GetBendingResolution(); // bending resolution
802   //sigmaNonB = fgTrackReconstructor->GetNonBendingResolution(); // non-bending resolution
803   *fCovariance = *fWeight;
804   // check whether the Invert method returns flag if matrix cannot be inverted,
805   // and do not calculate the Determinant in that case !!!!
806   if (fCovariance->Determinant() != 0) {
807     //  fCovariance->Invert();
808       Int_t ifail;
809       mnvertLocal(&((*fCovariance)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
810   } else {
811     AliWarning(" Determinant fCovariance=0:");
812   }
813   //windowB = fgkNSigma*TMath::Sqrt((*fCovariance)(0,0)+sigmaB*sigmaB);
814   //windowNonB = fgkNSigma*TMath::Sqrt((*fCovariance)(1,1)+sigmaNonB*sigmaNonB);
815   // Loop over all hits and take hits from the chamber
816   TMatrixD pointWeight(fgkSize,fgkSize);
817   TMatrixD saveWeight = pointWeight;
818   TMatrixD pointWeightTmp = pointWeight;
819   TMatrixD point(fgkSize,1);
820   TMatrixD trackPar = point;
821   TMatrixD trackParTmp = point;
822   Int_t nHitsOK = 0;
823   Double_t zLast;
824   zLast = ((AliMUONHitForRec*)fTrackHitsPtr->Last())->GetZ();
825
826   for (ihit=currIndx; ihit>=0 && ihit<fgNOfPoints; ihit+=iFB) {
827     hit = (AliMUONHitForRec*) ((*fgHitForRec)[ihit]);
828     if (hit->GetChamberNumber() == ichamb) {
829       //if (TMath::Abs(hit->GetZ()-zEnd) < 0.1) {
830       if (TMath::Abs(hit->GetZ()-zEnd) < 0.5) {
831         //if (TMath::Abs(hit->GetZ()-zEnd) > 0.1) {
832         if (TMath::Abs(hit->GetZ()-zEnd) > 0.05) {
833           // adjust position: for multiple hits in the chamber
834           // (mostly (only?) for GEANT hits)
835           cout << " ******* adjust " << zEnd << " " << hit->GetZ() << endl;
836           zEnd = hit->GetZ();
837           *fTrackPar = *fTrackParNew;
838           ParPropagation(zEnd);
839           WeightPropagation(zEnd, kTRUE);
840           fPosition = fPositionNew;
841           *fTrackPar = *fTrackParNew;
842           // Get covariance
843           *fCovariance = *fWeight;
844           if (fCovariance->Determinant() != 0) {
845             Int_t ifail;
846             mnvertLocal(&((*fCovariance)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
847           } else {
848             AliWarning(" Determinant fCovariance=0:" );
849           }
850         }
851         y = hit->GetBendingCoor();
852         x = hit->GetNonBendingCoor();
853         windowB = fgkNSigma*TMath::Sqrt((*fCovariance)(0,0)+hit->GetBendingReso2());
854         windowNonB = fgkNSigma*TMath::Sqrt((*fCovariance)(1,1)+hit->GetNonBendingReso2());
855
856         // windowB = TMath::Min (windowB,5.);
857         if (fgkNSigma > 6) windowB = TMath::Min (windowB,5.);
858         /*
859         if (TMath::Abs(hit->GetZ()-zLast) < 50) {
860           windowB = TMath::Min (windowB,0.5);
861           windowNonB = TMath::Min (windowNonB,3.);
862         } else if (TMath::Abs(hit->GetZ()-zLast) < 200) {
863           windowB = TMath::Min (windowB,1.5);
864           windowNonB = TMath::Min (windowNonB,3.);
865         } else if (TMath::Abs(hit->GetZ()-zLast) < 350) {
866           windowB = TMath::Min (windowB,4.);
867           windowNonB = TMath::Min (windowNonB,6.);
868         }
869         */
870
871         // Test
872         /*
873         if (TMath::Abs(hit->GetZ()-zLast) < 50) {
874           windowB = 5*TMath::Sqrt((*fCovariance)(0,0)+hit->GetBendingReso2());
875           windowNonB = 5*TMath::Sqrt((*fCovariance)(1,1)+hit->GetNonBendingReso2());
876         } else {
877           windowB = fgkNSigma*TMath::Sqrt((*fCovariance)(0,0)+hit->GetBendingReso2());
878           windowNonB = fgkNSigma*TMath::Sqrt((*fCovariance)(1,1)+hit->GetNonBendingReso2());
879         }
880         */
881
882         //cout << TMath::Abs((*fTrackParNew)(0,0)-y) << " " << windowB << " " << TMath::Abs((*fTrackParNew)(1,0)-x) << " " << windowNonB << " " << zEnd << endl;
883         if (TMath::Abs((*fTrackParNew)(0,0)-y) <= windowB &&
884             TMath::Abs((*fTrackParNew)(1,0)-x) <= windowNonB) {
885         //if (TMath::Abs((*fTrackParNew)(0,0)-y) <= windowB &&
886           //    TMath::Abs((*fTrackParNew)(1,0)-x) <= windowNonB &&
887           //  hit->GetTrackRefSignal() == 1) { // just for test
888           // Vector of measurements and covariance matrix
889           //fprintf(lun1,"%3d %3d %10.4f %10.4f \n", gAlice->GetEvNumber(), ichamb, x, y);
890           point.Zero();
891           point(0,0) = y;
892           point(1,0) = x;
893           pointWeight(0,0) = 1/hit->GetBendingReso2();
894           pointWeight(1,1) = 1/hit->GetNonBendingReso2();
895           TryPoint(point,pointWeight,trackPar,dChi2);
896           if (TMath::Abs(1./(trackPar)(4,0)) < fgTrackReconstructor->GetMinBendingMomentum()) continue; // p < p_min - next hit
897           ok = kTRUE;
898           nHitsOK++;
899           //if (nHitsOK > -1) {
900           if (nHitsOK == 1) {
901             // Save current members
902             saveWeight = *fWeight;
903             savePosition = fPosition;
904             // temporary storage for the current track
905             dChi2Tmp = dChi2;
906             trackParTmp = trackPar;
907             pointWeightTmp = pointWeight;
908             hitAdd = hit;
909           } else {
910             // branching: create a new track
911             trackPtr = fgTrackReconstructor->GetRecTracksPtr();
912             nRecTracks = fgTrackReconstructor->GetNRecTracks();
913             trackK = new ((*trackPtr)[nRecTracks]) AliMUONTrackK(NULL, NULL); 
914             *trackK = *this;
915             fgTrackReconstructor->SetNRecTracks(nRecTracks+1);
916             if (fgDebug > 0) cout << " ******** New track: " << ichamb << " " << hit->GetTTRTrack() << " " << 1/(trackPar)(4,0) << " " << hit->GetBendingCoor() << " " << hit->GetNonBendingCoor() << " " << fNTrackHits << " " << nRecTracks << endl;
917             trackK->fRecover = 0;
918             *(trackK->fTrackPar) = trackPar;
919             *(trackK->fWeight) += pointWeight; 
920             trackK->fChi2 += dChi2;
921             // Check
922             /*
923             *(trackK->fCovariance) = *(trackK->fWeight);
924             if (trackK->fCovariance->Determinant() != 0) {
925               Int_t ifail;
926               mnvertLocal(&((*(trackK->fCovariance))(0,0)), fgkSize,fgkSize,fgkSize,ifail);
927             }
928             cout << (*(trackK->fCovariance))(0,0) << " " << (*(trackK->fCovariance))(1,1) << " " << (*fCovariance)(0,0) << " " << (*fCovariance)(1,1) << endl;
929             */
930             // Add filtered matrices for the smoother
931             //AZ(z->-z) if (fTrackDir < 0) {
932             if (fTrackDir > 0) {
933               if (nHitsOK > 2) { // check for position adjustment
934                 for (Int_t i=trackK->fNSteps-1; i>=0; i--) {
935                   if (TMath::Abs(hit->GetZ()-(*trackK->fSteps)[i]) > 0.1) {
936                   //if (TMath::Abs(hit->GetZ()-(trackK->fSteps)[i]) > 0.1) {
937                     RemoveMatrices(trackK);
938                     cout << " *** Position adjustment 1 " << hit->GetZ() << " " 
939                          << (*trackK->fSteps)[i] << endl;
940                     AliFatal(" Position adjustment 1.");
941                   }
942                   else break;
943                 }
944               }
945               AddMatrices (trackK, dChi2, hit);
946             }
947             // Mark hits as being on 2 tracks
948             for (Int_t i=0; i<fNTrackHits; i++) {
949               hitLoop = (AliMUONHitForRec*) ((*fTrackHitsPtr)[i]);
950               hitLoop->SetNTrackHits(hitLoop->GetNTrackHits()+1); 
951               if (fgDebug >=10) {
952                 cout << " ** ";
953                 cout << hitLoop->GetChamberNumber() << " ";
954                 cout << hitLoop->GetBendingCoor() << " ";
955                 cout << hitLoop->GetNonBendingCoor() << " ";
956                 cout << hitLoop->GetZ() << " " << " ";
957                 cout << hitLoop->GetTrackRefSignal() << " " << " ";
958                 cout << hitLoop->GetTTRTrack() << endl;
959                 printf(" ** %d %10.4f %10.4f %10.4f %d %d \n", 
960                        hitLoop->GetChamberNumber(), hitLoop->GetBendingCoor(), 
961                        hitLoop->GetNonBendingCoor(), hitLoop->GetZ(), 
962                        hitLoop->GetTrackRefSignal(), hitLoop->GetTTRTrack());
963               }
964             }
965             //add point
966             trackK->fTrackHitsPtr->Add(hit); // add hit
967             trackK->fNTrackHits ++;
968             hit->SetNTrackHits(hit->GetNTrackHits()+1); // mark hit as being on track
969             if (ichamb == 9) {
970               // the last chamber
971               //AZ(z->-z) trackK->fTrackDir = -1;
972               trackK->fTrackDir = 1;
973               trackK->fBPFlag = kTRUE; 
974             }
975           }
976         }
977       }
978     } else break; // different chamber
979   } // for (ihit=currIndx;
980   if (ok) {
981     // Restore members
982     *fTrackPar = trackParTmp;
983     *fWeight = saveWeight;
984     *fWeight += pointWeightTmp; 
985     fChi2 += dChi2Tmp; // Chi2
986     fPosition = savePosition;
987     // Add filtered matrices for the smoother
988     //AZ(z->-z) if (fTrackDir < 0) {
989     if (fTrackDir > 0) {
990       for (Int_t i=fNSteps-1; i>=0; i--) {
991         if (TMath::Abs(fPosition-(*fSteps)[i]) > 0.1) {
992         //if (TMath::Abs(fPosition-fSteps[i]) > 0.1) {
993           RemoveMatrices(this);
994           if (fgDebug > 0) cout << " *** Position adjustment 2 " << fPosition << " " << (*fSteps)[i] << endl;
995         }
996         else break;
997       } // for (Int_t i=fNSteps-1;
998       AddMatrices (this, dChi2Tmp, hitAdd);
999       /*
1000       if (nHitsOK > 1) {
1001         for (Int_t i=0; i<fNSteps; i++) cout << (*fSteps)[i] << " "; cout << endl;
1002         for (Int_t i=0; i<trackK->fNSteps; i++) cout << (*trackK->fSteps)[i] << " "; cout << endl;
1003       }
1004       */
1005     } // if (fTrackDir > 0)
1006   }
1007   return ok;
1008 }
1009
1010   //__________________________________________________________________________
1011 void AliMUONTrackK::TryPoint(TMatrixD &point, const TMatrixD &pointWeight, TMatrixD &trackParTmp, Double_t &dChi2)
1012 {
1013   // Adds a measurement point (modifies track parameters and computes
1014   // change of Chi2)
1015
1016   // Solving linear system (W+U)p' = U(m-p) + (W+U)p
1017   TMatrixD wu = *fWeight;
1018   wu += pointWeight; // W+U
1019   trackParTmp = point;
1020   trackParTmp -= *fTrackParNew; // m-p
1021   TMatrixD right(pointWeight,TMatrixD::kMult,trackParTmp); // U(m-p)
1022   TMatrixD right1(wu,TMatrixD::kMult,*fTrackParNew); // (W+U)p
1023   right += right1; // U(m-p) + (W+U)p
1024
1025   // check whether the Invert method returns flag if matrix cannot be inverted,
1026   // and do not calculate the Determinant in that case !!!!
1027   if (wu.Determinant() != 0) {
1028     //  wu.Invert();
1029      Int_t ifail;
1030       mnvertLocal(&((wu)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1031   } else {
1032     AliWarning(" Determinant wu=0:");
1033   }
1034   trackParTmp = TMatrixD(wu,TMatrixD::kMult,right); 
1035
1036   right1 = trackParTmp;
1037   right1 -= point; // p'-m
1038   point = trackParTmp;
1039   point -= *fTrackParNew; // p'-p
1040   right = TMatrixD(*fWeight,TMatrixD::kMult,point); // W(p'-p)
1041   TMatrixD value(point,TMatrixD::kTransposeMult,right); // (p'-p)'W(p'-p)
1042   dChi2 = value(0,0);
1043   right = TMatrixD(pointWeight,TMatrixD::kMult,right1); // U(p'-m)
1044   value = TMatrixD(right1,TMatrixD::kTransposeMult,right); // (p'-m)'U(p'-m)
1045   dChi2 += value(0,0);
1046   return;
1047 }
1048
1049   //__________________________________________________________________________
1050 void AliMUONTrackK::MSThin(Int_t sign)
1051 {
1052   // Adds multiple scattering in a thin layer (only angles are affected)
1053   Double_t cosAlph, cosBeta, momentum, velo, path, theta0;
1054
1055   // check whether the Invert method returns flag if matrix cannot be inverted,
1056   // and do not calculate the Determinant in that case !!!!
1057   if (fWeight->Determinant() != 0) {
1058     //fWeight->Invert(); // covariance
1059
1060     Int_t ifail;
1061     mnvertLocal(&((*fWeight)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1062   } else {
1063     AliWarning(" Determinant fWeight=0:");
1064   }
1065
1066   cosAlph = TMath::Cos((*fTrackParNew)(2,0));
1067   cosBeta = TMath::Cos((*fTrackParNew)(3,0));
1068   momentum = 1/(*fTrackParNew)(4,0); // particle momentum
1069   //velo = momentum/TMath::Sqrt(momentum*momentum+muonMass*muonMass); // velocity/c for muon hypothesis
1070   velo = 1; // relativistic
1071   path = TMath::Abs(fgTrackReconstructor->GetChamberThicknessInX0()/cosAlph/cosBeta); // path length
1072   theta0 = 0.0136/velo/momentum*TMath::Sqrt(path)*(1+0.038*TMath::Log(path)); // projected scattering angle
1073
1074   (*fWeight)(2,2) += sign*theta0/cosBeta*theta0/cosBeta; // alpha
1075   (*fWeight)(3,3) += sign*theta0*theta0; // beta
1076   //fWeight->Invert(); // weight
1077
1078   Int_t ifail;
1079   mnvertLocal(&((*fWeight)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1080   return;
1081 }
1082
1083   //__________________________________________________________________________
1084 void AliMUONTrackK::StartBack(void)
1085 {
1086   // Starts backpropagator
1087   
1088   fBPFlag = kTRUE;
1089   fChi2 = 0;
1090   for (Int_t i=0; i<fgkSize; i++) {
1091     for (Int_t j=0; j<fgkSize; j++) {
1092       if (j==i) (*fWeight)(i,i) /= 100;
1093       //if (j==i) (*fWeight)(i,i) /= fNTrackHits*fNTrackHits;
1094       else (*fWeight)(j,i) = 0;
1095     }
1096   }
1097   // Sort hits on track in descending order in abs(z)
1098   SortHits(0, fTrackHitsPtr);
1099 }
1100
1101   //__________________________________________________________________________
1102 void AliMUONTrackK::SortHits(Int_t iflag, TObjArray *array)
1103 {
1104   // Sort hits in Z if the seed segment in the last but one station
1105   // (if iflag==0 in descending order in abs(z), if !=0 - unsort)
1106   
1107   if (iflag && ((AliMUONHitForRec*)(array->UncheckedAt(0)))->GetChamberNumber() == 6) return;
1108   Double_t z = 0, zmax = TMath::Abs(((AliMUONHitForRec*)(array->UncheckedAt(0)))->GetZ());
1109   Int_t i = 1, entries = array->GetEntriesFast(); 
1110   for ( ; i<entries; i++) {
1111     if (iflag) {
1112       if (((AliMUONHitForRec*)(array->UncheckedAt(i)))->GetChamberNumber() == 6) break;
1113     } else {
1114       z = TMath::Abs(((AliMUONHitForRec*)(array->UncheckedAt(i)))->GetZ());
1115       if (z < zmax) break;
1116       zmax = z;
1117       if (fgDebug >= 10) cout << " " << zmax << " " << z << " " << i << endl;
1118     }
1119   }
1120   if (!iflag) i--;
1121   for (Int_t j=0; j<=(i-1)/2; j++) {
1122     TObject *hit = array->UncheckedAt(j);
1123     array->AddAt(array->UncheckedAt(i-j),j);
1124     array->AddAt(hit,i-j);
1125   }
1126   if (fgDebug >= 10) {
1127     for (i=0; i<entries; i++) 
1128       cout << ((AliMUONHitForRec*)(array->UncheckedAt(i)))->GetZ() << " ";
1129     cout << " - Sort" << endl;
1130   }
1131 }
1132
1133   //__________________________________________________________________________
1134 void AliMUONTrackK::SetGeantParam(Double_t *VGeant3, Int_t iFB)
1135 {
1136   // Set vector of Geant3 parameters pointed to by "VGeant3"
1137   // from track parameters 
1138
1139   VGeant3[0] = (*fTrackParNew)(1,0); // X
1140   VGeant3[1] = (*fTrackParNew)(0,0); // Y
1141   VGeant3[2] = fPositionNew; // Z
1142   VGeant3[3] = iFB*TMath::Sin((*fTrackParNew)(3,0)); // Px/Ptot
1143   VGeant3[4] = iFB*TMath::Cos((*fTrackParNew)(3,0))*TMath::Sin((*fTrackParNew)(2,0)); // Py/Ptot
1144   VGeant3[5] = iFB*TMath::Sqrt(1.0-VGeant3[3]*VGeant3[3]-VGeant3[4]*VGeant3[4]); // Pz/Ptot
1145   VGeant3[6] = 1/TMath::Abs((*fTrackParNew)(4,0)); // Ptot
1146 }
1147
1148   //__________________________________________________________________________
1149 void AliMUONTrackK::GetFromGeantParam(Double_t *VGeant3, Int_t iFB)
1150 {
1151   // Get track parameters from vector of Geant3 parameters pointed 
1152   // to by "VGeant3"
1153
1154   fPositionNew = VGeant3[2]; // Z
1155   (*fTrackParNew)(0,0) = VGeant3[1]; // Y 
1156   (*fTrackParNew)(1,0) = VGeant3[0]; // X
1157   (*fTrackParNew)(3,0) = TMath::ASin(iFB*VGeant3[3]); // beta
1158   (*fTrackParNew)(2,0) = TMath::ASin(iFB*VGeant3[4]/TMath::Cos((*fTrackParNew)(3,0))); // alpha
1159   (*fTrackParNew)(4,0) = 1/VGeant3[6]*TMath::Sign(Double_t(1.0),(*fTrackPar)(4,0)); // 1/Ptot
1160 }
1161
1162   //__________________________________________________________________________
1163 void AliMUONTrackK::SetTrackQuality(Int_t iChi2)
1164 {
1165   // Computes "track quality" from Chi2 (if iChi2==0) or vice versa
1166
1167   if (fChi2 > 500) {
1168     cout << " ***** Too high Chi2: " << fChi2 << endl;
1169     fChi2 = 500;
1170   }
1171   if (iChi2 == 0) fChi2 = fNTrackHits + (500.-fChi2)/501;
1172   else fChi2 = 500 - (fChi2-fNTrackHits)*501;
1173 }
1174
1175   //__________________________________________________________________________
1176 Int_t AliMUONTrackK::Compare(const TObject* trackK) const
1177 {
1178   // "Compare" function to sort with decreasing "track quality".
1179   // Returns +1 (0, -1) if quality of current track
1180   // is smaller than (equal to, larger than) quality of trackK
1181
1182   if (fChi2 < ((AliMUONTrackK*)trackK)->fChi2) return(+1);
1183   else if (fChi2 == ((AliMUONTrackK*)trackK)->fChi2) return(0);
1184   else return(-1);
1185 }
1186
1187   //__________________________________________________________________________
1188 Bool_t AliMUONTrackK::KeepTrack(AliMUONTrackK* track0) const
1189 {
1190   // Check whether or not to keep current track 
1191   // (keep, if it has less than half of common hits with track0)
1192   Int_t hitsInCommon, nHits0, i, j, nTrackHits2;
1193   AliMUONHitForRec *hit0, *hit1;
1194
1195   hitsInCommon = 0;
1196   nHits0 = track0->fNTrackHits;
1197   nTrackHits2 = fNTrackHits/2;
1198
1199   for (i=0; i<nHits0; i++) {
1200     // Check if hit belongs to several tracks
1201     hit0 = (AliMUONHitForRec*) (*track0->fTrackHitsPtr)[i]; 
1202     if (hit0->GetNTrackHits() == 1) continue; 
1203     for (j=0; j<fNTrackHits; j++) {
1204       hit1 = (AliMUONHitForRec*) (*fTrackHitsPtr)[j]; 
1205       if (hit1->GetNTrackHits() == 1) continue; 
1206       if (hit0 == hit1) {
1207         hitsInCommon++;
1208         if (hitsInCommon >= nTrackHits2) return kFALSE;
1209         break;
1210       }
1211     } // for (j=0; 
1212   } // for (i=0; 
1213   return kTRUE;
1214 }
1215
1216   //__________________________________________________________________________
1217 void AliMUONTrackK::Kill(void)
1218 {
1219   // Kill track candidate
1220   Int_t i;
1221   AliMUONHitForRec *hit;
1222
1223   if (fTrackHitsPtr) {
1224     // Remove track mark from hits
1225     for (i=0; i<fNTrackHits; i++) {
1226       hit = (AliMUONHitForRec*) (*fTrackHitsPtr)[i]; 
1227       hit->SetNTrackHits(hit->GetNTrackHits()-1); 
1228     }
1229   }
1230   fgTrackReconstructor->GetRecTracksPtr()->Remove(this);
1231 }
1232
1233   //__________________________________________________________________________
1234 void AliMUONTrackK::FillMUONTrack(void)
1235 {
1236   // Compute track parameters at hit positions (as for AliMUONTrack)
1237
1238   // Set number of hits per track
1239   ((AliMUONTrack*)this)->SetNTrackHits(fNTrackHits);
1240
1241   // Set track parameters at vertex
1242   AliMUONTrackParam trackParam;
1243   SetTrackParam(&trackParam, fTrackPar, fPosition);
1244   ((AliMUONTrack*)this)->SetTrackParamAtVertex(&trackParam);
1245
1246   // Set track parameters at hits
1247   for (Int_t i = fNTrackHits-1; i>=0; i--) {
1248     if ((*fChi2Smooth)[i] < 0) {
1249       // Propagate through last chambers
1250       trackParam.ExtrapToZ(((AliMUONHitForRec*)((*fTrackHitsPtr)[i]))->GetZ());
1251     } else {
1252       // Take saved info
1253       SetTrackParam(&trackParam, (TMatrixD*)fParSmooth->UncheckedAt(i), ((AliMUONHitForRec*)((*fTrackHitsPtr)[i]))->GetZ());
1254     }
1255     ((AliMUONTrack*)this)->AddTrackParamAtHit(&trackParam); 
1256     // Fill array of HitForRec's
1257     ((AliMUONTrack*)this)->AddHitForRecAtHit((AliMUONHitForRec*)fTrackHitsPtr->UncheckedAt(i)); 
1258   }
1259 }
1260
1261   //__________________________________________________________________________
1262 void AliMUONTrackK::SetTrackParam(AliMUONTrackParam *trackParam, TMatrixD *par, Double_t z)
1263 {
1264   // Fill AliMUONTrackParam object
1265
1266   trackParam->SetBendingCoor((*par)(0,0));
1267   trackParam->SetNonBendingCoor((*par)(1,0));
1268   trackParam->SetBendingSlope(TMath::Tan((*par)(2,0)));
1269   trackParam->SetNonBendingSlope(TMath::Tan((*par)(3,0))/TMath::Cos((*par)(2,0)));
1270   trackParam->SetInverseBendingMomentum((*par)(4,0)/TMath::Cos((*par)(3,0)));
1271   trackParam->SetZ(z);
1272 }
1273
1274   //__________________________________________________________________________
1275 void AliMUONTrackK::Branson(void)
1276 {
1277   // Propagates track to the vertex thru absorber using Branson correction
1278   // (makes use of the AliMUONTrackParam class)
1279  
1280   //AliMUONTrackParam *trackParam = new AliMUONTrackParam();
1281   AliMUONTrackParam trackParam = AliMUONTrackParam();
1282   /*
1283   trackParam->SetBendingCoor((*fTrackPar)(0,0));
1284   trackParam->SetNonBendingCoor((*fTrackPar)(1,0));
1285   trackParam->SetBendingSlope(TMath::Tan((*fTrackPar)(2,0)));
1286   trackParam->SetNonBendingSlope(TMath::Tan((*fTrackPar)(3,0))/TMath::Cos((*fTrackPar)(2,0)));
1287   trackParam->SetInverseBendingMomentum((*fTrackPar)(4,0)/TMath::Cos((*fTrackPar)(3,0)));
1288   trackParam->SetZ(fPosition);
1289   */
1290   SetTrackParam(&trackParam, fTrackPar, fPosition);
1291
1292   trackParam.ExtrapToVertex(Double_t(0.), Double_t(0.), Double_t(0.));
1293   //trackParam.ExtrapToVertex();
1294
1295   (*fTrackPar)(0,0) = trackParam.GetBendingCoor();
1296   (*fTrackPar)(1,0) = trackParam.GetNonBendingCoor();
1297   (*fTrackPar)(2,0) = TMath::ATan(trackParam.GetBendingSlope());
1298   (*fTrackPar)(3,0) = TMath::ATan(TMath::Cos((*fTrackPar)(2,0))*trackParam.GetNonBendingSlope());
1299   (*fTrackPar)(4,0) = TMath::Cos((*fTrackPar)(3,0))*trackParam.GetInverseBendingMomentum();
1300   fPosition = trackParam.GetZ();
1301   //delete trackParam;
1302   cout << 1/(*fTrackPar)(4,0) << " " << fPosition << " " << (*fTrackPar)(0,0) << endl;
1303
1304   // Get covariance matrix
1305   *fCovariance = *fWeight;
1306   if (fCovariance->Determinant() != 0) {
1307       Int_t ifail;
1308       mnvertLocal(&((*fCovariance)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1309   } else {
1310     AliWarning(" Determinant fCovariance=0:");
1311   }
1312 }
1313
1314   //__________________________________________________________________________
1315 void AliMUONTrackK::GoToZ(Double_t zEnd)
1316 {
1317   // Propagates track to given Z
1318
1319   ParPropagation(zEnd);
1320   MSThin(1); // multiple scattering in the chamber
1321   WeightPropagation(zEnd, kFALSE);
1322   fPosition = fPositionNew;
1323   *fTrackPar = *fTrackParNew; 
1324 }
1325
1326   //__________________________________________________________________________
1327 void AliMUONTrackK::GoToVertex(Int_t iflag)
1328 {
1329   // Version 3.08
1330   // Propagates track to the vertex
1331   // All material constants are taken from AliRoot
1332
1333     static Double_t x01[5] = { 24.282,  // C
1334                                24.282,  // C
1335                                11.274,  // Concrete
1336                                 1.758,  // Fe 
1337                                 1.758}; // Fe (cm)
1338   // inner part theta < 3 degrees
1339     static Double_t x02[5] = { 30413,  // Air
1340                                24.282, // C
1341                                11.274, // Concrete
1342                                1.758,  // Fe
1343                                0.369}; // W (cm)
1344   // z positions of the materials inside the absober outer part theta > 3 degres
1345   static Double_t zPos[10] = {-90, -105, -315, -443, -468};
1346
1347   Double_t dZ, r0Norm, x0, deltaP, dChi2, pTotal, pOld;
1348   AliMUONHitForRec *hit;
1349   AliMUONRawCluster *clus;
1350   TClonesArray *rawclusters;
1351
1352   // First step to the rear end of the absorber
1353   //AZ(z->-z) Double_t zRear = 503;
1354   Double_t zRear = -503;
1355   GoToZ(zRear);
1356   Double_t tan3 = TMath::Tan(3./180*TMath::Pi());
1357
1358   // Go through absorber
1359   pOld = 1/(*fTrackPar)(4,0);
1360   Double_t r0Rear = (*fTrackPar)(0,0)*(*fTrackPar)(0,0) + 
1361                     (*fTrackPar)(1,0)*(*fTrackPar)(1,0);
1362   r0Rear = TMath::Sqrt(r0Rear)/TMath::Abs(fPosition)/tan3;
1363   r0Norm = r0Rear;
1364   Double_t p0, cos25, cos60;
1365   if (!iflag) goto vertex;
1366
1367   for (Int_t i=4; i>=0; i--) {
1368     ParPropagation(zPos[i]);
1369     WeightPropagation(zPos[i], kFALSE);
1370     dZ = TMath::Abs (fPositionNew-fPosition);
1371     if (r0Norm > 1) x0 = x01[i];
1372     else x0 = x02[i];
1373     MSLine(dZ,x0); // multiple scattering in the medium (linear approximation)
1374     fPosition = fPositionNew;
1375     *fTrackPar = *fTrackParNew; 
1376     r0Norm = (*fTrackPar)(0,0)*(*fTrackPar)(0,0) + 
1377              (*fTrackPar)(1,0)*(*fTrackPar)(1,0);
1378     r0Norm = TMath::Sqrt(r0Norm)/TMath::Abs(fPosition)/tan3;
1379   }
1380   // Correct momentum for energy losses
1381   pTotal = 1/TMath::Abs((*fTrackPar)(4,0));
1382   p0 = pTotal;
1383   cos25 = TMath::Cos(2.5/180*TMath::Pi());
1384   cos60 = TMath::Cos(6.0/180*TMath::Pi());
1385   for (Int_t j=0; j<1; j++) {
1386     /*
1387     if (r0Rear > 1) {
1388       if (p0 < 20) {
1389         deltaP = 2.164 + 0.145e-1*p0 - 0.417e-3*p0*p0;
1390       } else {
1391         deltaP = 2.275 + 0.102e-2*p0 - 0.674e-6*p0*p0;
1392       }
1393     } else {
1394       if (p0 < 20) {
1395         deltaP = 2.581 + 0.188e-1*p0 - 0.398e-3*p0*p0;
1396       } else {
1397         deltaP = 2.727 + 0.356e-2*p0 + 0.242e-5*p0*p0;
1398       }
1399     }
1400     */
1401     /*
1402     if (r0Rear < 1) {
1403       //W
1404       if (p0<15) {
1405         deltaP = 2.737 + 0.0494*p0 - 0.001123*p0*p0;
1406       } else {
1407         deltaP = 3.0643 + 0.01346*p0;
1408       }
1409       deltaP *= 0.95;
1410     } else {
1411       //Pb
1412       if (p0<15) {
1413         deltaP  = 2.1380 + 0.0351*p0 - 0.000853*p0*p0;
1414       } else {
1415         deltaP = 2.407 + 0.00702*p0;
1416       }
1417       deltaP *= 0.95;
1418     }
1419     */
1420     /*
1421     if (r0Rear < 1) {
1422       //W
1423       if (p0<18) {
1424         deltaP = 2.439 + 0.806e-1*p0 - 0.500e-2*p0*p0 + 0.106e-3*p0*p0*p0;
1425       } else {
1426         deltaP = 2.767 + 0.742e-2*p0 - 0.196e-4*p0*p0 + 0.403e-7*p0*p0*p0;
1427       }
1428       //deltaP += 0.2;
1429       deltaP *= cos25;
1430     } else {
1431       //Pb
1432       if (p0<18) {
1433         deltaP  = 2.209 + 0.800e-2*p0;
1434       } else {
1435         deltaP = 2.285 + 0.141e-2*p0 - 0.446e-6*p0*p0;
1436       }
1437       //deltaP += 0.2;
1438       deltaP *= cos60;
1439     }
1440     deltaP *= 1.1;
1441     */
1442     //*
1443     if (r0Rear  < 1) {
1444       if (p0 < 20) {
1445         deltaP = 2.5938 + 0.0570 * p0 - 0.001151 * p0 * p0;
1446       } else {
1447         deltaP = 3.0714 + 0.011767 * p0;
1448       }
1449     } else {
1450       if (p0 < 20) {
1451         deltaP  = 2.1207 + 0.05478 * p0 - 0.00145079 * p0 * p0;
1452       } else { 
1453         deltaP = 2.6069 + 0.0051705 * p0;
1454       }
1455     }
1456     deltaP *= 0.9; 
1457     //*/
1458
1459     p0 = pTotal + deltaP/TMath::Abs(TMath::Cos((*fTrackPar)(2,0))/TMath::Cos((*fTrackPar)(3,0)));
1460   }
1461   (*fTrackPar)(4,0) = 1/p0*TMath::Sign((Double_t)1.,(*fTrackPar)(4,0));
1462
1463   // Go to the vertex
1464 vertex:
1465   ParPropagation((Double_t)0.);
1466   WeightPropagation((Double_t)0., kFALSE);
1467   fPosition = fPositionNew;
1468   //*fTrackPar = *fTrackParNew; 
1469   // Add vertex as a hit
1470   TMatrixD pointWeight(fgkSize,fgkSize);
1471   TMatrixD point(fgkSize,1);
1472   TMatrixD trackParTmp = point;
1473   point(0,0) = 0; // vertex coordinate - should be taken somewhere
1474   point(1,0) = 0; // vertex coordinate - should be taken somewhere
1475   pointWeight(0,0) = 1/1.e-3/1.e-3; // 10 um error
1476   pointWeight(1,1) = 1/1.e-3/1.e-3; // 10 um error
1477   TryPoint(point,pointWeight,trackParTmp,dChi2);
1478   *fTrackPar = trackParTmp;
1479   *fWeight += pointWeight; 
1480   fChi2 += dChi2; // Chi2
1481   if (fgDebug < 0) return; // no output
1482
1483   cout << pOld << " " << 1/(*fTrackPar)(4,0) << " " << dChi2 << " " << fChi2 << " " << fNTrackHits << endl;
1484   for (Int_t i1=0; i1<fNTrackHits; i1++) {
1485     hit =  (AliMUONHitForRec*) ((*fTrackHitsPtr)[i1]);
1486     printf ("%4d", hit->GetChamberNumber()); 
1487   }
1488   cout << endl;
1489   if (fgDebug > 0) {
1490     for (Int_t i1=0; i1<fNTrackHits; i1++) {
1491       hit =  (AliMUONHitForRec*) ((*fTrackHitsPtr)[i1]);
1492       //cout << ((AliMUONHitForRec*)((*fTrackHitsPtr)[i1]))->GetHitNumber() << " ";
1493       //cout << ((AliMUONHitForRec*)((*fTrackHitsPtr)[i1]))->GetZ() << " ";
1494       printf ("%4d", fgHitForRec->IndexOf(hit)); 
1495     }
1496     cout << endl;
1497   }
1498   if (fgTrackReconstructor->GetRecTrackRefHits()) { 
1499       // from track ref. hits
1500     for (Int_t i1=0; i1<fNTrackHits; i1++) {
1501       hit =  (AliMUONHitForRec*) ((*fTrackHitsPtr)[i1]);
1502       cout << hit->GetTTRTrack() + hit->GetTrackRefSignal()*10000 << " ";
1503     }
1504   } else {
1505     // from raw clusters
1506     for (Int_t i1=0; i1<fNTrackHits; i1++) {
1507       hit =  (AliMUONHitForRec*) ((*fTrackHitsPtr)[i1]);
1508       rawclusters = fgTrackReconstructor->GetMUONData()->RawClusters(hit->GetChamberNumber());
1509       clus = (AliMUONRawCluster*) rawclusters->UncheckedAt(hit->GetHitNumber());
1510       printf ("%4d", clus->GetTrack(1)); 
1511     }
1512     cout << endl;
1513     for (Int_t i1=0; i1<fNTrackHits; i1++) {
1514       hit =  (AliMUONHitForRec*) ((*fTrackHitsPtr)[i1]);
1515       rawclusters = fgTrackReconstructor->GetMUONData()->RawClusters(hit->GetChamberNumber());
1516       clus = (AliMUONRawCluster*) rawclusters->UncheckedAt(hit->GetHitNumber());
1517       if (clus->GetTrack(2) != -1) printf ("%4d", clus->GetTrack(2));
1518       else printf ("%4s", "   ");
1519     }
1520   }
1521   cout << endl;
1522   for (Int_t i1=0; i1<fNTrackHits; i1++) {
1523     //cout << ((AliMUONHitForRec*)((*fTrackHitsPtr)[i1]))->GetHitNumber() << " ";
1524     cout << ((AliMUONHitForRec*)((*fTrackHitsPtr)[i1]))->GetZ() << " ";
1525     //cout << fgHitForRec->IndexOf(((AliMUONHitForRec*)((*fTrackHitsPtr)[i1]))) << " ";
1526   }
1527   cout << endl;
1528   for (Int_t i1=0; i1<fNTrackHits; i1++) printf("%8.4f", (*fChi2Smooth)[i1]);
1529   cout << endl;
1530   cout << "---------------------------------------------------" << endl;
1531
1532   // Get covariance matrix
1533   /* Not needed - covariance matrix is not interesting to anybody
1534   *fCovariance = *fWeight;
1535   if (fCovariance->Determinant() != 0) {
1536     //   fCovariance->Invert();
1537     Int_t ifail;
1538     mnvertLocal(&((*fCovariance)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1539   } else {
1540     AliWarning(" Determinant fCovariance=0:" );
1541   }
1542   */
1543 }
1544
1545   //__________________________________________________________________________
1546 void AliMUONTrackK::MSLine(Double_t dZ, Double_t x0)
1547 {
1548   // Adds multiple scattering in a thick layer for linear propagation
1549
1550   Double_t cosAlph = TMath::Cos((*fTrackPar)(2,0));
1551   Double_t tanAlph = TMath::Tan((*fTrackPar)(2,0));
1552   Double_t cosBeta = TMath::Cos((*fTrackPar)(3,0));
1553   Double_t sinBeta;
1554   sinBeta = TMath::Sin((*fTrackPar)(3,0));
1555   Double_t tanBeta = TMath::Tan((*fTrackPar)(3,0));
1556   Double_t momentum = 1/(*fTrackPar)(4,0);
1557   Double_t velo = 1; // relativistic velocity
1558   Double_t step = TMath::Abs(dZ/cosAlph/cosBeta); // step length
1559
1560   // Projected scattering angle
1561   Double_t theta0 = 0.0136/velo/momentum/TMath::Sqrt(x0)*(1+0.038*TMath::Log(step/x0)); 
1562   Double_t theta02 = theta0*theta0;
1563   Double_t dl2 = step*step/2*theta02;
1564   Double_t dl3 = dl2*step*2/3;
1565
1566   //Derivatives
1567   Double_t dYdT = 1/cosAlph;
1568   Double_t dYdB = 0; //(*fTrackPar)(2,0)*sinBeta/cosAlph;
1569   Double_t dXdT = tanAlph*tanBeta;
1570   //Double_t dXdB = (1+(*fTrackPar)(2,0)*tanAlph*sinBeta*sinBeta)/cosBeta;
1571   Double_t dXdB = 1/cosBeta;
1572   Double_t dAdT = 1/cosBeta;
1573   Double_t dAdB = 0; //(*fTrackPar)(2,0)*tanBeta;
1574
1575   // Get covariance matrix
1576   *fCovariance = *fWeight;
1577   if (fCovariance->Determinant() != 0) {
1578     //   fCovariance->Invert();
1579     Int_t ifail;
1580     mnvertLocal(&((*fCovariance)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1581   } else {
1582     AliWarning(" Determinant fCovariance=0:" );
1583   }
1584
1585   (*fCovariance)(0,0) += dl3*(dYdT*dYdT+dYdB*dYdB); // <yy>
1586   (*fCovariance)(1,1) += dl3*(dXdT*dXdT+dXdB*dXdB); // <xx>
1587   (*fCovariance)(2,2) += theta02*step*(dAdT*dAdT+dAdB*dAdB); // <aa>
1588   (*fCovariance)(3,3) += theta02*step; // <bb>
1589
1590   (*fCovariance)(0,1) += dl3*(dYdT*dXdT+dYdB*dXdB); // <yx>
1591   (*fCovariance)(1,0) = (*fCovariance)(0,1);
1592
1593   (*fCovariance)(0,2) += dl2*(dYdT*dAdT+dYdB*dAdB); // <ya>
1594   (*fCovariance)(2,0) = (*fCovariance)(0,2);
1595
1596   (*fCovariance)(0,3) += dl2*dYdB; // <yb>
1597   (*fCovariance)(3,0) = (*fCovariance)(0,3);
1598
1599   (*fCovariance)(1,2) += dl2*(-dXdT*dAdT+dXdB*dAdB); // <xa>
1600   (*fCovariance)(2,1) = (*fCovariance)(1,2);
1601
1602   (*fCovariance)(1,3) += dl2*dXdB; // <xb>
1603   (*fCovariance)(3,1) = (*fCovariance)(1,3);
1604
1605   (*fCovariance)(2,3) += theta02*step*dAdB; // <ab>
1606   (*fCovariance)(3,2) = (*fCovariance)(2,3);
1607
1608   // Get weight matrix
1609   *fWeight = *fCovariance;
1610   if (fWeight->Determinant() != 0) {
1611     //  fWeight->Invert();
1612     Int_t ifail;
1613     mnvertLocal(&((*fWeight)(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1614   } else {
1615     AliWarning(" Determinant fWeight=0:");
1616   }
1617 }
1618  
1619   //__________________________________________________________________________
1620 Bool_t AliMUONTrackK::Recover(void)
1621 {
1622   // Adds new failed track(s) which can be tried to be recovered
1623   Int_t nRecTracks;
1624   TClonesArray *trackPtr;
1625   AliMUONTrackK *trackK;
1626
1627   if (fgDebug > 0) cout << " ******** Enter Recover " << endl;
1628   trackPtr = fgTrackReconstructor->GetRecTracksPtr();
1629
1630   // Remove hit with the highest chi2
1631   Double_t chi2 = 0;
1632   if (fgDebug > 0) {
1633     for (Int_t i=0; i<fNTrackHits; i++) {
1634       chi2 = fChi2Smooth ? (*fChi2Smooth)[i] : (*fChi2Array)[i];
1635       printf("%10.4f", chi2);
1636     }
1637     printf("\n");
1638     for (Int_t i=0; i<fNTrackHits; i++) {
1639       printf("%10d", ((AliMUONHitForRec*)fTrackHitsPtr->UncheckedAt(i))->GetChamberNumber());
1640     }
1641     printf("\n");
1642   }
1643   Double_t chi2max = 0;
1644   Int_t imax = 0;
1645   for (Int_t i=0; i<fNTrackHits; i++) {
1646     chi2 = fChi2Smooth ? (*fChi2Smooth)[i] : (*fChi2Array)[i];
1647     if (chi2 < chi2max) continue;
1648     chi2max = chi2;
1649     imax = i;
1650   }
1651   //if (chi2max < 10) return kFALSE; // !!!
1652   //if (chi2max < 25) imax = fNTrackHits - 1;
1653   if (chi2max < 15) imax = fNTrackHits - 1; // discard the last point
1654   // Check if the outlier is not from the seed segment
1655   AliMUONHitForRec *skipHit = (AliMUONHitForRec*) fTrackHitsPtr->UncheckedAt(imax);
1656   if (skipHit == fStartSegment->GetHitForRec1() || skipHit == fStartSegment->GetHitForRec2()) {
1657     //DropBranches(fStartSegment); // drop all tracks with the same seed segment
1658     return kFALSE; // to be changed probably
1659   }
1660   
1661   // Make a copy of track hit collection
1662   TObjArray *hits = new TObjArray(*fTrackHitsPtr);
1663   Int_t imax0;
1664   imax0 = imax;
1665
1666   // Hits after the found one will be removed
1667   if (GetStation0() == 3 && skipHit->GetChamberNumber() > 7) {
1668     SortHits(1, fTrackHitsPtr); // unsort hits
1669     imax = fTrackHitsPtr->IndexOf(skipHit);
1670   }
1671   Int_t nTrackHits = fNTrackHits;
1672   for (Int_t i=imax+1; i<nTrackHits; i++) {
1673     AliMUONHitForRec *hit = (AliMUONHitForRec*) fTrackHitsPtr->UncheckedAt(i);
1674     fTrackHitsPtr->Remove(hit);
1675     hit->SetNTrackHits(hit->GetNTrackHits()-1); // unmark hit 
1676     fNTrackHits--;
1677   }
1678
1679   // Check if the track candidate doesn't exist yet
1680   if (ExistDouble()) { delete hits; return kFALSE; }
1681
1682   //DropBranches(imax0, hits); // drop branches downstream the discarded hit
1683   delete hits;
1684
1685   nRecTracks = fgTrackReconstructor->GetNRecTracks();
1686   skipHit = (AliMUONHitForRec*) ((*fTrackHitsPtr)[fNTrackHits-1]);
1687   // Remove all saved steps and smoother matrices after the skipped hit 
1688   RemoveMatrices(skipHit->GetZ());
1689
1690   //AZ(z->-z) if (skipHit->GetZ() > fStartSegment->GetHitForRec2()->GetZ() || !fNSteps) {
1691   if (TMath::Abs(skipHit->GetZ()) > TMath::Abs(fStartSegment->GetHitForRec2()->GetZ()) || !fNSteps) {
1692     // Propagation toward high Z or skipped hit next to segment - 
1693     // start track from segment 
1694     trackK = new ((*trackPtr)[nRecTracks]) AliMUONTrackK(fStartSegment); 
1695     fgTrackReconstructor->SetNRecTracks(nRecTracks+1);
1696     trackK->fRecover = 1;
1697     trackK->fSkipHit = skipHit;
1698     trackK->fNTrackHits = fNTrackHits;
1699     delete trackK->fTrackHitsPtr; // not efficient ?
1700     trackK->fTrackHitsPtr = new TObjArray(*fTrackHitsPtr);
1701     if (fgDebug > 0) cout << nRecTracks << " " << trackK->fRecover << endl;
1702     return kTRUE;
1703   } 
1704
1705   trackK = new ((*trackPtr)[nRecTracks]) AliMUONTrackK(NULL, NULL);
1706   *trackK = *this;
1707   fgTrackReconstructor->SetNRecTracks(nRecTracks+1);
1708   //AZ(z->-z) trackK->fTrackDir = -1;
1709   trackK->fTrackDir = 1;
1710   trackK->fRecover = 1;
1711   trackK->fSkipHit = skipHit;
1712   Int_t iD = trackK->fParFilter->Last()->GetUniqueID();
1713   if (iD > 1) { 
1714     trackK->fParFilter->Last()->SetUniqueID(iD-1);
1715     CreateMatrix(trackK->fParFilter); 
1716     iD = 1; 
1717     trackK->fParFilter->Last()->SetUniqueID(iD);
1718   }
1719   *((TMatrixD*)trackK->fParFilter->Last()) = *((TMatrixD*)fParExtrap->Last());
1720   *(trackK->fTrackPar) = *((TMatrixD*)trackK->fParFilter->Last());
1721   iD = trackK->fCovFilter->Last()->GetUniqueID();
1722   if (iD > 1) { 
1723     trackK->fCovFilter->Last()->SetUniqueID(iD-1);
1724     CreateMatrix(trackK->fCovFilter); 
1725     iD = 1; 
1726     trackK->fCovFilter->Last()->SetUniqueID(iD);
1727   }
1728   *((TMatrixD*)trackK->fCovFilter->Last()) = *((TMatrixD*)fCovExtrap->Last());
1729   *(trackK->fWeight) = *((TMatrixD*)trackK->fCovFilter->Last());
1730   if (trackK->fWeight->Determinant() != 0) {
1731     Int_t ifail;
1732     mnvertLocal(&((*(trackK->fWeight))(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1733   } else {
1734     AliWarning(" Determinant fWeight=0:");
1735   }
1736   trackK->fPosition = trackK->fPositionNew = (*fSteps)[fNSteps-1];
1737   trackK->fChi2 = 0;
1738   for (Int_t i=0; i<fNTrackHits-1; i++) trackK->fChi2 += (*fChi2Array)[i];
1739   if (fgDebug > 0) cout << nRecTracks << " " << trackK->fRecover << endl;
1740   return kTRUE;
1741 }
1742
1743   //__________________________________________________________________________
1744 void AliMUONTrackK::AddMatrices(AliMUONTrackK *trackK, Double_t dChi2, AliMUONHitForRec *hitAdd)
1745 {
1746   // Adds matrices for the smoother and keep Chi2 for the point
1747   // Track parameters
1748   //trackK->fParFilter->Last()->Print();
1749   Int_t iD = trackK->fParFilter->Last()->GetUniqueID();
1750   if (iD > 1) { 
1751     trackK->fParFilter->Last()->SetUniqueID(iD-1);
1752     CreateMatrix(trackK->fParFilter); 
1753     iD = 1; 
1754   }
1755   *((TMatrixD*)(trackK->fParFilter->Last())) = *(trackK->fTrackPar);
1756   trackK->fParFilter->Last()->SetUniqueID(iD);
1757   if (fgDebug > 1) {
1758     cout << " Add matrices" << " " << fPosition << " " << dChi2 << " " << fgHitForRec->IndexOf(hitAdd) << endl;
1759     //trackK->fTrackPar->Print();
1760     //trackK->fTrackParNew->Print();
1761     trackK->fParFilter->Last()->Print();
1762     cout << " Add matrices" << endl;
1763   }
1764   // Covariance
1765   *(trackK->fCovariance) = *(trackK->fWeight);
1766   if (trackK->fCovariance->Determinant() != 0) {
1767     Int_t ifail;
1768     mnvertLocal(&((*(trackK->fCovariance))(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1769   } else {
1770     AliWarning(" Determinant fCovariance=0:");
1771   }
1772   iD = trackK->fCovFilter->Last()->GetUniqueID();
1773   if (iD > 1) { 
1774     trackK->fCovFilter->Last()->SetUniqueID(iD-1);
1775     CreateMatrix(trackK->fCovFilter); 
1776     iD = 1; 
1777   }
1778   *((TMatrixD*)(trackK->fCovFilter->Last())) = *(trackK->fCovariance);
1779   trackK->fCovFilter->Last()->SetUniqueID(iD);
1780
1781   // Save Chi2-increment for point
1782   Int_t indx = trackK->fTrackHitsPtr->IndexOf(hitAdd);
1783   if (indx < 0) indx = fNTrackHits;
1784   if (trackK->fChi2Array->fN <= indx) trackK->fChi2Array->Set(indx+10); 
1785   trackK->fChi2Array->AddAt(dChi2,indx);
1786 }
1787
1788   //__________________________________________________________________________
1789 void AliMUONTrackK::CreateMatrix(TObjArray *objArray)
1790 {
1791   // Create new matrix and add it to TObjArray 
1792
1793   TMatrixD *matrix = (TMatrixD*) objArray->First();
1794   TMatrixD *tmp = new TMatrixD(*matrix);
1795   objArray->AddAtAndExpand(tmp,objArray->GetLast());
1796   //cout << " !!! " << tmp << " " << tmp->GetUniqueID() << " " << tmp->GetNoElements() << endl;
1797 }
1798
1799   //__________________________________________________________________________
1800 void AliMUONTrackK::RemoveMatrices(Double_t zEnd)
1801 {
1802   // Remove matrices (and saved steps) in the smoother part with abs(z) < abs(zEnd)
1803
1804   for (Int_t i=fNSteps-1; i>=0; i--) {
1805     if (fgDebug > 1) printf("%10.4f %10.4f \n", (*fSteps)[i], zEnd);
1806     if (TMath::Abs((*fSteps)[i]) > TMath::Abs(zEnd) - 0.01) break;
1807     RemoveMatrices(this);
1808   } // for (Int_t i=fNSteps-1;
1809 }
1810
1811   //__________________________________________________________________________
1812 void AliMUONTrackK::RemoveMatrices(AliMUONTrackK* trackK)
1813 {
1814   // Remove last saved matrices and steps in the smoother part 
1815
1816   trackK->fNSteps--;
1817   Int_t i = trackK->fNSteps;
1818
1819   Int_t id = 0;
1820   // Delete only matrices not shared by several tracks
1821   id = trackK->fParExtrap->Last()->GetUniqueID();
1822   if (id > 1) {
1823     trackK->fParExtrap->Last()->SetUniqueID(id-1);
1824     trackK->fParExtrap->RemoveAt(i);
1825   }
1826   else ((TMatrixD*)(trackK->fParExtrap->RemoveAt(i)))->Delete();
1827   id = fParFilter->Last()->GetUniqueID();
1828   if (id > 1) { 
1829     trackK->fParFilter->Last()->SetUniqueID(id-1);
1830     trackK->fParFilter->RemoveAt(i);
1831   }
1832   else ((TMatrixD*)(trackK->fParFilter->RemoveAt(i)))->Delete();
1833   id = trackK->fCovExtrap->Last()->GetUniqueID();
1834   if (id > 1) { 
1835     trackK->fCovExtrap->Last()->SetUniqueID(id-1);
1836     trackK->fCovExtrap->RemoveAt(i);
1837   }
1838   else ((TMatrixD*)(trackK->fCovExtrap->RemoveAt(i)))->Delete();
1839   id = trackK->fCovFilter->Last()->GetUniqueID();
1840   if (id > 1) { 
1841     trackK->fCovFilter->Last()->SetUniqueID(id-1);
1842     trackK->fCovFilter->RemoveAt(i);
1843   }
1844   else ((TMatrixD*)(trackK->fCovFilter->RemoveAt(i)))->Delete();
1845   id = trackK->fJacob->Last()->GetUniqueID();
1846   if (id > 1) { 
1847     trackK->fJacob->Last()->SetUniqueID(id-1);
1848     trackK->fJacob->RemoveAt(i);
1849   }
1850   else ((TMatrixD*)(trackK->fJacob->RemoveAt(i)))->Delete();
1851 }
1852
1853   //__________________________________________________________________________
1854 Bool_t AliMUONTrackK::Smooth(void)
1855 {
1856   // Apply smoother
1857   Int_t ihit = fNTrackHits - 1;
1858   AliMUONHitForRec *hit = (AliMUONHitForRec*) (*fTrackHitsPtr)[ihit];
1859   fChi2Smooth = new TArrayD(fNTrackHits);
1860   fChi2Smooth->Reset(-1);
1861   fChi2 = 0;
1862   fParSmooth = new TObjArray(15);
1863   fParSmooth->Clear();
1864
1865   if (fgDebug > 0) {
1866     cout << " ******** Enter Smooth " << endl;
1867     cout << (*fSteps)[fNSteps-1] << " " << fPosition << " " << fPositionNew << endl; 
1868     /*
1869     for (Int_t i=fNSteps-1; i>=0; i--) cout << (*fSteps)[i] << " ";
1870     cout << endl;
1871     for (Int_t i=fNSteps-1; i>=0; i--) {cout << i << " " << (*fSteps)[i]; ((TMatrixD*)fParFilter->UncheckedAt(i))->Print(); ((TMatrixD*)fParExtrap->UncheckedAt(i))->Print(); ((TMatrixD*)fJacob->UncheckedAt(i))->Print();}
1872     */
1873     for (Int_t i=ihit; i>=0; i--) cout << ((AliMUONHitForRec*)(*fTrackHitsPtr)[i])->GetZ() << " ";
1874     cout << endl;
1875   }
1876
1877   // Find last point corresponding to the last hit
1878   Int_t iLast = fNSteps - 1;
1879   for ( ; iLast>=0; iLast--) {
1880     //AZ(z->-z) if ((*fSteps)[iLast] + 0.01 > ((AliMUONHitForRec*)(*fTrackHitsPtr)[fNTrackHits-1])->GetZ()) break;
1881     if (TMath::Abs((*fSteps)[iLast]) + 0.01 > TMath::Abs(((AliMUONHitForRec*)(*fTrackHitsPtr)[fNTrackHits-1])->GetZ())) break;
1882   }
1883
1884   TMatrixD parSmooth = *((TMatrixD*)(fParFilter->UncheckedAt(iLast))); // last filtered = first smoothed
1885   //parSmooth.Dump();
1886   TMatrixD covSmooth = *((TMatrixD*)(fCovFilter->UncheckedAt(iLast))); // last filtered = first smoothed
1887   TMatrixD tmp=covSmooth, weight=covSmooth, gain = covSmooth;
1888   TMatrixD tmpPar = *fTrackPar;
1889   //parSmooth.Print(); ((TMatrixD*)(fParExtrap->Last()))->Print(); 
1890
1891   Bool_t found;
1892   Double_t chi2max = 0;
1893   for (Int_t i=iLast+1; i>0; i--) {
1894     if (i == iLast + 1) goto L33; // temporary fix
1895
1896     // Smoother gain matrix
1897     weight = *((TMatrixD*)(fCovExtrap->UncheckedAt(i)));
1898     if (weight.Determinant() != 0) {
1899       Int_t ifail;
1900       mnvertLocal(&(weight(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1901     } else {
1902       AliWarning(" Determinant weight=0:");
1903     }
1904     // Fk'Wkk+1
1905     tmp = TMatrixD(*((TMatrixD*)(fJacob->UncheckedAt(i))),TMatrixD::kTransposeMult,weight);
1906     gain = TMatrixD(*((TMatrixD*)(fCovFilter->UncheckedAt(i-1))),TMatrixD::kMult,tmp);
1907     //cout << (*fSteps)[i-1] << " " << (*fSteps)[i] << endl; gain.Print();
1908
1909     // Smoothed parameter vector
1910     //((TMatrixD*)(fParExtrap->UncheckedAt(i)))->Dump();
1911     parSmooth -= *((TMatrixD*)(fParExtrap->UncheckedAt(i)));
1912     tmpPar = *((TMatrixD*)(fParFilter->UncheckedAt(i-1)));
1913     tmpPar += TMatrixD(gain,TMatrixD::kMult,parSmooth);
1914     parSmooth = tmpPar;
1915
1916     // Smoothed covariance
1917     covSmooth -= *((TMatrixD*)(fCovExtrap->UncheckedAt(i)));
1918     weight = TMatrixD(TMatrixD::kTransposed,gain);
1919     tmp = TMatrixD(covSmooth,TMatrixD::kMult,weight);
1920     covSmooth = *((TMatrixD*)(fCovFilter->UncheckedAt(i-1)));
1921     covSmooth += TMatrixD(gain,TMatrixD::kMult,tmp);
1922
1923     // Check if there was a measurement at given z
1924     found = kFALSE;
1925     for ( ; ihit>=0; ihit--) { 
1926       hit = (AliMUONHitForRec*) (*fTrackHitsPtr)[ihit];
1927       if (TMath::Abs(hit->GetZ()-(*fSteps)[i-1]) < 0.1) { found = kTRUE; break; }
1928       //AZ(z->-z) else if (ihit < fNTrackHits-1 && hit->GetZ() > (*fSteps)[i-1]) { ihit++; break; }
1929       else if (ihit < fNTrackHits-1 && TMath::Abs(hit->GetZ()) > TMath::Abs((*fSteps)[i-1])) { ihit++; break; }
1930     }
1931     if (!found) continue; // no measurement - skip the rest
1932     else if (fgDebug > 1) cout << i << " " << ihit << " " << hit->GetZ() << endl;
1933     if (ihit == 0) continue; // the first hit - skip the rest
1934
1935 L33:
1936     // Smoothed residuals
1937     tmpPar = 0;
1938     tmpPar(0,0) = hit->GetBendingCoor() - parSmooth(0,0); // bending coordinate
1939     tmpPar(1,0) = hit->GetNonBendingCoor() - parSmooth(1,0); // non-bending coordinate
1940     if (fgDebug > 1) {
1941       cout << hit->GetBendingCoor() << " " << parSmooth(0,0) << " " << tmpPar(0,0) << endl;
1942       cout << hit->GetNonBendingCoor() << " " << parSmooth(1,0) << " " << tmpPar(1,0) << endl;
1943     }
1944     // Cov. matrix of smoothed residuals
1945     tmp = 0;
1946     tmp(0,0) = hit->GetBendingReso2() - covSmooth(0,0);
1947     tmp(1,1) = hit->GetNonBendingReso2() - covSmooth(1,1);
1948     tmp(0,1) = tmp(1,0) = -covSmooth(0,1);
1949     tmp(2,2) = tmp(3,3) = tmp(4,4) = 1;
1950
1951     // Calculate Chi2 of smoothed residuals
1952     if (tmp.Determinant() != 0) {
1953       Int_t ifail;
1954       mnvertLocal(&(tmp(0,0)), fgkSize,fgkSize,fgkSize,ifail);
1955     } else {
1956       AliWarning(" Determinant tmp=0:");
1957     }
1958     TMatrixD vector(tmp,TMatrixD::kMult,tmpPar);
1959     TMatrixD chi2(tmpPar,TMatrixD::kTransposeMult,vector);
1960     if (fgDebug > 1) chi2.Print();
1961     (*fChi2Smooth)[ihit] = chi2(0,0);
1962     if (chi2(0,0) > chi2max) chi2max = chi2(0,0); 
1963     fChi2 += chi2(0,0);
1964     if (chi2(0,0) < 0) { 
1965       chi2.Print(); cout << " chi2 < 0 " << i << " " << iLast << endl;
1966       //AliFatal("chi2 < 0.");
1967     }
1968     // Save smoothed parameters
1969     TMatrixD *par = new TMatrixD(parSmooth);
1970     fParSmooth->AddAtAndExpand(par, ihit);
1971
1972   } // for (Int_t i=iLast+1;
1973
1974   //if (chi2max > 16) { 
1975   //if (chi2max > 25) { 
1976   //if (chi2max > 50) { 
1977   //if (chi2max > 100) { 
1978   if (chi2max > fgkChi2max) { 
1979     //if (Recover()) DropBranches(); 
1980     //Recover();
1981     Outlier();
1982     return kFALSE; 
1983   }
1984   return kTRUE;
1985 }
1986  
1987   //__________________________________________________________________________
1988 void AliMUONTrackK::Outlier()
1989 {
1990   // Adds new track with removed hit having the highest chi2
1991
1992   if (fgDebug > 0) {
1993     cout << " ******** Enter Outlier " << endl;
1994     for (Int_t i=0; i<fNTrackHits; i++) printf("%10.4f", (*fChi2Smooth)[i]);
1995     printf("\n");
1996     for (Int_t i=0; i<fNTrackHits; i++) {
1997       printf("%10d", ((AliMUONHitForRec*)fTrackHitsPtr->UncheckedAt(i))->GetChamberNumber());
1998     }
1999     printf("\n");
2000   }
2001
2002   Double_t chi2max = 0;
2003   Int_t imax = 0;
2004   for (Int_t i=0; i<fNTrackHits; i++) {
2005     if ((*fChi2Smooth)[i] < chi2max) continue;
2006     chi2max = (*fChi2Smooth)[i];
2007     imax = i;
2008   }
2009   // Check if the outlier is not from the seed segment
2010   AliMUONHitForRec *hit = (AliMUONHitForRec*) fTrackHitsPtr->UncheckedAt(imax);
2011   if (hit == fStartSegment->GetHitForRec1() || hit == fStartSegment->GetHitForRec2()) return; // to be changed probably
2012
2013   // Check for missing station
2014   Int_t ok = 1;
2015   if (imax == 0) {
2016     if (((AliMUONHitForRec*)fTrackHitsPtr->UncheckedAt(1))->GetChamberNumber() < 8) ok--; 
2017   } else if (imax == fNTrackHits-1) {
2018     if (((AliMUONHitForRec*)fTrackHitsPtr->UncheckedAt(fNTrackHits-2))->GetChamberNumber() > 1) ok--; 
2019   } 
2020   else if (((AliMUONHitForRec*)fTrackHitsPtr->UncheckedAt(imax-1))->GetChamberNumber()/2 - ((AliMUONHitForRec*)fTrackHitsPtr->UncheckedAt(imax+1))->GetChamberNumber()/2 > 1) ok--;
2021   if (!ok) { Recover(); return; } // try to recover track
2022   //AZ if (!ok) { if (fgDebug >= 0) cout << imax << endl; DropBranches(imax, 0); return; } 
2023
2024   // Remove saved steps and smoother matrices after the outlier
2025   RemoveMatrices(hit->GetZ()); 
2026   
2027   // Check for possible double track candidates
2028   //if (ExistDouble(hit)) return;
2029
2030   TClonesArray *trackPtr = fgTrackReconstructor->GetRecTracksPtr();
2031   Int_t nRecTracks = fgTrackReconstructor->GetNRecTracks();
2032
2033   AliMUONTrackK *trackK = 0;
2034   if (!fNSteps || GetStation0() == 3 && hit->GetChamberNumber() > 7) {
2035     // start track from segment 
2036     trackK = new ((*trackPtr)[nRecTracks]) AliMUONTrackK(fStartSegment); 
2037     fgTrackReconstructor->SetNRecTracks(nRecTracks+1);
2038     trackK->fRecover = 2;
2039     trackK->fSkipHit = hit;
2040     trackK->fNTrackHits = fNTrackHits;
2041     delete trackK->fTrackHitsPtr; // not efficient ?
2042     trackK->fTrackHitsPtr = new TObjArray(*fTrackHitsPtr);
2043     if (GetStation0() == 3) trackK->SortHits(1, trackK->fTrackHitsPtr);
2044     if (fgDebug > 0) cout << nRecTracks << " Outlier" << endl;
2045     return;
2046   } 
2047   trackK = new ((*trackPtr)[nRecTracks]) AliMUONTrackK(NULL, NULL);
2048   *trackK = *this;
2049   fgTrackReconstructor->SetNRecTracks(nRecTracks+1);
2050   //AZ(z->-z) trackK->fTrackDir = -1;
2051   trackK->fTrackDir = 1;
2052   trackK->fRecover = 2;
2053   trackK->fSkipHit = hit;
2054   Int_t iD = trackK->fParFilter->Last()->GetUniqueID();
2055   if (iD > 1) { 
2056     trackK->fParFilter->Last()->SetUniqueID(iD-1);
2057     CreateMatrix(trackK->fParFilter); 
2058     iD = 1; 
2059     trackK->fParFilter->Last()->SetUniqueID(iD);
2060   }
2061   *((TMatrixD*)trackK->fParFilter->Last()) = *((TMatrixD*)fParExtrap->Last());
2062   *(trackK->fTrackPar) = *((TMatrixD*)trackK->fParFilter->Last());
2063   iD = trackK->fCovFilter->Last()->GetUniqueID();
2064   if (iD > 1) { 
2065     trackK->fCovFilter->Last()->SetUniqueID(iD-1);
2066     CreateMatrix(trackK->fCovFilter); 
2067     iD = 1; 
2068     trackK->fCovFilter->Last()->SetUniqueID(iD);
2069   }
2070   *((TMatrixD*)trackK->fCovFilter->Last()) = *((TMatrixD*)fCovExtrap->Last());
2071   *(trackK->fWeight) = *((TMatrixD*)trackK->fCovFilter->Last());
2072   if (trackK->fWeight->Determinant() != 0) {
2073     Int_t ifail;
2074     mnvertLocal(&((*(trackK->fWeight))(0,0)), fgkSize,fgkSize,fgkSize,ifail);
2075   } else {
2076     AliWarning(" Determinant fWeight=0:");
2077   }
2078   trackK->fPosition = trackK->fPositionNew = (*fSteps)[fNSteps-1];
2079   trackK->fChi2 = 0;
2080   for (Int_t i=0; i<fNTrackHits-1; i++) trackK->fChi2 += (*fChi2Array)[i];
2081   if (fgDebug > 0) cout << nRecTracks << " Outlier " << trackK->fChi2 << endl;
2082 }
2083
2084   //__________________________________________________________________________
2085 Double_t AliMUONTrackK::GetChi2PerPoint(Int_t iPoint) const
2086 {
2087   // Return Chi2 at point
2088   return fChi2Smooth ? (*fChi2Smooth)[iPoint] : (*fChi2Array)[iPoint];
2089   //return 0.;
2090 }
2091
2092   //__________________________________________________________________________
2093 void AliMUONTrackK::Print(FILE *lun) const
2094 {
2095   // Print out track information
2096
2097   Int_t flag = 1;
2098   AliMUONHitForRec *hit = 0; 
2099   if (fgTrackReconstructor->GetRecTrackRefHits()) { 
2100     // from track ref. hits
2101     for (Int_t j=0; j<fNTrackHits; j++) {
2102       hit = (AliMUONHitForRec*) fTrackHitsPtr->UncheckedAt(j);
2103       if (hit->GetTTRTrack() > 1) { flag = 0; break; }
2104     }
2105     for (Int_t j=0; j<fNTrackHits; j++) {
2106       printf("%10.4f", GetChi2PerPoint(j));
2107       if (GetChi2PerPoint(j) > -0.1) {
2108         hit = (AliMUONHitForRec*) fTrackHitsPtr->UncheckedAt(j);
2109         fprintf(lun,"%3d %3d %10.4f", gAlice->GetEvNumber(), hit->GetChamberNumber(), GetChi2PerPoint(j));
2110         fprintf(lun, "%3d %3d %3d \n", hit->GetTrackRefSignal(), hit->GetTTRTrack(), flag);
2111       }
2112     }
2113     printf("\n");
2114   } else {
2115     // from raw clusters
2116     AliMUONRawCluster *clus = 0;
2117     TClonesArray *rawclusters = 0;
2118     for (Int_t i1=0; i1<fNTrackHits; i1++) {
2119       hit =  (AliMUONHitForRec*) ((*fTrackHitsPtr)[i1]);
2120       rawclusters = fgTrackReconstructor->GetMUONData()->RawClusters(hit->GetChamberNumber());
2121       clus = (AliMUONRawCluster*) rawclusters->UncheckedAt(hit->GetHitNumber());
2122       if (TMath::Abs(clus->GetTrack(1)-1) < 2) {
2123         if (clus->GetTrack(2)) flag = 2;
2124         continue;
2125       }
2126       if (clus->GetTrack(2) && TMath::Abs(clus->GetTrack(2)-1) < 2) {
2127         flag = 3;
2128         continue;
2129       }
2130       flag = 0;
2131       break;
2132     }
2133     Int_t sig[2]={1,1}, tid[2]={0};
2134     for (Int_t i1=0; i1<fNTrackHits; i1++) {
2135       if (GetChi2PerPoint(i1) < -0.1) continue;
2136       hit =  (AliMUONHitForRec*) ((*fTrackHitsPtr)[i1]);
2137       rawclusters = fgTrackReconstructor->GetMUONData()->RawClusters(hit->GetChamberNumber());
2138       clus = (AliMUONRawCluster*) rawclusters->UncheckedAt(hit->GetHitNumber());
2139       for (Int_t j=0; j<2; j++) {
2140         tid[j] = clus->GetTrack(j+1) - 1;
2141         if (clus->GetTrack(j+1) < 0) { sig[j] = 0; tid[j] = 999; }
2142       }
2143       fprintf(lun,"%3d %3d %10.4f", gAlice->GetEvNumber(), hit->GetChamberNumber(), GetChi2PerPoint(i1));
2144       if (!(clus->GetTrack(2))) fprintf(lun, "%3d %3d", sig[0], tid[0]); // simple cluster
2145       else { // track overlap
2146         fprintf(lun, "%3d %3d", TMath::Max(sig[0],sig[1]), TMath::Min(tid[0],tid[1]));
2147         //if (tid[0] < 2) flag *= 2;
2148         //else if (tid[1] < 2) flag *= 3;
2149       }
2150       fprintf (lun, "%3d \n", flag); 
2151     }
2152   }
2153 }
2154
2155   //__________________________________________________________________________
2156 void AliMUONTrackK::DropBranches(Int_t imax, TObjArray *hits)
2157 {
2158   // Drop branches downstream of the skipped hit 
2159   Int_t nRecTracks;
2160   TClonesArray *trackPtr;
2161   AliMUONTrackK *trackK;
2162
2163   trackPtr = fgTrackReconstructor->GetRecTracksPtr();
2164   nRecTracks = fgTrackReconstructor->GetNRecTracks();
2165   Int_t icand = trackPtr->IndexOf(this);
2166   if (!hits) hits = fTrackHitsPtr; 
2167
2168   // Check if the track candidate doesn't exist yet
2169   for (Int_t i=icand+1; i<nRecTracks; i++) {
2170     trackK = (AliMUONTrackK*) ((*trackPtr)[i]);
2171     if (trackK->fNTrackHits == 2 && trackK->GetRecover() == 0) continue;
2172     if (trackK->GetRecover() < 0) continue;
2173
2174     if (trackK->fNTrackHits >= imax + 1) {
2175       for (Int_t j=0; j<=imax; j++) {
2176         //if (j != fNTrackHits-1 && (*trackK->fTrackHitsPtr)[j] != (*fTrackHitsPtr)[j]) break;
2177         if ((*trackK->fTrackHitsPtr)[j] != (*hits)[j]) break;
2178         if (j == imax) {
2179           if (hits != fTrackHitsPtr) {
2180             // Drop all branches downstream the hit (for Recover)
2181             trackK->SetRecover(-1);
2182             if (fgDebug >= 0 )cout << " Recover " << i << endl;
2183             continue;
2184           }
2185           // Check if the removal of the hit breaks the track
2186           Int_t ok = 1;
2187           if (imax == 0) {
2188             if (((AliMUONHitForRec*)trackK->fTrackHitsPtr->UncheckedAt(1))->GetChamberNumber() < 8) ok--; }
2189           else if (imax == trackK->fNTrackHits-1) continue;
2190             // else if (imax == trackK->fNTrackHits-1) {
2191             //if (((AliMUONHitForRec*)trackK->fTrackHitsPtr->UncheckedAt(trackK->fNTrackHits-2))->GetChamberNumber() > 1) ok--; 
2192             //} 
2193           else if (((AliMUONHitForRec*)trackK->fTrackHitsPtr->UncheckedAt(imax-1))->GetChamberNumber()/2 - ((AliMUONHitForRec*)trackK->fTrackHitsPtr->UncheckedAt(imax+1))->GetChamberNumber()/2 > 1) ok--;
2194           if (!ok) trackK->SetRecover(-1);
2195         }
2196       } // for (Int_t j=0;
2197     }
2198   } // for (Int_t i=0;
2199 }
2200
2201   //__________________________________________________________________________
2202 void AliMUONTrackK::DropBranches(AliMUONSegment *segment)
2203 {
2204   // Drop all candidates with the same seed segment
2205   Int_t nRecTracks;
2206   TClonesArray *trackPtr;
2207   AliMUONTrackK *trackK;
2208
2209   trackPtr = fgTrackReconstructor->GetRecTracksPtr();
2210   nRecTracks = fgTrackReconstructor->GetNRecTracks();
2211   Int_t icand = trackPtr->IndexOf(this);
2212
2213   for (Int_t i=icand+1; i<nRecTracks; i++) {
2214     trackK = (AliMUONTrackK*) ((*trackPtr)[i]);
2215     if (trackK->fNTrackHits == 2 && trackK->GetRecover() == 0) continue;
2216     if (trackK->GetRecover() < 0) continue;
2217     if (trackK->fStartSegment == segment) trackK->SetRecover(-1);
2218   }
2219   if (fgDebug >= 0) cout << " Drop segment " << endl; 
2220 }
2221
2222   //__________________________________________________________________________
2223 AliMUONHitForRec* AliMUONTrackK::GetHitLastOk(void)
2224 {
2225   // Return the hit where track stopped
2226
2227   if (!fNSteps) return (AliMUONHitForRec*)((*fTrackHitsPtr)[1]);
2228   return fSkipHit;
2229 }
2230
2231   //__________________________________________________________________________
2232 Int_t AliMUONTrackK::GetStation0(void)
2233 {
2234   // Return seed station number
2235   return fStartSegment->GetHitForRec1()->GetChamberNumber() / 2;
2236 }
2237
2238   //__________________________________________________________________________
2239 Bool_t AliMUONTrackK::ExistDouble(AliMUONHitForRec *hit)
2240 {
2241   // Check if the track will make a double after outlier removal
2242
2243   TClonesArray *trackPtr = fgTrackReconstructor->GetRecTracksPtr();
2244   Int_t nRecTracks = fgTrackReconstructor->GetNRecTracks();
2245   TObjArray *hitArray = new TObjArray(*fTrackHitsPtr);
2246   TObjArray *hitArray1 = new TObjArray(*hitArray);
2247   hitArray1->Remove(hit);
2248   hitArray1->Compress();
2249
2250   Bool_t same = kFALSE;
2251   for (Int_t i=0; i<nRecTracks; i++) {
2252     AliMUONTrackK *trackK = (AliMUONTrackK*) ((*trackPtr)[i]);
2253     if (trackK->fNTrackHits == 2 && trackK->GetRecover() == 0) continue;
2254     if (trackK == this) continue;
2255     if (trackK->fNTrackHits == fNTrackHits || trackK->fNTrackHits == fNTrackHits-1) {
2256       TObjArray *hits = new TObjArray(*trackK->fTrackHitsPtr);
2257       same = kTRUE;
2258       if (trackK->fNTrackHits == fNTrackHits) {
2259         for (Int_t j=0; j<fNTrackHits; j++) {
2260           if (hits->UncheckedAt(j) != hitArray->UncheckedAt(j)) { same = kFALSE; break; }
2261         }
2262         if (same) { delete hits; break; }
2263         if (trackK->fSkipHit) {
2264           TObjArray *hits1 = new TObjArray(*hits);
2265           if (hits1->Remove(trackK->fSkipHit) > 0) {
2266             hits1->Compress();
2267             same = kTRUE;
2268             for (Int_t j=0; j<fNTrackHits-1; j++) {
2269               if (hits1->UncheckedAt(j) != hitArray1->UncheckedAt(j)) { same = kFALSE; break; }
2270             }
2271             if (same) { delete hits1; break; }
2272           }
2273           delete hits1;
2274         }
2275       } else {
2276         // Check with removed outlier
2277         same = kTRUE;
2278         for (Int_t j=0; j<fNTrackHits-1; j++) {
2279           if (hits->UncheckedAt(j) != hitArray1->UncheckedAt(j)) { same = kFALSE; break; }
2280         }
2281         if (same) { delete hits; break; }
2282       } 
2283       delete hits;
2284     }
2285   } // for (Int_t i=0; i<nRecTracks;
2286   delete hitArray; delete hitArray1;
2287   if (same && fgDebug >= 0) cout << " Same" << endl;
2288   return same;
2289 }
2290
2291   //__________________________________________________________________________
2292 Bool_t AliMUONTrackK::ExistDouble(void)
2293 {
2294   // Check if the track will make a double after recovery
2295
2296   TClonesArray *trackPtr = fgTrackReconstructor->GetRecTracksPtr();
2297   Int_t nRecTracks = fgTrackReconstructor->GetNRecTracks();
2298
2299   TObjArray *hitArray = new TObjArray(*fTrackHitsPtr);
2300   if (GetStation0() == 3) SortHits(0, hitArray); // sort
2301   //if (GetStation0() == 3) SortHits(1, hitArray); // unsort
2302
2303   Bool_t same = kFALSE;
2304   for (Int_t i=0; i<nRecTracks; i++) {
2305     AliMUONTrackK *trackK = (AliMUONTrackK*) ((*trackPtr)[i]);
2306     if (trackK->fNTrackHits == 2 && trackK->GetRecover() == 0) continue;
2307     if (trackK == this) continue;
2308     //AZ if (trackK->GetRecover() < 0) continue; //
2309     if (trackK->fNTrackHits >= fNTrackHits) {
2310       TObjArray *hits = new TObjArray(*trackK->fTrackHitsPtr);
2311       if (trackK->GetStation0() == 3) SortHits(0, hits); // sort
2312       //if (trackK->GetStation0() == 3) SortHits(1, hits); // unsort
2313       for (Int_t j=0; j<fNTrackHits; j++) {
2314         //cout << fNTrackHits << " " << i << " " << j << " " << (*hitArray)[j] << " " << (*hits)[j] << " " << trackK->fSkipHit << endl;
2315         if (j != fNTrackHits-1 && (*hitArray)[j] != (*hits)[j]) break; 
2316         if (j == fNTrackHits-1) {
2317           if (trackK->fSkipHit && TMath::Abs(((AliMUONHitForRec*)((*hitArray)[j]))->GetZ()-trackK->fSkipHit->GetZ()) < 0.5) same = kTRUE; 
2318           //if (trackK->fNTrackHits > fNTrackHits && 
2319           //if (trackK->fSkipHit) cout << ((AliMUONHitForRec*)((*hitArray)[j]))->GetZ() << " " << trackK->fSkipHit->GetZ() << endl;
2320         }
2321       } // for (Int_t j=0;
2322       delete hits;
2323       if (same) break; 
2324     }
2325   } // for (Int_t i=0;
2326   delete hitArray;
2327   return same;
2328 }