5a140572a995ad737981bfe6bbd3ad9bf7655557
[u/mrichter/AliRoot.git] / MUON / AliMUONTrack.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 ///////////////////////////////////////////////////
19 //
20 // Reconstructed track
21 // in
22 // ALICE
23 // dimuon
24 // spectrometer
25 //
26 ///////////////////////////////////////////////////
27
28 #include <stdlib.h> // for exit()
29 #include <Riostream.h>
30 #include <TMatrixD.h>
31
32 #include "AliMUONTrack.h"
33
34 #include "AliMUONTrackParam.h" 
35 #include "AliMUONHitForRec.h" 
36 #include "AliMUONConstants.h"
37 #include "AliMUONTrackExtrap.h" 
38
39 #include "AliLog.h"
40
41 #include <TMath.h>
42
43 /// \cond CLASSIMP
44 ClassImp(AliMUONTrack) // Class implementation in ROOT context
45 /// \endcond
46
47 const Double_t AliMUONTrack::fgkMaxTrackingDistanceBending    = 2.;
48 const Double_t AliMUONTrack::fgkMaxTrackingDistanceNonBending = 2.;
49
50 //__________________________________________________________________________
51 AliMUONTrack::AliMUONTrack()
52   : TObject(),
53     fTrackParamAtVertex(),
54     fTrackParamAtHit(0x0),
55     fHitForRecAtHit(0x0),
56     fNTrackHits(0),
57     fExtrapTrackParam(),
58     fFitWithVertex(kFALSE),
59     fVertex(0x0),
60     fFitFMin(-1.),
61     fMatchTrigger(kFALSE),
62     fChi2MatchTrigger(0.),
63     fTrackID(0)
64 {
65   /// Default constructor
66 }
67
68   //__________________________________________________________________________
69 AliMUONTrack::AliMUONTrack(AliMUONHitForRec* hitForRec1, AliMUONHitForRec* hitForRec2)
70   : TObject(),
71     fTrackParamAtVertex(),
72     fTrackParamAtHit(0x0),
73     fHitForRecAtHit(0x0),
74     fNTrackHits(0),
75     fExtrapTrackParam(),
76     fFitWithVertex(kFALSE),
77     fVertex(0x0),
78     fFitFMin(-1.),
79     fMatchTrigger(kFALSE),
80     fChi2MatchTrigger(0.),
81     fTrackID(0)
82 {
83   /// Constructor from thw hitForRec's
84
85   fTrackParamAtHit = new TClonesArray("AliMUONTrackParam",10);
86   fHitForRecAtHit = new TClonesArray("AliMUONHitForRec",10);
87   
88   if (!hitForRec1) return; //AZ
89   
90   // Add hits to the track
91   AddTrackParamAtHit(0,hitForRec1);
92   AddTrackParamAtHit(0,hitForRec2);
93   
94   // sort TrackParamAtHit according to increasing -Z
95   fTrackParamAtHit->Sort();
96   
97   // Set track parameters at first track hit
98   AliMUONTrackParam* trackParamAtFirstHit = (AliMUONTrackParam*) fTrackParamAtHit->First();
99   AliMUONHitForRec* firstHit = trackParamAtFirstHit->GetHitForRecPtr();
100   AliMUONHitForRec* lastHit = ((AliMUONTrackParam*) fTrackParamAtHit->Last())->GetHitForRecPtr();
101   Double_t dZ = firstHit->GetZ() - lastHit->GetZ();
102   // Non bending plane
103   Double_t nonBendingCoor = firstHit->GetNonBendingCoor();
104   trackParamAtFirstHit->SetNonBendingCoor(nonBendingCoor);
105   trackParamAtFirstHit->SetNonBendingSlope((nonBendingCoor - lastHit->GetNonBendingCoor()) / dZ);
106   // Bending plane
107   Double_t bendingCoor = firstHit->GetBendingCoor();
108   trackParamAtFirstHit->SetBendingCoor(bendingCoor);
109   Double_t bendingSlope = (bendingCoor - lastHit->GetBendingCoor()) / dZ;
110   trackParamAtFirstHit->SetBendingSlope(bendingSlope);
111   // Inverse bending momentum
112   Double_t bendingImpact = bendingCoor - firstHit->GetZ() * bendingSlope;
113   Double_t inverseBendingMomentum = 1. / AliMUONTrackExtrap::GetBendingMomentumFromImpactParam(bendingImpact);
114   trackParamAtFirstHit->SetInverseBendingMomentum(inverseBendingMomentum);
115   
116   // Evaluate covariances
117   TMatrixD *paramCov = trackParamAtFirstHit->GetCovariances();
118   (*paramCov) = 0;
119   // Non bending plane
120   (*paramCov)(0,0) = firstHit->GetNonBendingReso2();
121   (*paramCov)(0,1) = firstHit->GetNonBendingReso2() / dZ;
122   (*paramCov)(1,0) = (*paramCov)(0,1);
123   (*paramCov)(1,1) = ( firstHit->GetNonBendingReso2() + lastHit->GetNonBendingReso2() ) / dZ / dZ;
124   // Bending plane
125   (*paramCov)(2,2) = firstHit->GetBendingReso2();
126   (*paramCov)(2,3) = firstHit->GetBendingReso2() / dZ;
127   (*paramCov)(3,2) = (*paramCov)(2,3);
128   (*paramCov)(3,3) = ( firstHit->GetBendingReso2() + lastHit->GetBendingReso2() ) / dZ / dZ;
129   // Inverse bending momentum (50% error)
130   (*paramCov)(4,4) = 0.5*inverseBendingMomentum * 0.5*inverseBendingMomentum;
131   
132 }
133
134   //__________________________________________________________________________
135 AliMUONTrack::~AliMUONTrack()
136 {
137   /// Destructor
138   if (fTrackParamAtHit) {
139     // delete the TClonesArray of pointers to TrackParam
140     delete fTrackParamAtHit;
141     fTrackParamAtHit = 0x0;
142   }
143
144   if (fHitForRecAtHit) {
145     // delete the TClonesArray of pointers to HitForRec
146     delete fHitForRecAtHit;
147     fHitForRecAtHit = 0x0;
148   }
149   
150   if (fVertex) {
151     // delete the vertex used during the tracking procedure
152     delete fVertex;
153     fVertex = 0x0;
154   }
155 }
156
157   //__________________________________________________________________________
158 AliMUONTrack::AliMUONTrack (const AliMUONTrack& theMUONTrack)
159   : TObject(theMUONTrack),
160     fTrackParamAtVertex(theMUONTrack.fTrackParamAtVertex),
161     fTrackParamAtHit(0x0),
162     fHitForRecAtHit(0x0),
163     fNTrackHits(theMUONTrack.fNTrackHits),
164     fExtrapTrackParam(theMUONTrack.fExtrapTrackParam),
165     fFitWithVertex(theMUONTrack.fFitWithVertex),
166     fVertex(0x0),
167     fFitFMin(theMUONTrack.fFitFMin),
168     fMatchTrigger(theMUONTrack.fMatchTrigger),
169     fChi2MatchTrigger(theMUONTrack.fChi2MatchTrigger),
170     fTrackID(theMUONTrack.fTrackID)
171 {
172   ///copy constructor
173   Int_t maxIndex = 0;
174   
175   // necessary to make a copy of the objects and not only the pointers in TClonesArray.
176   if (theMUONTrack.fTrackParamAtHit) {
177     maxIndex = (theMUONTrack.fTrackParamAtHit)->GetEntriesFast();
178     fTrackParamAtHit = new TClonesArray("AliMUONTrackParam",maxIndex);
179     for (Int_t index = 0; index < maxIndex; index++) {
180       new ((*fTrackParamAtHit)[index]) AliMUONTrackParam(*(AliMUONTrackParam*)theMUONTrack.fTrackParamAtHit->At(index));
181     }
182   }
183   
184   // necessary to make a copy of the objects and not only the pointers in TClonesArray.
185   if (theMUONTrack.fHitForRecAtHit) {
186     maxIndex = (theMUONTrack.fHitForRecAtHit)->GetEntriesFast();
187     fHitForRecAtHit = new TClonesArray("AliMUONHitForRec",maxIndex);
188     for (Int_t index = 0; index < maxIndex; index++) {
189       new ((*fHitForRecAtHit)[index]) AliMUONHitForRec(*(AliMUONHitForRec*)theMUONTrack.fHitForRecAtHit->At(index));
190     }
191   }
192   
193   // copy vertex used during the tracking procedure if any
194   if (theMUONTrack.fVertex) fVertex = new AliMUONHitForRec(*(theMUONTrack.fVertex));
195   
196 }
197
198   //__________________________________________________________________________
199 AliMUONTrack & AliMUONTrack::operator=(const AliMUONTrack& theMUONTrack)
200 {
201   /// Asignment operator
202   // check assignement to self
203   if (this == &theMUONTrack)
204     return *this;
205
206   // base class assignement
207   TObject::operator=(theMUONTrack);
208
209   fTrackParamAtVertex = theMUONTrack.fTrackParamAtVertex;
210
211   Int_t maxIndex = 0;
212   
213   // necessary to make a copy of the objects and not only the pointers in TClonesArray.
214   if (theMUONTrack.fTrackParamAtHit) {
215     if (fTrackParamAtHit) fTrackParamAtHit->Clear();
216     else fTrackParamAtHit = new TClonesArray("AliMUONTrackParam",10);
217     maxIndex = (theMUONTrack.fTrackParamAtHit)->GetEntriesFast();
218     for (Int_t index = 0; index < maxIndex; index++) {
219       new ((*fTrackParamAtHit)[fTrackParamAtHit->GetEntriesFast()])
220         AliMUONTrackParam(*(AliMUONTrackParam*)(theMUONTrack.fTrackParamAtHit)->At(index));
221     }
222   } else if (fTrackParamAtHit) {
223     delete fTrackParamAtHit;
224     fTrackParamAtHit = 0x0;
225   }
226
227   // necessary to make a copy of the objects and not only the pointers in TClonesArray.
228   if (theMUONTrack.fHitForRecAtHit) {
229     if (fHitForRecAtHit) fHitForRecAtHit->Clear();
230     else fHitForRecAtHit = new TClonesArray("AliMUONHitForRec",10);
231     maxIndex = (theMUONTrack.fHitForRecAtHit)->GetEntriesFast();
232     for (Int_t index = 0; index < maxIndex; index++) {
233       new ((*fHitForRecAtHit)[fHitForRecAtHit->GetEntriesFast()])
234         AliMUONHitForRec(*(AliMUONHitForRec*)(theMUONTrack.fHitForRecAtHit)->At(index));
235     }
236   } else if (fHitForRecAtHit) {
237     delete fHitForRecAtHit;
238     fHitForRecAtHit = 0x0;
239   }
240   
241   // copy vertex used during the tracking procedure if any.
242   if (theMUONTrack.fVertex) {
243     if (fVertex) *fVertex = *(theMUONTrack.fVertex);
244     else fVertex = new AliMUONHitForRec(*(theMUONTrack.fVertex));
245   } else if (fVertex) {
246     delete fVertex;
247     fVertex = 0x0;
248   }
249   
250   fExtrapTrackParam = theMUONTrack.fExtrapTrackParam;
251   
252   fNTrackHits         =  theMUONTrack.fNTrackHits;
253   fFitWithVertex      =  theMUONTrack.fFitWithVertex;
254   fFitFMin            =  theMUONTrack.fFitFMin;
255   fMatchTrigger       =  theMUONTrack.fMatchTrigger;
256   fChi2MatchTrigger   =  theMUONTrack.fChi2MatchTrigger;
257   fTrackID            =  theMUONTrack.fTrackID;
258
259   return *this;
260 }
261
262   //__________________________________________________________________________
263 void AliMUONTrack::AddTrackParamAtHit(AliMUONTrackParam *trackParam, AliMUONHitForRec *hitForRec) 
264 {
265   /// Add TrackParamAtHit if "trackParam" != NULL
266   /// else create empty TrackParamAtHit and set the z position to the one of "hitForRec" if any
267   /// Update link to HitForRec if "hitForRec" != NULL
268   if (!fTrackParamAtHit) {
269     fTrackParamAtHit = new TClonesArray("AliMUONTrackParam",10);  
270     fNTrackHits = 0;
271   }
272   AliMUONTrackParam* trackParamAtHit;
273   if (trackParam) {
274     trackParamAtHit = new ((*fTrackParamAtHit)[fNTrackHits]) AliMUONTrackParam(*trackParam);
275     if (hitForRec) {
276       if (hitForRec->GetZ() != trackParam->GetZ())
277         AliWarning("Added track parameters at a different z position than the one of the attached hit");
278     }
279   } else {
280     trackParamAtHit = new ((*fTrackParamAtHit)[fNTrackHits]) AliMUONTrackParam();
281     if (hitForRec) ((AliMUONTrackParam*) fTrackParamAtHit->UncheckedAt(fNTrackHits))->SetZ(hitForRec->GetZ());
282   }
283   if (hitForRec) trackParamAtHit->SetHitForRecPtr(hitForRec);
284   fNTrackHits++;
285 }
286
287   //__________________________________________________________________________
288 void AliMUONTrack::AddHitForRecAtHit(const AliMUONHitForRec *hitForRec) 
289 {
290   /// Add hitForRec to the array of hitForRec at hit
291   if (!fHitForRecAtHit)
292     fHitForRecAtHit = new TClonesArray("AliMUONHitForRec",10); 
293   
294   if (!hitForRec)
295     AliFatal("AliMUONTrack::AddHitForRecAtHit: hitForRec == NULL");
296   
297   new ((*fHitForRecAtHit)[fHitForRecAtHit->GetEntriesFast()]) AliMUONHitForRec(*hitForRec);
298 }
299
300   //__________________________________________________________________________
301 void AliMUONTrack::SetVertex(AliMUONHitForRec* vertex)
302 {
303   /// Set the vertex used during the tracking procedure
304   if (!fVertex) fVertex = new AliMUONHitForRec(*vertex);
305   else *fVertex = *vertex;
306 }
307
308   //__________________________________________________________________________
309 Int_t AliMUONTrack::HitsInCommon(AliMUONTrack* track) const
310 {
311   /// Returns the number of hits in common between the current track ("this")
312   /// and the track pointed to by "track".
313   Int_t hitsInCommon = 0;
314   AliMUONTrackParam *trackParamAtHit1, *trackParamAtHit2;
315   // Loop over hits of first track
316   trackParamAtHit1 = (AliMUONTrackParam*) this->fTrackParamAtHit->First();
317   while (trackParamAtHit1) {
318     // Loop over hits of second track
319     trackParamAtHit2 = (AliMUONTrackParam*) track->fTrackParamAtHit->First();
320     while (trackParamAtHit2) {
321       // Increment "hitsInCommon" if both TrackParamAtHits point to the same HitForRec
322       if ((trackParamAtHit1->GetHitForRecPtr()) == (trackParamAtHit2->GetHitForRecPtr())) {
323         hitsInCommon++;
324         break;
325       }
326       trackParamAtHit2 = (AliMUONTrackParam*) track->fTrackParamAtHit->After(trackParamAtHit2);
327     } // trackParamAtHit2
328     trackParamAtHit1 = (AliMUONTrackParam*) this->fTrackParamAtHit->After(trackParamAtHit1);
329   } // trackParamAtHit1
330   return hitsInCommon;
331 }
332
333   //__________________________________________________________________________
334 Bool_t* AliMUONTrack::CompatibleTrack(AliMUONTrack * track, Double_t sigma2Cut) const
335 {
336   /// Return kTRUE/kFALSE for each chamber if hit is compatible or not 
337   TClonesArray *hitArray, *thisHitArray;
338   AliMUONHitForRec *hit, *thisHit;
339   Int_t chamberNumber;
340   Float_t deltaZ;
341   Float_t deltaZMax = 1.; // 1 cm
342   Float_t chi2 = 0;
343   Bool_t *nCompHit = new Bool_t[AliMUONConstants::NTrackingCh()]; 
344
345   for ( Int_t ch = 0; ch < AliMUONConstants::NTrackingCh(); ch++) {
346     nCompHit[ch] = kFALSE;
347   }
348
349   thisHitArray = this->GetHitForRecAtHit();
350
351   hitArray =  track->GetHitForRecAtHit();
352
353   for (Int_t iHthis = 0; iHthis < thisHitArray->GetEntriesFast(); iHthis++) {
354     thisHit = (AliMUONHitForRec*) thisHitArray->At(iHthis);
355     chamberNumber = thisHit->GetChamberNumber();
356     if (chamberNumber < 0 || chamberNumber > AliMUONConstants::NTrackingCh()) continue; 
357     nCompHit[chamberNumber] = kFALSE;
358     for (Int_t iH = 0; iH < hitArray->GetEntriesFast(); iH++) {
359       hit = (AliMUONHitForRec*) hitArray->At(iH);
360       deltaZ = TMath::Abs(thisHit->GetZ() - hit->GetZ());
361       chi2 = thisHit->NormalizedChi2WithHitForRec(hit,sigma2Cut); // set cut to 4 sigmas
362       if (chi2 < 3. && deltaZ < deltaZMax) {
363         nCompHit[chamberNumber] = kTRUE;
364         break;
365       }
366     }  
367   }
368   
369   return nCompHit;
370 }
371
372   //__________________________________________________________________________
373 Double_t AliMUONTrack::TryOneHitForRec(AliMUONHitForRec* hitForRec)
374 {
375 /// Test the compatibility between the track and the hitForRec:
376 /// return the corresponding Chi2
377   
378   // Get track parameters and their covariances at the z position of hitForRec
379   AliMUONTrackParam extrapTrackParam(fExtrapTrackParam);
380   AliMUONTrackExtrap::ExtrapToZCov(&extrapTrackParam, hitForRec->GetZ());
381   
382   // Set differences between trackParam and hitForRec in the bending and non bending directions
383   TMatrixD dPos(2,1);
384   dPos(0,0) = hitForRec->GetNonBendingCoor() - extrapTrackParam.GetNonBendingCoor();
385   dPos(1,0) = hitForRec->GetBendingCoor() - extrapTrackParam.GetBendingCoor();
386   
387   // quick test of hitForRec compatibility within a wide road of x*y = 10*1 cm2 to save computing time
388   if (TMath::Abs(dPos(0,0)) > fgkMaxTrackingDistanceNonBending ||
389       TMath::Abs(dPos(1,0)) > fgkMaxTrackingDistanceBending) return 1.e10;
390   
391   // Set the error matrix from trackParam covariances and hitForRec resolution
392   TMatrixD* paramCov = extrapTrackParam.GetCovariances();
393   TMatrixD error(2,2);
394   error(0,0) = (*paramCov)(0,0) + hitForRec->GetNonBendingReso2();
395   error(0,1) = (*paramCov)(0,2);
396   error(1,0) = (*paramCov)(2,0);
397   error(1,1) = (*paramCov)(2,2) + hitForRec->GetBendingReso2();
398   
399   // Invert the error matrix for Chi2 calculation
400   if (error.Determinant() != 0) {
401     error.Invert();
402   } else {
403     AliWarning(" Determinant error=0");
404     return 1.e10;
405   }
406   
407   // Compute the Chi2 value
408   TMatrixD tmp(error,TMatrixD::kMult,dPos);
409   TMatrixD result(dPos,TMatrixD::kTransposeMult,tmp);
410   
411   return result(0,0);
412   
413 }
414
415   //__________________________________________________________________________
416 Double_t AliMUONTrack::TryTwoHitForRec(AliMUONHitForRec* hitForRec1, AliMUONHitForRec* hitForRec2)
417 {
418 /// Test the compatibility between the track and the 2 hitForRec together:
419 /// return the corresponding Chi2 accounting for covariances between the 2 hitForRec
420   
421   // Get track parameters and their covariances at the z position of the first hitForRec
422   AliMUONTrackParam extrapTrackParam1(fExtrapTrackParam);
423   AliMUONTrackExtrap::ExtrapToZCov(&extrapTrackParam1, hitForRec1->GetZ());
424   
425   // Get track parameters at second hitForRec
426   AliMUONTrackParam extrapTrackParam2(extrapTrackParam1);
427   AliMUONTrackExtrap::ExtrapToZ(&extrapTrackParam2, hitForRec2->GetZ());
428   
429   // Set differences between track and the 2 hitForRec in the bending and non bending directions
430   TMatrixD dPos(4,1);
431   dPos(0,0) = hitForRec1->GetNonBendingCoor() - extrapTrackParam1.GetNonBendingCoor();
432   dPos(1,0) = hitForRec1->GetBendingCoor() - extrapTrackParam1.GetBendingCoor();
433   dPos(2,0) = hitForRec2->GetNonBendingCoor() - extrapTrackParam2.GetNonBendingCoor();
434   dPos(3,0) = hitForRec2->GetBendingCoor() - extrapTrackParam2.GetBendingCoor();
435   
436   // quick tests of hitForRec compatibility within a wide road of x*y = 1*1 cm2 to save computing time
437   if (TMath::Abs(dPos(0,0)) > fgkMaxTrackingDistanceNonBending ||
438       TMath::Abs(dPos(1,0)) > fgkMaxTrackingDistanceBending    ||
439       TMath::Abs(dPos(2,0)) > fgkMaxTrackingDistanceNonBending ||
440       TMath::Abs(dPos(3,0)) > fgkMaxTrackingDistanceBending) return 1.e10;
441   
442   // Calculate the error matrix from the track parameter covariances at first hitForRec
443   TMatrixD error(4,4);
444   error = 0.;
445   if (extrapTrackParam1.CovariancesExist()) {
446     // Get the pointer to the parameter covariance matrix at first hitForRec
447     TMatrixD* paramCov = extrapTrackParam1.GetCovariances();
448     
449     // Save track parameters at first hitForRec
450     AliMUONTrackParam extrapTrackParam1Save(extrapTrackParam1);
451     Double_t nonBendingCoor1         = extrapTrackParam1Save.GetNonBendingCoor();
452     Double_t nonBendingSlope1        = extrapTrackParam1Save.GetNonBendingSlope();
453     Double_t bendingCoor1            = extrapTrackParam1Save.GetBendingCoor();
454     Double_t bendingSlope1           = extrapTrackParam1Save.GetBendingSlope();
455     Double_t inverseBendingMomentum1 = extrapTrackParam1Save.GetInverseBendingMomentum();
456     Double_t z1                      = extrapTrackParam1Save.GetZ();
457     
458     // Save track coordinates at second hitForRec
459     Double_t nonBendingCoor2         = extrapTrackParam2.GetNonBendingCoor();
460     Double_t bendingCoor2            = extrapTrackParam2.GetBendingCoor();
461     
462     // Calculate the jacobian related to the transformation between track parameters
463     // at first hitForRec and track coordinates at the 2 hitForRec z-position
464     TMatrixD jacob(4,5);
465     jacob = 0.;
466     // first derivative at the first hitForRec:
467     jacob(0,0) = 1.; // dx1/dx
468     jacob(1,2) = 1.; // dy1/dy
469     // first derivative at the second hitForRec:
470     Double_t dParam[5];
471     for (Int_t i=0; i<5; i++) {
472       // Skip jacobian calculation for parameters with no associated error
473       if ((*paramCov)(i,i) == 0.) continue;
474       // Small variation of parameter i only
475       for (Int_t j=0; j<5; j++) {
476         if (j==i) {
477           dParam[j] = TMath::Sqrt((*paramCov)(i,i));
478           if (j == 4) dParam[j] *= TMath::Sign(1.,-inverseBendingMomentum1); // variation always in the same direction
479         } else dParam[j] = 0.;
480       }
481       // Set new track parameters at first hitForRec
482       extrapTrackParam1Save.SetNonBendingCoor        (nonBendingCoor1         + dParam[0]);
483       extrapTrackParam1Save.SetNonBendingSlope       (nonBendingSlope1        + dParam[1]);
484       extrapTrackParam1Save.SetBendingCoor           (bendingCoor1            + dParam[2]);
485       extrapTrackParam1Save.SetBendingSlope          (bendingSlope1           + dParam[3]);
486       extrapTrackParam1Save.SetInverseBendingMomentum(inverseBendingMomentum1 + dParam[4]);
487       extrapTrackParam1Save.SetZ                     (z1);
488       // Extrapolate new track parameters to the z position of the second hitForRec
489       AliMUONTrackExtrap::ExtrapToZ(&extrapTrackParam1Save,hitForRec2->GetZ());
490       // Calculate the jacobian
491       jacob(2,i) = (extrapTrackParam1Save.GetNonBendingCoor()  - nonBendingCoor2) / dParam[i]; // dx2/dParami
492       jacob(3,i) = (extrapTrackParam1Save.GetBendingCoor()     - bendingCoor2   ) / dParam[i]; // dy2/dParami
493     }
494     
495     // Calculate the error matrix
496     TMatrixD tmp((*paramCov),TMatrixD::kMultTranspose,jacob);
497     error = TMatrixD(jacob,TMatrixD::kMult,tmp);
498   }
499   
500   // Add hitForRec resolution to the error matrix
501   error(0,0) += hitForRec1->GetNonBendingReso2();
502   error(1,1) += hitForRec1->GetBendingReso2();
503   error(2,2) += hitForRec2->GetNonBendingReso2();
504   error(3,3) += hitForRec2->GetBendingReso2();
505   
506   // invert the error matrix for Chi2 calculation
507   if (error.Determinant() != 0) {
508     error.Invert();
509   } else {
510     AliWarning(" Determinant error=0");
511     return 1.e10;
512   }
513   
514   // Compute the Chi2 value
515   TMatrixD tmp2(error,TMatrixD::kMult,dPos);
516   TMatrixD result(dPos,TMatrixD::kTransposeMult,tmp2);
517   
518   return result(0,0);
519   
520 }
521
522   //__________________________________________________________________________
523 void AliMUONTrack::RecursiveDump(void) const
524 {
525   /// Recursive dump of AliMUONTrack, i.e. with dump of TrackParamAtHit's and attached HitForRec's
526   AliMUONTrackParam *trackParamAtHit;
527   AliMUONHitForRec *hitForRec;
528   cout << "Recursive dump of Track: " << this << endl;
529   // Track
530   this->Dump();
531   for (Int_t trackHitIndex = 0; trackHitIndex < fNTrackHits; trackHitIndex++) {
532     trackParamAtHit = (AliMUONTrackParam*) ((*fTrackParamAtHit)[trackHitIndex]);
533     // TrackHit
534     cout << "TrackParamAtHit: " << trackParamAtHit << " (index: " << trackHitIndex << ")" << endl;
535     trackParamAtHit->Dump();
536     hitForRec = trackParamAtHit->GetHitForRecPtr();
537     // HitForRec
538     cout << "HitForRec: " << hitForRec << endl;
539     hitForRec->Dump();
540   }
541   return;
542 }
543   
544 //_____________________________________________-
545 void AliMUONTrack::Print(Option_t* opt) const
546 {
547   /// Printing Track information 
548   /// "full" option for printing all the information about the track
549   TString sopt(opt);
550   sopt.ToUpper();
551  
552   if ( sopt.Contains("FULL") ) { 
553     cout << "<AliMUONTrack> No.Clusters=" << setw(2)   << GetNTrackHits() << 
554       //      ", Bending P="<< setw(8) << setprecision(5)      << 1./GetInverseBendingMomentum() << 
555       //", NonBendSlope=" << setw(8) << setprecision(5)  << GetNonBendingSlope()*180./TMath::Pi() <<
556       //", BendSlope=" << setw(8) << setprecision(5)     << GetBendingSlope()*180./TMath::Pi() <<
557       ", Match2Trig=" << setw(1) << GetMatchTrigger()  << 
558       ", Chi2-tracking-trigger=" << setw(8) << setprecision(5) <<  GetChi2MatchTrigger() << endl ;
559     GetTrackParamAtHit()->First()->Print("full");
560   }
561   else {
562     cout << "<AliMUONTrack>";
563     GetTrackParamAtHit()->First()->Print("");
564
565   }
566     
567 }