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