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