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