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