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