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