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