]> git.uio.no Git - u/mrichter/AliRoot.git/blob - MUON/AliMUONTrack.cxx
Exec changed to UserExec.
[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 // Class AliMUONTrack
20 //-------------------
21 // Reconstructed track in ALICE dimuon spectrometer
22 //-----------------------------------------------------------------------------
23
24 #include "AliMUONTrack.h"
25
26 #include "AliMUONReconstructor.h"
27 #include "AliMUONRecoParam.h"
28 #include "AliMUONVCluster.h"
29 #include "AliMUONVClusterStore.h"
30 #include "AliMUONObjectPair.h"
31 #include "AliMUONConstants.h"
32 #include "AliMUONTrackExtrap.h"
33
34 #include "AliLog.h"
35
36 #include <TMath.h>
37 #include <TMatrixD.h>
38
39 #include <Riostream.h>
40
41 /// \cond CLASSIMP
42 ClassImp(AliMUONTrack) // Class implementation in ROOT context
43 /// \endcond
44
45 //__________________________________________________________________________
46 AliMUONTrack::AliMUONTrack()
47   : TObject(),
48     fTrackParamAtCluster(0x0),
49     fFitWithVertex(kFALSE),
50     fVertexErrXY2(),
51     fFitWithMCS(kFALSE),
52     fClusterWeightsNonBending(0x0),
53     fClusterWeightsBending(0x0),
54     fGlobalChi2(-1.),
55     fImproved(kFALSE),
56     fMatchTrigger(-1),
57     floTrgNum(-1),
58     fChi2MatchTrigger(0.),
59     fTrackID(0),
60     fTrackParamAtVertex(0x0),
61     fHitsPatternInTrigCh(0),
62     fLocalTrigger(0)
63 {
64   /// Default constructor
65   fVertexErrXY2[0] = 0.;
66   fVertexErrXY2[1] = 0.;
67 }
68
69   //__________________________________________________________________________
70 AliMUONTrack::AliMUONTrack(AliMUONObjectPair *segment, Double_t bendingVertexDispersion)
71   : TObject(),
72     fTrackParamAtCluster(new TClonesArray("AliMUONTrackParam",10)),
73     fFitWithVertex(kFALSE),
74     fVertexErrXY2(),
75     fFitWithMCS(kFALSE),
76     fClusterWeightsNonBending(0x0),
77     fClusterWeightsBending(0x0),
78     fGlobalChi2(0.),
79     fImproved(kFALSE),
80     fMatchTrigger(-1),
81     floTrgNum(-1),    
82     fChi2MatchTrigger(0.),
83     fTrackID(0),
84     fTrackParamAtVertex(0x0),
85     fHitsPatternInTrigCh(0),
86     fLocalTrigger(0)
87 {
88   /// Constructor from two clusters
89   
90   fVertexErrXY2[0] = 0.;
91   fVertexErrXY2[1] = 0.;
92   
93   // Pointers to clusters from the segment
94   AliMUONVCluster* firstCluster = (AliMUONVCluster*) segment->First();
95   AliMUONVCluster* lastCluster = (AliMUONVCluster*) segment->Second();
96   
97   // Compute track parameters
98   Double_t z1 = firstCluster->GetZ();
99   Double_t z2 = lastCluster->GetZ();
100   Double_t dZ = z1 - z2;
101   // Non bending plane
102   Double_t nonBendingCoor1 = firstCluster->GetX();
103   Double_t nonBendingCoor2 = lastCluster->GetX();
104   Double_t nonBendingSlope = (nonBendingCoor1 - nonBendingCoor2) / dZ;
105   // Bending plane
106   Double_t bendingCoor1 = firstCluster->GetY();
107   Double_t bendingCoor2 = lastCluster->GetY();
108   Double_t bendingSlope = (bendingCoor1 - bendingCoor2) / dZ;
109   // Inverse bending momentum
110   Double_t bendingImpact = bendingCoor1 - z1 * bendingSlope;
111   Double_t inverseBendingMomentum = 1. / AliMUONTrackExtrap::GetBendingMomentumFromImpactParam(bendingImpact);
112   
113   // Set track parameters at first cluster
114   AliMUONTrackParam trackParamAtFirstCluster;
115   trackParamAtFirstCluster.SetZ(z1);
116   trackParamAtFirstCluster.SetNonBendingCoor(nonBendingCoor1);
117   trackParamAtFirstCluster.SetNonBendingSlope(nonBendingSlope);
118   trackParamAtFirstCluster.SetBendingCoor(bendingCoor1);
119   trackParamAtFirstCluster.SetBendingSlope(bendingSlope);
120   trackParamAtFirstCluster.SetInverseBendingMomentum(inverseBendingMomentum);
121   
122   // Set track parameters at last cluster
123   AliMUONTrackParam trackParamAtLastCluster;
124   trackParamAtLastCluster.SetZ(z2);
125   trackParamAtLastCluster.SetNonBendingCoor(nonBendingCoor2);
126   trackParamAtLastCluster.SetNonBendingSlope(nonBendingSlope);
127   trackParamAtLastCluster.SetBendingCoor(bendingCoor2);
128   trackParamAtLastCluster.SetBendingSlope(bendingSlope);
129   trackParamAtLastCluster.SetInverseBendingMomentum(inverseBendingMomentum);
130   
131   // Compute and set track parameters covariances at first cluster
132   TMatrixD paramCov(5,5);
133   paramCov.Zero();
134   // Non bending plane
135   paramCov(0,0) = firstCluster->GetErrX2();
136   paramCov(0,1) = firstCluster->GetErrX2() / dZ;
137   paramCov(1,0) = paramCov(0,1);
138   paramCov(1,1) = ( firstCluster->GetErrX2() + lastCluster->GetErrX2() ) / dZ / dZ;
139   // Bending plane
140   paramCov(2,2) = firstCluster->GetErrY2();
141   paramCov(2,3) = firstCluster->GetErrY2() / dZ;
142   paramCov(3,2) = paramCov(2,3);
143   paramCov(3,3) = ( firstCluster->GetErrY2() + lastCluster->GetErrY2() ) / dZ / dZ;
144   // Inverse bending momentum (vertex resolution + bending slope resolution + 10% error on dipole parameters+field)
145   paramCov(4,4) = ( ( bendingVertexDispersion*bendingVertexDispersion +
146                     (z1 * z1 * lastCluster->GetErrY2() + z2 * z2 * firstCluster->GetErrY2()) / dZ / dZ) /
147                    bendingImpact / bendingImpact + 0.1 * 0.1) * inverseBendingMomentum * inverseBendingMomentum ;
148   paramCov(2,4) = - z2 * firstCluster->GetErrY2() * inverseBendingMomentum / bendingImpact / dZ;
149   paramCov(4,2) = paramCov(2,4);
150   paramCov(3,4) = - (z1 * lastCluster->GetErrY2() + z2 * firstCluster->GetErrY2()) * inverseBendingMomentum / bendingImpact / dZ / dZ;
151   paramCov(4,3) = paramCov(3,4);
152   
153   // Set covariances
154   trackParamAtFirstCluster.SetCovariances(paramCov);
155   
156   // Compute and set track parameters covariances at last cluster
157   paramCov(1,0) = - paramCov(1,0);
158   paramCov(0,1) = - paramCov(0,1);
159   paramCov(3,2) = - paramCov(3,2);
160   paramCov(2,3) = - paramCov(2,3);
161   paramCov(2,4) = z1 * lastCluster->GetErrY2() * inverseBendingMomentum / bendingImpact / dZ;
162   paramCov(4,2) = paramCov(2,4);
163   trackParamAtLastCluster.SetCovariances(paramCov);
164   
165   // Add track parameters at clusters
166   AddTrackParamAtCluster(trackParamAtFirstCluster,*firstCluster);
167   AddTrackParamAtCluster(trackParamAtLastCluster,*lastCluster);
168   
169 }
170
171 //__________________________________________________________________________
172 AliMUONTrack::AliMUONTrack(const AliMUONTrack& track)
173   : TObject(track),
174     fTrackParamAtCluster(0x0),
175     fFitWithVertex(track.fFitWithVertex),
176     fVertexErrXY2(),
177     fFitWithMCS(track.fFitWithMCS),
178     fClusterWeightsNonBending(0x0),
179     fClusterWeightsBending(0x0),
180     fGlobalChi2(track.fGlobalChi2),
181     fImproved(track.fImproved),
182     fMatchTrigger(track.fMatchTrigger),
183     floTrgNum(track.floTrgNum),    
184     fChi2MatchTrigger(track.fChi2MatchTrigger),
185     fTrackID(track.fTrackID),
186     fTrackParamAtVertex(0x0),
187     fHitsPatternInTrigCh(track.fHitsPatternInTrigCh),
188     fLocalTrigger(track.fLocalTrigger)
189 {
190   ///copy constructor
191   
192   // necessary to make a copy of the objects and not only the pointers in TClonesArray.
193   if (track.fTrackParamAtCluster) {
194     fTrackParamAtCluster = new TClonesArray("AliMUONTrackParam",10);
195     AliMUONTrackParam *trackParamAtCluster = (AliMUONTrackParam*) track.fTrackParamAtCluster->First();
196     while (trackParamAtCluster) {
197       new ((*fTrackParamAtCluster)[GetNClusters()]) AliMUONTrackParam(*trackParamAtCluster);
198       trackParamAtCluster = (AliMUONTrackParam*) track.fTrackParamAtCluster->After(trackParamAtCluster);
199     }
200   }
201   
202   // copy vertex resolution square used during the tracking procedure
203   fVertexErrXY2[0] = track.fVertexErrXY2[0];
204   fVertexErrXY2[1] = track.fVertexErrXY2[1];
205   
206   // copy cluster weights matrices if any
207   if (track.fClusterWeightsNonBending) fClusterWeightsNonBending = new TMatrixD(*(track.fClusterWeightsNonBending));
208   if (track.fClusterWeightsBending) fClusterWeightsBending = new TMatrixD(*(track.fClusterWeightsBending));
209   
210   // copy track parameters at vertex if any
211   if (track.fTrackParamAtVertex) fTrackParamAtVertex = new AliMUONTrackParam(*(track.fTrackParamAtVertex));
212   
213 }
214
215   //__________________________________________________________________________
216 AliMUONTrack & AliMUONTrack::operator=(const AliMUONTrack& track)
217 {
218   /// Asignment operator
219   // check assignement to self
220   if (this == &track)
221     return *this;
222
223   // base class assignement
224   TObject::operator=(track);
225   
226   // clear memory
227   Clear();
228   
229   // necessary to make a copy of the objects and not only the pointers in TClonesArray
230   if (track.fTrackParamAtCluster) {
231     fTrackParamAtCluster = new TClonesArray("AliMUONTrackParam",10);
232     AliMUONTrackParam *trackParamAtCluster = (AliMUONTrackParam*) track.fTrackParamAtCluster->First();
233     while (trackParamAtCluster) {
234       new ((*fTrackParamAtCluster)[GetNClusters()]) AliMUONTrackParam(*trackParamAtCluster);
235       trackParamAtCluster = (AliMUONTrackParam*) track.fTrackParamAtCluster->After(trackParamAtCluster);
236     }
237   }
238   
239   // copy cluster weights matrix if any
240   if (track.fClusterWeightsNonBending) {
241     if (fClusterWeightsNonBending) {
242       fClusterWeightsNonBending->ResizeTo(*(track.fClusterWeightsNonBending));
243       *fClusterWeightsNonBending = *(track.fClusterWeightsNonBending);
244     } else fClusterWeightsNonBending = new TMatrixD(*(track.fClusterWeightsNonBending));
245   }
246   
247   // copy cluster weights matrix if any
248   if (track.fClusterWeightsBending) {
249     if (fClusterWeightsBending) {
250       fClusterWeightsBending->ResizeTo(*(track.fClusterWeightsBending));
251       *fClusterWeightsBending = *(track.fClusterWeightsBending);
252     } else fClusterWeightsBending = new TMatrixD(*(track.fClusterWeightsBending));
253   }
254   
255   // copy track parameters at vertex if any
256   if (track.fTrackParamAtVertex) {
257     if (fTrackParamAtVertex) *fTrackParamAtVertex = *(track.fTrackParamAtVertex);
258     else fTrackParamAtVertex = new AliMUONTrackParam(*(track.fTrackParamAtVertex));
259   }
260   
261   fFitWithVertex      =  track.fFitWithVertex;
262   fVertexErrXY2[0]    =  track.fVertexErrXY2[0];
263   fVertexErrXY2[1]    =  track.fVertexErrXY2[1];
264   fFitWithMCS         =  track.fFitWithMCS;
265   fGlobalChi2         =  track.fGlobalChi2;
266   fImproved           =  track.fImproved;
267   fMatchTrigger       =  track.fMatchTrigger;
268   floTrgNum           =  track.floTrgNum;
269   fChi2MatchTrigger   =  track.fChi2MatchTrigger;
270   fTrackID            =  track.fTrackID; 
271   fHitsPatternInTrigCh = track.fHitsPatternInTrigCh;
272   fLocalTrigger        = track.fLocalTrigger;
273
274   return *this;
275 }
276
277   //__________________________________________________________________________
278 AliMUONTrack::~AliMUONTrack()
279 {
280   /// Destructor
281   delete fTrackParamAtCluster;
282   delete fClusterWeightsNonBending;
283   delete fClusterWeightsBending;
284   delete fTrackParamAtVertex;
285 }
286
287   //__________________________________________________________________________
288 void AliMUONTrack::Clear(Option_t* opt)
289 {
290   /// Clear arrays
291   if (opt && opt[0] == 'C' && fTrackParamAtCluster) fTrackParamAtCluster->Clear("C");
292   else {
293     delete fTrackParamAtCluster;
294     fTrackParamAtCluster = 0x0;
295   }
296   delete fClusterWeightsNonBending; fClusterWeightsNonBending = 0x0;
297   delete fClusterWeightsBending; fClusterWeightsBending = 0x0;
298   delete fTrackParamAtVertex; fTrackParamAtVertex = 0x0;
299 }
300
301   //__________________________________________________________________________
302 void AliMUONTrack::Reset()
303 {
304   /// Reset to default values
305   SetUniqueID(0);
306   fFitWithVertex = kFALSE;
307   fVertexErrXY2[0] = 0.;
308   fVertexErrXY2[1] = 0.;
309   fFitWithMCS = kFALSE;
310   fGlobalChi2 = -1.;
311   fImproved = kFALSE;
312   fMatchTrigger = -1;
313   floTrgNum = -1;
314   fChi2MatchTrigger = 0.;
315   fTrackID = 0;
316   fHitsPatternInTrigCh = 0;
317   fLocalTrigger = 0;
318   delete fTrackParamAtCluster; fTrackParamAtCluster = 0x0;
319   delete fClusterWeightsNonBending; fClusterWeightsNonBending = 0x0;
320   delete fClusterWeightsBending; fClusterWeightsBending = 0x0;
321   delete fTrackParamAtVertex; fTrackParamAtVertex = 0x0;
322 }
323
324   //__________________________________________________________________________
325 TClonesArray* AliMUONTrack::GetTrackParamAtCluster() const
326 {
327   /// return array of track parameters at cluster (create it if needed)
328   if (!fTrackParamAtCluster) fTrackParamAtCluster = new TClonesArray("AliMUONTrackParam",10);
329   return fTrackParamAtCluster;
330 }
331
332   //__________________________________________________________________________
333 void AliMUONTrack::AddTrackParamAtCluster(const AliMUONTrackParam &trackParam, AliMUONVCluster &cluster, Bool_t copy)
334 {
335   /// Copy given track parameters into a new TrackParamAtCluster
336   /// Link parameters with the associated cluster
337   /// If copy=kTRUE: the cluster is copied then passed the trackParam which become its owner 
338   ///     otherwise: make sure to do not delete the cluster until it is used by the track
339   
340   // check chamber ID of the associated cluster
341   if (cluster.GetChamberId() < 0 || cluster.GetChamberId() > AliMUONConstants::NTrackingCh()) {
342     AliError(Form("Chamber ID of the associated cluster is not valid (ChamberId=%d)",cluster.GetChamberId()));
343     return;
344   }
345   
346   // check whether track parameters are given at the correct cluster z position
347   if (cluster.GetZ() != trackParam.GetZ()) {
348     AliError("track parameters are given at a different z position than the one of the associated cluster");
349     return;
350   }
351   
352   // add parameters to the array of track parameters
353   if (!fTrackParamAtCluster) fTrackParamAtCluster = new TClonesArray("AliMUONTrackParam",10);
354   AliMUONTrackParam* trackParamAtCluster = new ((*fTrackParamAtCluster)[GetNClusters()]) AliMUONTrackParam(trackParam);
355   
356   // link parameters with the associated cluster or its copy
357   if (copy) {
358     AliMUONVCluster *clusterCopy = static_cast<AliMUONVCluster*>(cluster.Clone());
359     trackParamAtCluster->SetClusterPtr(clusterCopy, kTRUE);
360   } else trackParamAtCluster->SetClusterPtr(&cluster);
361   
362   // sort the array of track parameters
363   fTrackParamAtCluster->Sort();
364 }
365
366   //__________________________________________________________________________
367 void AliMUONTrack::RemoveTrackParamAtCluster(AliMUONTrackParam *trackParam)
368 {
369   /// Remove trackParam from the array of TrackParamAtCluster
370   if (!fTrackParamAtCluster || !fTrackParamAtCluster->Remove(trackParam)) {
371     AliWarning("object to remove does not exist in array fTrackParamAtCluster");
372     return;
373   }
374   
375   fTrackParamAtCluster->Compress();
376 }
377
378   //__________________________________________________________________________
379 void AliMUONTrack::UpdateTrackParamAtCluster()
380 {
381   /// Update track parameters at each attached cluster
382   
383   if (GetNClusters() == 0) {
384     AliWarning("no cluster attached to the track");
385     return;
386   }
387   
388   AliMUONTrackParam* startingTrackParam = (AliMUONTrackParam*) fTrackParamAtCluster->First();
389   AliMUONTrackParam* trackParamAtCluster = (AliMUONTrackParam*) fTrackParamAtCluster->After(startingTrackParam);
390   while (trackParamAtCluster) {
391     
392     // reset track parameters and their covariances
393     trackParamAtCluster->SetParameters(startingTrackParam->GetParameters());
394     trackParamAtCluster->SetZ(startingTrackParam->GetZ());
395     
396     // extrapolation to the given z
397     AliMUONTrackExtrap::ExtrapToZ(trackParamAtCluster, trackParamAtCluster->GetClusterPtr()->GetZ());
398     
399     // prepare next step
400     startingTrackParam = trackParamAtCluster;
401     trackParamAtCluster = (AliMUONTrackParam*) (fTrackParamAtCluster->After(trackParamAtCluster));
402   }
403
404 }
405
406   //__________________________________________________________________________
407 void AliMUONTrack::UpdateCovTrackParamAtCluster()
408 {
409   /// Update track parameters and their covariances at each attached cluster
410   /// Include effects of multiple scattering in chambers
411   
412   if (GetNClusters() == 0) {
413     AliWarning("no cluster attached to the track");
414     return;
415   }
416   
417   AliMUONTrackParam* startingTrackParam = (AliMUONTrackParam*) fTrackParamAtCluster->First();
418   AliMUONTrackParam* trackParamAtCluster = (AliMUONTrackParam*) fTrackParamAtCluster->After(startingTrackParam);
419   Int_t expectedChamber = startingTrackParam->GetClusterPtr()->GetChamberId() + 1;
420   Int_t currentChamber;
421   while (trackParamAtCluster) {
422     
423     // reset track parameters and their covariances
424     trackParamAtCluster->SetParameters(startingTrackParam->GetParameters());
425     trackParamAtCluster->SetZ(startingTrackParam->GetZ());
426     trackParamAtCluster->SetCovariances(startingTrackParam->GetCovariances());
427     
428     // add MCS effect
429     AliMUONTrackExtrap::AddMCSEffect(trackParamAtCluster,AliMUONConstants::ChamberThicknessInX0(),1.);
430     
431     // add MCS in missing chambers if any
432     currentChamber = trackParamAtCluster->GetClusterPtr()->GetChamberId();
433     while (currentChamber > expectedChamber) {
434       // extrapolation to the missing chamber
435       AliMUONTrackExtrap::ExtrapToZCov(trackParamAtCluster, AliMUONConstants::DefaultChamberZ(expectedChamber));
436       // add MCS effect
437       AliMUONTrackExtrap::AddMCSEffect(trackParamAtCluster,AliMUONConstants::ChamberThicknessInX0(),1.);
438       expectedChamber++;
439     }
440     
441     // extrapolation to the z of the current cluster
442     AliMUONTrackExtrap::ExtrapToZCov(trackParamAtCluster, trackParamAtCluster->GetClusterPtr()->GetZ());
443     
444     // prepare next step
445     expectedChamber = currentChamber + 1;
446     startingTrackParam = trackParamAtCluster;
447     trackParamAtCluster = (AliMUONTrackParam*) (fTrackParamAtCluster->After(trackParamAtCluster));
448   }
449   
450 }
451
452   //__________________________________________________________________________
453 Bool_t AliMUONTrack::IsValid(UInt_t requestedStationMask)
454 {
455   /// check the validity of the current track (at least one cluster per requested station)
456   
457   Int_t nClusters = GetNClusters();
458   AliMUONTrackParam *trackParam;
459   Int_t currentStation(0);
460   
461   UInt_t m(0);
462   
463   for (Int_t i = 0; i < nClusters; i++) 
464   {
465     trackParam = (AliMUONTrackParam*) fTrackParamAtCluster->UncheckedAt(i);
466     
467     // skip unrequested stations
468 //    while (expectedStation < AliMUONConstants::NTrackingSt() &&
469 //         !AliMUONReconstructor::GetRecoParam()->RequestStation(expectedStation)) expectedStation++;
470 //    
471
472     currentStation = trackParam->GetClusterPtr()->GetChamberId()/2;
473     
474     m |= ( 1 << currentStation );
475     
476   }
477   
478   return ( (requestedStationMask & m) == requestedStationMask ) ;
479 }
480
481   //__________________________________________________________________________
482 void AliMUONTrack::TagRemovableClusters(UInt_t requestedStationMask) {
483   /// Identify clusters that can be removed from the track,
484   /// with the only requirement to have at least 1 cluster per requested station
485   
486   Int_t nClusters = GetNClusters();
487   AliMUONTrackParam *trackParam, *nextTrackParam;
488   Int_t currentCh, nextCh;
489   
490   // reset flags to kFALSE for all clusters in required station
491   for (Int_t i = 0; i < nClusters; i++) {
492     trackParam = (AliMUONTrackParam*) fTrackParamAtCluster->UncheckedAt(i);
493     Int_t stationId = ( 1 << (trackParam->GetClusterPtr()->GetChamberId()/2) );
494     UInt_t m = ( 1 << stationId );
495     if ( m & requestedStationMask )
496       trackParam->SetRemovable(kFALSE);
497     else trackParam->SetRemovable(kTRUE);
498   }
499   
500   // loop over track parameters
501   for (Int_t i = 0; i < nClusters; i++) {
502     trackParam = (AliMUONTrackParam*) fTrackParamAtCluster->UncheckedAt(i);
503     
504     currentCh = trackParam->GetClusterPtr()->GetChamberId();
505     
506     // loop over next track parameters
507     for (Int_t j = i+1; j < nClusters; j++) {
508       nextTrackParam = (AliMUONTrackParam*) fTrackParamAtCluster->UncheckedAt(j);
509       
510       nextCh = nextTrackParam->GetClusterPtr()->GetChamberId();
511       
512       // check if the 2 clusters are on the same station
513       if (nextCh/2 != currentCh/2) break;
514       
515       // set clusters in the same station as being removable
516       trackParam->SetRemovable(kTRUE);
517       nextTrackParam->SetRemovable(kTRUE);
518       
519     }
520     
521   }
522     
523 }
524
525   //__________________________________________________________________________
526 Bool_t AliMUONTrack::ComputeLocalChi2(Bool_t accountForMCS)
527 {
528   /// Compute each cluster contribution to the chi2 of the track
529   /// accounting for multiple scattering or not according to the flag
530   /// - Also recompute the weight matrices of the attached clusters if accountForMCS=kTRUE
531   /// - Assume that track parameters at each cluster are corrects
532   /// - Return kFALSE if computation failed
533   AliDebug(1,"Enter ComputeLocalChi2");
534   
535   if (!fTrackParamAtCluster) {
536     AliWarning("no cluster attached to this track");
537     return kFALSE;
538   }
539   
540   if (accountForMCS) { // Compute local chi2 taking into account multiple scattering effects
541       
542     // Compute MCS covariance matrix only once
543     Int_t nClusters = GetNClusters();
544     TMatrixD mcsCovariances(nClusters,nClusters);
545     ComputeMCSCovariances(mcsCovariances);
546     
547     // Make sure cluster weights are consistent with following calculations
548     if (!ComputeClusterWeights(&mcsCovariances)) {
549       AliWarning("cannot take into account the multiple scattering effects");
550       return ComputeLocalChi2(kFALSE);
551     }
552     
553     // Compute chi2 of the track
554     Double_t globalChi2 = ComputeGlobalChi2(kTRUE);
555     if (globalChi2 < 0.) return kFALSE;
556     
557     // Loop over removable clusters and compute their local chi2
558     AliMUONTrackParam* trackParamAtCluster1;
559     AliMUONVCluster *cluster, *discardedCluster;
560     Int_t iCluster1, iCluster2, iCurrentCluster1, iCurrentCluster2;
561     TMatrixD clusterWeightsNB(nClusters-1,nClusters-1);
562     TMatrixD clusterWeightsB(nClusters-1,nClusters-1);
563     Double_t *dX = new Double_t[nClusters-1];
564     Double_t *dY = new Double_t[nClusters-1];
565     Double_t globalChi2b;
566     AliMUONTrackParam* trackParamAtCluster = (AliMUONTrackParam*) fTrackParamAtCluster->First();
567     while (trackParamAtCluster) {
568       
569       discardedCluster = trackParamAtCluster->GetClusterPtr();
570       
571       // Recompute cluster weights without the current cluster
572       if (!ComputeClusterWeights(clusterWeightsNB, clusterWeightsB, &mcsCovariances, discardedCluster)) {
573         AliWarning("cannot take into account the multiple scattering effects");
574         delete [] dX;
575         delete [] dY;
576         return ComputeLocalChi2(kFALSE);
577       }
578       
579       // Compute track chi2 without the current cluster
580       globalChi2b = 0.;
581       iCurrentCluster1 = 0;
582       for (iCluster1 = 0; iCluster1 < nClusters ; iCluster1++) { 
583         trackParamAtCluster1 = (AliMUONTrackParam*) fTrackParamAtCluster->UncheckedAt(iCluster1);
584         cluster = trackParamAtCluster1->GetClusterPtr();
585         
586         if (cluster == discardedCluster) continue;
587         
588         // Compute and save residuals
589         dX[iCurrentCluster1] = cluster->GetX() - trackParamAtCluster1->GetNonBendingCoor();
590         dY[iCurrentCluster1] = cluster->GetY() - trackParamAtCluster1->GetBendingCoor();
591         
592         iCurrentCluster2 = 0;
593         for (iCluster2 = 0; iCluster2 < iCluster1; iCluster2++) {
594           cluster = ((AliMUONTrackParam*) fTrackParamAtCluster->UncheckedAt(iCluster2))->GetClusterPtr();
595           
596           if (cluster == discardedCluster) continue;
597           
598           // Add contribution from covariances
599           globalChi2b += (clusterWeightsNB(iCurrentCluster1, iCurrentCluster2) +
600                           clusterWeightsNB(iCurrentCluster2, iCurrentCluster1)) * dX[iCurrentCluster1] * dX[iCurrentCluster2] +
601                          (clusterWeightsB(iCurrentCluster1, iCurrentCluster2) +
602                           clusterWeightsB(iCurrentCluster2, iCurrentCluster1)) * dY[iCurrentCluster1] * dY[iCurrentCluster2];
603           
604           iCurrentCluster2++;
605         }
606         
607         // Add contribution from variances
608         globalChi2b += clusterWeightsNB(iCurrentCluster1, iCurrentCluster1) * dX[iCurrentCluster1] * dX[iCurrentCluster1] +
609                        clusterWeightsB(iCurrentCluster1, iCurrentCluster1) * dY[iCurrentCluster1] * dY[iCurrentCluster1];
610         
611         iCurrentCluster1++;
612       }
613
614       // Set local chi2
615       trackParamAtCluster->SetLocalChi2(globalChi2 - globalChi2b);
616       
617       trackParamAtCluster = (AliMUONTrackParam*) fTrackParamAtCluster->After(trackParamAtCluster);
618     }
619     
620     delete [] dX;
621     delete [] dY;
622     
623   } else { // without multiple scattering effects
624     
625     AliMUONVCluster *discardedCluster;
626     Double_t dX, dY;
627     AliMUONTrackParam* trackParamAtCluster = (AliMUONTrackParam*) fTrackParamAtCluster->First();
628     while (trackParamAtCluster) {
629       
630       discardedCluster = trackParamAtCluster->GetClusterPtr();
631       
632       // Compute residuals
633       dX = discardedCluster->GetX() - trackParamAtCluster->GetNonBendingCoor();
634       dY = discardedCluster->GetY() - trackParamAtCluster->GetBendingCoor();
635       
636       // Set local chi2
637       trackParamAtCluster->SetLocalChi2(dX * dX / discardedCluster->GetErrX2() + dY * dY / discardedCluster->GetErrY2());
638     
639       trackParamAtCluster = (AliMUONTrackParam*) fTrackParamAtCluster->After(trackParamAtCluster);
640     }
641   
642   }
643   
644   return kTRUE;
645   
646 }
647
648   //__________________________________________________________________________
649 Double_t AliMUONTrack::ComputeGlobalChi2(Bool_t accountForMCS)
650 {
651   /// Compute the chi2 of the track accounting for multiple scattering or not according to the flag
652   /// - Assume that track parameters at each cluster are corrects
653   /// - Assume the cluster weights matrices are corrects
654   /// - Return negative value if chi2 computation failed
655   AliDebug(1,"Enter ComputeGlobalChi2");
656   
657   if (!fTrackParamAtCluster) {
658     AliWarning("no cluster attached to this track");
659     return 1.e10;
660   }
661   
662   Double_t chi2 = 0.;
663   
664   if (accountForMCS) {
665     
666     // Check the weight matrices. If weight matrices are not available compute chi2 without MCS
667     if (!fClusterWeightsNonBending || !fClusterWeightsBending) {
668       AliWarning("cluster weights including multiple scattering effects are not available\n\t\t --> compute chi2 WITHOUT multiple scattering");
669       return ComputeGlobalChi2(kFALSE);
670     }
671     Int_t nClusters = GetNClusters();
672     if (fClusterWeightsNonBending->GetNrows() != nClusters || fClusterWeightsBending->GetNcols() != nClusters) {
673       AliWarning("cluster weights including multiple scattering effects are not available\n\t\t --> compute chi2 WITHOUT multiple scattering");
674       return ComputeGlobalChi2(kFALSE);
675     }
676     
677     // Compute chi2
678     AliMUONVCluster *cluster;
679     Double_t *dX = new Double_t[nClusters];
680     Double_t *dY = new Double_t[nClusters];
681     AliMUONTrackParam* trackParamAtCluster;
682     for (Int_t iCluster1 = 0; iCluster1 < nClusters; iCluster1++) { 
683       trackParamAtCluster = (AliMUONTrackParam*) fTrackParamAtCluster->UncheckedAt(iCluster1);
684       cluster = trackParamAtCluster->GetClusterPtr();
685       dX[iCluster1] = cluster->GetX() - trackParamAtCluster->GetNonBendingCoor();
686       dY[iCluster1] = cluster->GetY() - trackParamAtCluster->GetBendingCoor();
687       for (Int_t iCluster2 = 0; iCluster2 < iCluster1; iCluster2++) {
688         chi2 += ((*fClusterWeightsNonBending)(iCluster1, iCluster2) + (*fClusterWeightsNonBending)(iCluster2, iCluster1)) * dX[iCluster1] * dX[iCluster2] +
689                 ((*fClusterWeightsBending)(iCluster1, iCluster2) + (*fClusterWeightsBending)(iCluster2, iCluster1)) * dY[iCluster1] * dY[iCluster2];
690       }
691       chi2 += ((*fClusterWeightsNonBending)(iCluster1, iCluster1) * dX[iCluster1] * dX[iCluster1]) +
692               ((*fClusterWeightsBending)(iCluster1, iCluster1) * dY[iCluster1] * dY[iCluster1]);
693     }
694     delete [] dX;
695     delete [] dY;
696     
697   } else {
698     
699     AliMUONVCluster *cluster;
700     Double_t dX, dY;
701     AliMUONTrackParam* trackParamAtCluster;
702     Int_t nClusters = GetNClusters();
703     for (Int_t iCluster = 0; iCluster < nClusters ; iCluster++) { 
704       trackParamAtCluster = (AliMUONTrackParam*) fTrackParamAtCluster->UncheckedAt(iCluster);
705       cluster = trackParamAtCluster->GetClusterPtr();
706       dX = cluster->GetX() - trackParamAtCluster->GetNonBendingCoor();
707       dY = cluster->GetY() - trackParamAtCluster->GetBendingCoor();
708       chi2 += dX * dX / cluster->GetErrX2() + dY * dY / cluster->GetErrY2();
709     }
710     
711   }
712   
713   return chi2;
714   
715 }
716
717   //__________________________________________________________________________
718 Bool_t AliMUONTrack::ComputeClusterWeights(TMatrixD* mcsCovariances)
719 {
720   /// Compute the weight matrices of the attached clusters, in non bending and bending direction,
721   /// accounting for multiple scattering correlations and cluster resolution
722   /// - Use the provided MCS covariance matrix if any (otherwise build it temporarily)
723   /// - Assume that track parameters at each cluster are corrects
724   /// - Return kFALSE if computation failed
725   AliDebug(1,"Enter ComputeClusterWeights1");
726   
727   if (!fTrackParamAtCluster) {
728     AliWarning("no cluster attached to this track");
729     return kFALSE;
730   }
731   
732   // Alocate memory
733   Int_t nClusters = GetNClusters();
734   if (!fClusterWeightsNonBending) fClusterWeightsNonBending = new TMatrixD(nClusters,nClusters);
735   if (!fClusterWeightsBending) fClusterWeightsBending = new TMatrixD(nClusters,nClusters);
736   
737   // Compute weights matrices
738   if (!ComputeClusterWeights(*fClusterWeightsNonBending, *fClusterWeightsBending, mcsCovariances)) return kFALSE;
739   
740   return kTRUE;
741   
742 }
743
744   //__________________________________________________________________________
745 Bool_t AliMUONTrack::ComputeClusterWeights(TMatrixD& clusterWeightsNB, TMatrixD& clusterWeightsB,
746                                            TMatrixD* mcsCovariances, AliMUONVCluster* discardedCluster) const
747 {
748   /// Compute the weight matrices, in non bending and bending direction,
749   /// of the other attached clusters assuming the discarded one does not exist
750   /// accounting for multiple scattering correlations and cluster resolution
751   /// - Use the provided MCS covariance matrix if any (otherwise build it temporarily)
752   /// - Return kFALSE if computation failed
753   AliDebug(1,"Enter ComputeClusterWeights2");
754   
755   // Check MCS covariance matrix and recompute it if need
756   Int_t nClusters = GetNClusters();
757   Bool_t deleteMCSCov = kFALSE;
758   if (!mcsCovariances) {
759     mcsCovariances = new TMatrixD(nClusters,nClusters);
760     deleteMCSCov = kTRUE;
761     ComputeMCSCovariances(*mcsCovariances);
762   }
763   
764   // Resize the weights matrices; alocate memory
765   if (discardedCluster) {
766     clusterWeightsNB.ResizeTo(nClusters-1,nClusters-1);
767     clusterWeightsB.ResizeTo(nClusters-1,nClusters-1);
768   } else {
769     clusterWeightsNB.ResizeTo(nClusters,nClusters);
770     clusterWeightsB.ResizeTo(nClusters,nClusters);
771   }
772   
773   // Define variables
774   AliMUONVCluster *cluster1, *cluster2;
775   Int_t iCurrentCluster1, iCurrentCluster2;
776   
777   // Compute the covariance matrices
778   iCurrentCluster1 = 0;
779   for (Int_t iCluster1 = 0; iCluster1 < nClusters; iCluster1++) { 
780     cluster1 = ((AliMUONTrackParam*) fTrackParamAtCluster->UncheckedAt(iCluster1))->GetClusterPtr();
781     
782     if (cluster1 == discardedCluster) continue;
783     
784     // Loop over next clusters
785     iCurrentCluster2 = iCurrentCluster1;
786     for (Int_t iCluster2 = iCluster1; iCluster2 < nClusters; iCluster2++) {
787       cluster2 = ((AliMUONTrackParam*) fTrackParamAtCluster->UncheckedAt(iCluster2))->GetClusterPtr();
788       
789       if (cluster2 == discardedCluster) continue;
790       
791       // Fill with MCS covariances
792       clusterWeightsNB(iCurrentCluster1, iCurrentCluster2) = (*mcsCovariances)(iCluster1,iCluster2);
793       
794       // Equal contribution from multiple scattering in non bending and bending directions
795       clusterWeightsB(iCurrentCluster1, iCurrentCluster2) = clusterWeightsNB(iCurrentCluster1, iCurrentCluster2);
796       
797       // Add contribution from cluster resolution to diagonal element and symmetrize the matrix
798       if (iCurrentCluster1 == iCurrentCluster2) {
799         
800         // In non bending plane
801         clusterWeightsNB(iCurrentCluster1, iCurrentCluster1) += cluster1->GetErrX2();
802         // In bending plane
803         clusterWeightsB(iCurrentCluster1, iCurrentCluster1) += cluster1->GetErrY2();
804         
805       } else {
806         
807         // In non bending plane
808         clusterWeightsNB(iCurrentCluster2, iCurrentCluster1) = clusterWeightsNB(iCurrentCluster1, iCurrentCluster2);
809         // In bending plane
810         clusterWeightsB(iCurrentCluster2, iCurrentCluster1) = clusterWeightsB(iCurrentCluster1, iCurrentCluster2);
811         
812       }
813       
814       iCurrentCluster2++;
815     }
816     
817     iCurrentCluster1++;
818   }
819     
820   // Inversion of covariance matrices to get the weights
821   if (clusterWeightsNB.Determinant() != 0 && clusterWeightsB.Determinant() != 0) {
822     clusterWeightsNB.Invert();
823     clusterWeightsB.Invert();
824   } else {
825     AliWarning(" Determinant = 0");
826     clusterWeightsNB.ResizeTo(0,0);
827     clusterWeightsB.ResizeTo(0,0);
828     if(deleteMCSCov) delete mcsCovariances;
829     return kFALSE;
830   }
831   
832   if(deleteMCSCov) delete mcsCovariances;
833   
834   return kTRUE;
835   
836 }
837
838   //__________________________________________________________________________
839 void AliMUONTrack::ComputeMCSCovariances(TMatrixD& mcsCovariances) const
840 {
841   /// Compute the multiple scattering covariance matrix
842   /// (assume that track parameters at each cluster are corrects)
843   AliDebug(1,"Enter ComputeMCSCovariances");
844   
845   // Reset the size of the covariance matrix if needed
846   Int_t nClusters = GetNClusters();
847   if (mcsCovariances.GetNrows() != nClusters) mcsCovariances.ResizeTo(nClusters,nClusters);
848   
849   // Define variables
850   Int_t nChambers = AliMUONConstants::NTrackingCh();
851   AliMUONTrackParam* trackParamAtCluster;
852   AliMUONTrackParam extrapTrackParam;
853   Int_t currentChamber = 0, expectedChamber = 0, size = 0;
854   Double_t *mcsAngle2 = new Double_t[2*nChambers];
855   Double_t *zMCS = new Double_t[2*nChambers];
856   Int_t *indices = new Int_t[2*nClusters];
857   
858   // Compute multiple scattering dispersion angle at each chamber
859   // and save the z position where it is calculated
860   for (Int_t iCluster = 0; iCluster < nClusters; iCluster++) {
861     trackParamAtCluster = (AliMUONTrackParam*) fTrackParamAtCluster->UncheckedAt(iCluster);
862     
863     // look for missing chambers if any
864     currentChamber = trackParamAtCluster->GetClusterPtr()->GetChamberId();
865     while (currentChamber > expectedChamber) {
866       
867       // Save the z position where MCS dispersion is calculated
868       zMCS[size] = AliMUONConstants::DefaultChamberZ(expectedChamber);
869       
870       // Do not take into account MCS in chambers prior the first cluster
871       if (iCluster > 0) {
872         
873         // Get track parameters at missing chamber z
874         extrapTrackParam = *trackParamAtCluster;
875         AliMUONTrackExtrap::ExtrapToZ(&extrapTrackParam, zMCS[size]);
876         
877         // Save multiple scattering dispersion angle in missing chamber
878         mcsAngle2[size] = AliMUONTrackExtrap::GetMCSAngle2(extrapTrackParam,AliMUONConstants::ChamberThicknessInX0(),1.);
879         
880       } else mcsAngle2[size] = 0.;
881       
882       expectedChamber++;
883       size++;
884     }
885     
886     // Save z position where MCS dispersion is calculated
887     zMCS[size] = trackParamAtCluster->GetZ();
888     
889     // Save multiple scattering dispersion angle in current chamber
890     mcsAngle2[size] = AliMUONTrackExtrap::GetMCSAngle2(*trackParamAtCluster,AliMUONConstants::ChamberThicknessInX0(),1.);
891     
892     // Save indice in zMCS array corresponding to the current cluster
893     indices[iCluster] = size;
894     
895     expectedChamber = currentChamber + 1;
896     size++;
897   }
898   
899   // complete array of z if last cluster is on the last but one chamber
900   if (currentChamber != nChambers-1) zMCS[size++] = AliMUONConstants::DefaultChamberZ(nChambers-1);
901   
902   // Compute the covariance matrix
903   for (Int_t iCluster1 = 0; iCluster1 < nClusters; iCluster1++) { 
904     
905     for (Int_t iCluster2 = iCluster1; iCluster2 < nClusters; iCluster2++) {
906       
907       // Initialization to 0 (diagonal plus upper triangular part)
908       mcsCovariances(iCluster1,iCluster2) = 0.;
909       
910       // Compute contribution from multiple scattering in upstream chambers
911       for (Int_t k = 0; k < indices[iCluster1]; k++) {  
912         mcsCovariances(iCluster1,iCluster2) += (zMCS[indices[iCluster1]] - zMCS[k]) * (zMCS[indices[iCluster2]] - zMCS[k]) * mcsAngle2[k];
913       }
914       
915       // Symetrize the matrix
916       mcsCovariances(iCluster2,iCluster1) = mcsCovariances(iCluster1,iCluster2);
917     }
918     
919   }
920     
921   delete [] mcsAngle2;
922   delete [] zMCS;
923   delete [] indices;
924   
925 }
926
927   //__________________________________________________________________________
928 Int_t AliMUONTrack::ClustersInCommon(AliMUONTrack* track) const
929 {
930   /// Returns the number of clusters in common between the current track ("this")
931   /// and the track pointed to by "track".
932   if (!fTrackParamAtCluster || !this->fTrackParamAtCluster) return 0;
933   Int_t clustersInCommon = 0;
934   AliMUONTrackParam *trackParamAtCluster1, *trackParamAtCluster2;
935   // Loop over clusters of first track
936   trackParamAtCluster1 = (AliMUONTrackParam*) this->fTrackParamAtCluster->First();
937   while (trackParamAtCluster1) {
938     // Loop over clusters of second track
939     trackParamAtCluster2 = (AliMUONTrackParam*) track->fTrackParamAtCluster->First();
940     while (trackParamAtCluster2) {
941       // Increment "clustersInCommon" if both trackParamAtCluster1 & 2 point to the same cluster
942       if ((trackParamAtCluster1->GetClusterPtr()) == (trackParamAtCluster2->GetClusterPtr())) {
943         clustersInCommon++;
944         break;
945       }
946       trackParamAtCluster2 = (AliMUONTrackParam*) track->fTrackParamAtCluster->After(trackParamAtCluster2);
947     } // trackParamAtCluster2
948     trackParamAtCluster1 = (AliMUONTrackParam*) this->fTrackParamAtCluster->After(trackParamAtCluster1);
949   } // trackParamAtCluster1
950   return clustersInCommon;
951 }
952
953   //__________________________________________________________________________
954 Double_t AliMUONTrack::GetNormalizedChi2() const
955 {
956   /// return the chi2 value divided by the number of degrees of freedom (or 1.e10 if ndf < 0)
957   
958   Double_t numberOfDegFree = (2. * GetNClusters() - 5.);
959   if (numberOfDegFree > 0.) return fGlobalChi2 / numberOfDegFree;
960   else return fGlobalChi2; // system is under-constraint
961 }
962
963   //__________________________________________________________________________
964 Bool_t* AliMUONTrack::CompatibleTrack(AliMUONTrack *track, Double_t sigmaCut) const
965 {
966   /// for each chamber: return kTRUE (kFALSE) if clusters are compatible (not compatible)
967   AliMUONTrackParam *trackParamAtCluster1, *trackParamAtCluster2;
968   AliMUONVCluster *cluster1, *cluster2;
969   Double_t chi2, dX, dY, dZ;
970   Double_t chi2Max = sigmaCut * sigmaCut;
971   Double_t dZMax = 1.; // 1 cm
972   
973   Bool_t *compatibleCluster = new Bool_t[AliMUONConstants::NTrackingCh()]; 
974   for ( Int_t ch = 0; ch < AliMUONConstants::NTrackingCh(); ch++) compatibleCluster[ch] = kFALSE;
975
976   if (!fTrackParamAtCluster || !this->fTrackParamAtCluster) return compatibleCluster;
977   
978   // Loop over clusters of first track
979   trackParamAtCluster1 = (AliMUONTrackParam*) this->fTrackParamAtCluster->First();
980   while (trackParamAtCluster1) {
981     
982     cluster1 = trackParamAtCluster1->GetClusterPtr();
983     
984     // Loop over clusters of second track
985     trackParamAtCluster2 = (AliMUONTrackParam*) track->fTrackParamAtCluster->First();
986     while (trackParamAtCluster2) {
987       
988       cluster2 = trackParamAtCluster2->GetClusterPtr();
989       
990       //prepare next step
991       trackParamAtCluster2 = (AliMUONTrackParam*) track->fTrackParamAtCluster->After(trackParamAtCluster2);
992       
993       // z direction
994       dZ = cluster1->GetZ() - cluster2->GetZ();
995       if (dZ > dZMax) continue;
996       
997       // non bending direction
998       dX = cluster1->GetX() - cluster2->GetX();
999       chi2 = dX * dX / (cluster1->GetErrX2() + cluster2->GetErrX2());
1000       if (chi2 > chi2Max) continue;
1001       
1002       // bending direction
1003       dY = cluster1->GetY() - cluster2->GetY();
1004       chi2 = dY * dY / (cluster1->GetErrY2() + cluster2->GetErrY2());
1005       if (chi2 > chi2Max) continue;
1006       
1007       compatibleCluster[cluster1->GetChamberId()] = kTRUE;
1008       break;
1009     }
1010     
1011     trackParamAtCluster1 = (AliMUONTrackParam*) this->fTrackParamAtCluster->After(trackParamAtCluster1);
1012   }
1013   
1014   return compatibleCluster;
1015 }
1016
1017 //__________________________________________________________________________
1018 void AliMUONTrack::SetTrackParamAtVertex(const AliMUONTrackParam* trackParam)
1019 {
1020   /// set track parameters at vertex
1021   if (trackParam == 0x0) return;
1022   if (fTrackParamAtVertex) *fTrackParamAtVertex = *trackParam;
1023   else fTrackParamAtVertex = new AliMUONTrackParam(*trackParam);
1024 }
1025
1026 //__________________________________________________________________________
1027 void AliMUONTrack::RecursiveDump() const
1028 {
1029   /// Recursive dump of AliMUONTrack, i.e. with dump of trackParamAtCluster and attached clusters
1030   AliMUONTrackParam *trackParamAtCluster;
1031   AliMUONVCluster *cluster;
1032   cout << "Recursive dump of Track: " << this << endl;
1033   // Track
1034   this->Dump();
1035   for (Int_t iCluster = 0; iCluster < GetNClusters(); iCluster++) {
1036     trackParamAtCluster = (AliMUONTrackParam*) ((*fTrackParamAtCluster)[iCluster]);
1037     // trackParamAtCluster
1038     cout << "trackParamAtCluster: " << trackParamAtCluster << " (index: " << iCluster << ")" << endl;
1039     trackParamAtCluster->Dump();
1040     cluster = trackParamAtCluster->GetClusterPtr();
1041     // cluster
1042     cout << "cluster: " << cluster << endl;
1043     cluster->Print();
1044   }
1045   return;
1046 }
1047   
1048 //_____________________________________________-
1049 void AliMUONTrack::Print(Option_t*) const
1050 {
1051   /// Printing Track information 
1052
1053   cout << "<AliMUONTrack> No.Clusters=" << setw(2)   << GetNClusters() << 
1054       ", Match2Trig=" << setw(1) << GetMatchTrigger()  << 
1055       ", LoTrgNum=" << setw(3) << GetLoTrgNum()  << 
1056     ", Chi2-tracking-trigger=" << setw(8) << setprecision(5) <<  GetChi2MatchTrigger();
1057   cout << Form(" HitTriggerPattern %x",fHitsPatternInTrigCh) << endl;
1058   if (fTrackParamAtCluster) fTrackParamAtCluster->First()->Print("FULL");
1059 }
1060
1061 //__________________________________________________________________________
1062 void AliMUONTrack::SetLocalTrigger(Int_t loCirc, Int_t loStripX, Int_t loStripY, Int_t loDev, Int_t loLpt, Int_t loHpt)
1063 {
1064   /// pack the local trigger information and store
1065
1066   if (loCirc < 0) return;
1067
1068   fLocalTrigger = 0;
1069   fLocalTrigger += loCirc;
1070   fLocalTrigger += loStripX << 8;
1071   fLocalTrigger += loStripY << 13;
1072   fLocalTrigger += loDev    << 17;
1073   fLocalTrigger += loLpt    << 22;
1074   fLocalTrigger += loHpt    << 24;
1075
1076 }
1077