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