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