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