1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
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 **************************************************************************/
18 //-----------------------------------------------------------------------------
21 // Reconstructed track in ALICE dimuon spectrometer
22 //-----------------------------------------------------------------------------
24 #include "AliMUONTrack.h"
26 #include "AliMUONReconstructor.h"
27 #include "AliMUONVCluster.h"
28 #include "AliMUONVClusterStore.h"
29 #include "AliMUONObjectPair.h"
30 #include "AliMUONTrackExtrap.h"
31 #include "AliMUONConstants.h"
32 #include "AliMUONTrackParam.h"
38 #include <Riostream.h>
41 ClassImp(AliMUONTrack) // Class implementation in ROOT context
45 const Double_t AliMUONTrack::fgkMaxChi2 = 1.e10; ///< maximum chi2 above which the track can be considered as abnormal
48 //__________________________________________________________________________
49 AliMUONTrack::AliMUONTrack()
51 fTrackParamAtCluster(0x0),
52 fFitWithVertex(kFALSE),
55 fClusterWeightsNonBending(0x0),
56 fClusterWeightsBending(0x0),
60 fChi2MatchTrigger(0.),
62 fTrackParamAtVertex(0x0),
63 fHitsPatternInTrigCh(0),
67 /// Default constructor
68 fVertexErrXY2[0] = 0.;
69 fVertexErrXY2[1] = 0.;
72 //__________________________________________________________________________
73 AliMUONTrack::AliMUONTrack(AliMUONObjectPair *segment, Double_t bendingVertexDispersion)
75 fTrackParamAtCluster(new TObjArray(20)),
76 fFitWithVertex(kFALSE),
79 fClusterWeightsNonBending(0x0),
80 fClusterWeightsBending(0x0),
84 fChi2MatchTrigger(0.),
86 fTrackParamAtVertex(0x0),
87 fHitsPatternInTrigCh(0),
91 /// Constructor from two clusters
93 fTrackParamAtCluster->SetOwner(kTRUE);
95 fVertexErrXY2[0] = 0.;
96 fVertexErrXY2[1] = 0.;
98 // Pointers to clusters from the segment
99 AliMUONVCluster* firstCluster = (AliMUONVCluster*) segment->First();
100 AliMUONVCluster* lastCluster = (AliMUONVCluster*) segment->Second();
102 // Compute track parameters
103 Double_t z1 = firstCluster->GetZ();
104 Double_t z2 = lastCluster->GetZ();
105 Double_t dZ = z1 - z2;
107 Double_t nonBendingCoor1 = firstCluster->GetX();
108 Double_t nonBendingCoor2 = lastCluster->GetX();
109 Double_t nonBendingSlope = (nonBendingCoor1 - nonBendingCoor2) / dZ;
111 Double_t bendingCoor1 = firstCluster->GetY();
112 Double_t bendingCoor2 = lastCluster->GetY();
113 Double_t bendingSlope = (bendingCoor1 - bendingCoor2) / dZ;
114 // Inverse bending momentum
115 Double_t bendingImpact = bendingCoor1 - z1 * bendingSlope;
116 Double_t inverseBendingMomentum = 1. / AliMUONTrackExtrap::GetBendingMomentumFromImpactParam(bendingImpact);
118 // Set track parameters at first cluster
119 AliMUONTrackParam trackParamAtFirstCluster;
120 trackParamAtFirstCluster.SetZ(z1);
121 trackParamAtFirstCluster.SetNonBendingCoor(nonBendingCoor1);
122 trackParamAtFirstCluster.SetNonBendingSlope(nonBendingSlope);
123 trackParamAtFirstCluster.SetBendingCoor(bendingCoor1);
124 trackParamAtFirstCluster.SetBendingSlope(bendingSlope);
125 trackParamAtFirstCluster.SetInverseBendingMomentum(inverseBendingMomentum);
127 // Set track parameters at last cluster
128 AliMUONTrackParam trackParamAtLastCluster;
129 trackParamAtLastCluster.SetZ(z2);
130 trackParamAtLastCluster.SetNonBendingCoor(nonBendingCoor2);
131 trackParamAtLastCluster.SetNonBendingSlope(nonBendingSlope);
132 trackParamAtLastCluster.SetBendingCoor(bendingCoor2);
133 trackParamAtLastCluster.SetBendingSlope(bendingSlope);
134 trackParamAtLastCluster.SetInverseBendingMomentum(inverseBendingMomentum);
136 // Compute and set track parameters covariances at first cluster
137 TMatrixD paramCov(5,5);
140 paramCov(0,0) = firstCluster->GetErrX2();
141 paramCov(0,1) = firstCluster->GetErrX2() / dZ;
142 paramCov(1,0) = paramCov(0,1);
143 paramCov(1,1) = ( firstCluster->GetErrX2() + lastCluster->GetErrX2() ) / dZ / dZ;
145 paramCov(2,2) = firstCluster->GetErrY2();
146 paramCov(2,3) = firstCluster->GetErrY2() / dZ;
147 paramCov(3,2) = paramCov(2,3);
148 paramCov(3,3) = ( firstCluster->GetErrY2() + lastCluster->GetErrY2() ) / dZ / dZ;
149 // Inverse bending momentum (vertex resolution + bending slope resolution + 10% error on dipole parameters+field)
150 if (AliMUONTrackExtrap::IsFieldON()) {
151 paramCov(4,4) = ( ( bendingVertexDispersion*bendingVertexDispersion +
152 (z1 * z1 * lastCluster->GetErrY2() + z2 * z2 * firstCluster->GetErrY2()) / dZ / dZ) /
153 bendingImpact / bendingImpact + 0.1 * 0.1) * inverseBendingMomentum * inverseBendingMomentum ;
154 paramCov(2,4) = - z2 * firstCluster->GetErrY2() * inverseBendingMomentum / bendingImpact / dZ;
155 paramCov(4,2) = paramCov(2,4);
156 paramCov(3,4) = - (z1 * lastCluster->GetErrY2() + z2 * firstCluster->GetErrY2()) * inverseBendingMomentum / bendingImpact / dZ / dZ;
157 paramCov(4,3) = paramCov(3,4);
158 } else paramCov(4,4) = inverseBendingMomentum*inverseBendingMomentum;
159 trackParamAtFirstCluster.SetCovariances(paramCov);
161 // Compute and set track parameters covariances at last cluster
163 paramCov(0,0) = lastCluster->GetErrX2();
164 paramCov(0,1) = - lastCluster->GetErrX2() / dZ;
165 paramCov(1,0) = paramCov(0,1);
167 paramCov(2,2) = lastCluster->GetErrY2();
168 paramCov(2,3) = - lastCluster->GetErrY2() / dZ;
169 paramCov(3,2) = paramCov(2,3);
170 // Inverse bending momentum (vertex resolution + bending slope resolution + 10% error on dipole parameters+field)
171 if (AliMUONTrackExtrap::IsFieldON()) {
172 paramCov(2,4) = z1 * lastCluster->GetErrY2() * inverseBendingMomentum / bendingImpact / dZ;
173 paramCov(4,2) = paramCov(2,4);
175 trackParamAtLastCluster.SetCovariances(paramCov);
177 // Add track parameters at clusters
178 AddTrackParamAtCluster(trackParamAtFirstCluster,*firstCluster);
179 AddTrackParamAtCluster(trackParamAtLastCluster,*lastCluster);
183 //__________________________________________________________________________
184 AliMUONTrack::AliMUONTrack(const AliMUONTrack& track)
186 fTrackParamAtCluster(0x0),
187 fFitWithVertex(track.fFitWithVertex),
189 fFitWithMCS(track.fFitWithMCS),
190 fClusterWeightsNonBending(0x0),
191 fClusterWeightsBending(0x0),
192 fGlobalChi2(track.fGlobalChi2),
193 fImproved(track.fImproved),
194 fMatchTrigger(track.fMatchTrigger),
195 fChi2MatchTrigger(track.fChi2MatchTrigger),
196 fTrackID(track.fTrackID),
197 fTrackParamAtVertex(0x0),
198 fHitsPatternInTrigCh(track.fHitsPatternInTrigCh),
199 fLocalTrigger(track.fLocalTrigger),
200 fConnected(track.fConnected)
204 // necessary to make a copy of the objects and not only the pointers in TObjArray.
205 if (track.fTrackParamAtCluster) {
206 fTrackParamAtCluster = new TObjArray(track.fTrackParamAtCluster->GetSize());
207 fTrackParamAtCluster->SetOwner(kTRUE);
208 for (Int_t i = 0; i < track.GetNClusters(); i++)
209 fTrackParamAtCluster->AddLast(new AliMUONTrackParam(*static_cast<AliMUONTrackParam*>(track.fTrackParamAtCluster->UncheckedAt(i))));
212 // copy vertex resolution square used during the tracking procedure
213 fVertexErrXY2[0] = track.fVertexErrXY2[0];
214 fVertexErrXY2[1] = track.fVertexErrXY2[1];
216 // copy cluster weights matrices if any
217 if (track.fClusterWeightsNonBending) fClusterWeightsNonBending = new TMatrixD(*(track.fClusterWeightsNonBending));
218 if (track.fClusterWeightsBending) fClusterWeightsBending = new TMatrixD(*(track.fClusterWeightsBending));
220 // copy track parameters at vertex if any
221 if (track.fTrackParamAtVertex) fTrackParamAtVertex = new AliMUONTrackParam(*(track.fTrackParamAtVertex));
225 //__________________________________________________________________________
226 AliMUONTrack & AliMUONTrack::operator=(const AliMUONTrack& track)
228 /// Asignment operator
229 // check assignement to self
233 // base class assignement
234 TObject::operator=(track);
239 // necessary to make a copy of the objects and not only the pointers in TObjArray
240 if (track.fTrackParamAtCluster) {
241 fTrackParamAtCluster = new TObjArray(track.fTrackParamAtCluster->GetSize());
242 fTrackParamAtCluster->SetOwner(kTRUE);
243 for (Int_t i = 0; i < track.GetNClusters(); i++)
244 fTrackParamAtCluster->AddLast(new AliMUONTrackParam(*static_cast<AliMUONTrackParam*>(track.fTrackParamAtCluster->UncheckedAt(i))));
247 // copy cluster weights matrix if any
248 if (track.fClusterWeightsNonBending) {
249 if (fClusterWeightsNonBending) {
250 fClusterWeightsNonBending->ResizeTo(*(track.fClusterWeightsNonBending));
251 *fClusterWeightsNonBending = *(track.fClusterWeightsNonBending);
252 } else fClusterWeightsNonBending = new TMatrixD(*(track.fClusterWeightsNonBending));
255 // copy cluster weights matrix if any
256 if (track.fClusterWeightsBending) {
257 if (fClusterWeightsBending) {
258 fClusterWeightsBending->ResizeTo(*(track.fClusterWeightsBending));
259 *fClusterWeightsBending = *(track.fClusterWeightsBending);
260 } else fClusterWeightsBending = new TMatrixD(*(track.fClusterWeightsBending));
263 // copy track parameters at vertex if any
264 if (track.fTrackParamAtVertex) {
265 if (fTrackParamAtVertex) *fTrackParamAtVertex = *(track.fTrackParamAtVertex);
266 else fTrackParamAtVertex = new AliMUONTrackParam(*(track.fTrackParamAtVertex));
269 fFitWithVertex = track.fFitWithVertex;
270 fVertexErrXY2[0] = track.fVertexErrXY2[0];
271 fVertexErrXY2[1] = track.fVertexErrXY2[1];
272 fFitWithMCS = track.fFitWithMCS;
273 fGlobalChi2 = track.fGlobalChi2;
274 fImproved = track.fImproved;
275 fMatchTrigger = track.fMatchTrigger;
276 fChi2MatchTrigger = track.fChi2MatchTrigger;
277 fTrackID = track.fTrackID;
278 fHitsPatternInTrigCh = track.fHitsPatternInTrigCh;
279 fLocalTrigger = track.fLocalTrigger;
280 fConnected = track.fConnected;
285 //__________________________________________________________________________
286 AliMUONTrack::~AliMUONTrack()
289 delete fTrackParamAtCluster;
290 delete fClusterWeightsNonBending;
291 delete fClusterWeightsBending;
292 delete fTrackParamAtVertex;
295 //__________________________________________________________________________
296 void AliMUONTrack::Clear(Option_t* /*opt*/)
299 delete fTrackParamAtCluster; fTrackParamAtCluster = 0x0;
300 delete fClusterWeightsNonBending; fClusterWeightsNonBending = 0x0;
301 delete fClusterWeightsBending; fClusterWeightsBending = 0x0;
302 delete fTrackParamAtVertex; fTrackParamAtVertex = 0x0;
305 //__________________________________________________________________________
306 void AliMUONTrack::Reset()
308 /// Reset to default values
310 fFitWithVertex = kFALSE;
311 fVertexErrXY2[0] = 0.;
312 fVertexErrXY2[1] = 0.;
313 fFitWithMCS = kFALSE;
317 fChi2MatchTrigger = 0.;
319 fHitsPatternInTrigCh = 0;
322 delete fTrackParamAtCluster; fTrackParamAtCluster = 0x0;
323 delete fClusterWeightsNonBending; fClusterWeightsNonBending = 0x0;
324 delete fClusterWeightsBending; fClusterWeightsBending = 0x0;
325 delete fTrackParamAtVertex; fTrackParamAtVertex = 0x0;
328 //__________________________________________________________________________
329 TObjArray* AliMUONTrack::GetTrackParamAtCluster() const
331 /// return array of track parameters at cluster (create it if needed)
332 if (!fTrackParamAtCluster) {
333 fTrackParamAtCluster = new TObjArray(20);
334 fTrackParamAtCluster->SetOwner(kTRUE);
336 return fTrackParamAtCluster;
339 //__________________________________________________________________________
340 void AliMUONTrack::AddTrackParamAtCluster(const AliMUONTrackParam &trackParam, AliMUONVCluster &cluster, Bool_t copy)
342 /// Copy given track parameters into a new TrackParamAtCluster
343 /// Link parameters with the associated cluster
344 /// If copy=kTRUE: the cluster is copied then passed the trackParam which become its owner
345 /// otherwise: make sure to do not delete the cluster until it is used by the track
347 // check chamber ID of the associated cluster
348 if (cluster.GetChamberId() < 0 || cluster.GetChamberId() > AliMUONConstants::NTrackingCh()) {
349 AliError(Form("Chamber ID of the associated cluster is not valid (ChamberId=%d)",cluster.GetChamberId()));
353 // check whether track parameters are given at the correct cluster z position
354 if (TMath::Abs(cluster.GetZ() - trackParam.GetZ())>1.e-5) { // AU
355 AliError("track parameters are given at a different z position than the one of the associated cluster");
359 // add parameters to the array of track parameters
360 if (!fTrackParamAtCluster) {
361 fTrackParamAtCluster = new TObjArray(20);
362 fTrackParamAtCluster->SetOwner(kTRUE);
364 AliMUONTrackParam* trackParamAtCluster = new AliMUONTrackParam(trackParam);
365 fTrackParamAtCluster->AddLast(trackParamAtCluster);
367 // link parameters with the associated cluster or its copy
369 AliMUONVCluster *clusterCopy = static_cast<AliMUONVCluster*>(cluster.Clone());
370 trackParamAtCluster->SetClusterPtr(clusterCopy, kTRUE);
371 } else trackParamAtCluster->SetClusterPtr(&cluster);
373 // sort the array of track parameters
374 fTrackParamAtCluster->Sort();
377 //__________________________________________________________________________
378 void AliMUONTrack::RemoveTrackParamAtCluster(AliMUONTrackParam *trackParam)
380 /// Remove trackParam from the array of TrackParamAtCluster and delete it since the array is owner
382 if (fTrackParamAtCluster) {
384 AliMUONTrackParam* trackParamAtCluster = static_cast<AliMUONTrackParam*>(fTrackParamAtCluster->Remove(trackParam));
386 if (trackParamAtCluster) {
389 delete trackParamAtCluster;
392 fTrackParamAtCluster->Compress();
394 } else AliWarning("object to remove does not exist in array fTrackParamAtCluster");
396 } else AliWarning("array fTrackParamAtCluster does not exist");
400 //__________________________________________________________________________
401 Bool_t AliMUONTrack::UpdateTrackParamAtCluster()
403 /// Update track parameters at each attached cluster
404 /// Return kFALSE in case of failure (i.e. extrapolation problem)
406 Int_t nClusters = GetNClusters();
407 if (nClusters == 0) {
408 AliWarning("no cluster attached to the track");
412 Bool_t extrapStatus = kTRUE;
413 AliMUONTrackParam* startingTrackParam = static_cast<AliMUONTrackParam*>(fTrackParamAtCluster->UncheckedAt(0));
415 for (Int_t i = 1; i < nClusters; i++) {
416 AliMUONTrackParam* trackParamAtCluster = static_cast<AliMUONTrackParam*>(fTrackParamAtCluster->UncheckedAt(i));
418 // reset track parameters and their covariances
419 trackParamAtCluster->SetParameters(startingTrackParam->GetParameters());
420 trackParamAtCluster->SetZ(startingTrackParam->GetZ());
422 // extrapolation to the given z
423 if (!AliMUONTrackExtrap::ExtrapToZ(trackParamAtCluster, trackParamAtCluster->GetClusterPtr()->GetZ())) extrapStatus = kFALSE;
426 startingTrackParam = trackParamAtCluster;
429 // set global chi2 to max value in case of problem during track extrapolation
430 if (!extrapStatus) SetGlobalChi2(2.*MaxChi2());
435 //__________________________________________________________________________
436 Bool_t AliMUONTrack::UpdateCovTrackParamAtCluster()
438 /// Update track parameters and their covariances at each attached cluster
439 /// Include effects of multiple scattering in chambers
440 /// Return kFALSE in case of failure (i.e. extrapolation problem)
442 Int_t nClusters = GetNClusters();
443 if (nClusters == 0) {
444 AliWarning("no cluster attached to the track");
448 Bool_t extrapStatus = kTRUE;
449 AliMUONTrackParam* startingTrackParam = static_cast<AliMUONTrackParam*>(fTrackParamAtCluster->UncheckedAt(0));
450 Int_t expectedChamber = startingTrackParam->GetClusterPtr()->GetChamberId() + 1;
451 Int_t currentChamber;
453 for (Int_t i = 1; i < nClusters; i++) {
454 AliMUONTrackParam* trackParamAtCluster = static_cast<AliMUONTrackParam*>(fTrackParamAtCluster->UncheckedAt(i));
456 // reset track parameters and their covariances
457 trackParamAtCluster->SetParameters(startingTrackParam->GetParameters());
458 trackParamAtCluster->SetZ(startingTrackParam->GetZ());
459 trackParamAtCluster->SetCovariances(startingTrackParam->GetCovariances());
462 AliMUONTrackExtrap::AddMCSEffect(trackParamAtCluster,AliMUONConstants::ChamberThicknessInX0(expectedChamber-1),-1.);
464 // add MCS in missing chambers if any
465 currentChamber = trackParamAtCluster->GetClusterPtr()->GetChamberId();
466 while (currentChamber > expectedChamber) {
467 // extrapolation to the missing chamber
468 if (!AliMUONTrackExtrap::ExtrapToZCov(trackParamAtCluster, AliMUONConstants::DefaultChamberZ(expectedChamber))) extrapStatus = kFALSE;
470 AliMUONTrackExtrap::AddMCSEffect(trackParamAtCluster,AliMUONConstants::ChamberThicknessInX0(expectedChamber),-1.);
474 // extrapolation to the z of the current cluster
475 if (!AliMUONTrackExtrap::ExtrapToZCov(trackParamAtCluster, trackParamAtCluster->GetClusterPtr()->GetZ())) extrapStatus = kFALSE;
478 expectedChamber = currentChamber + 1;
479 startingTrackParam = trackParamAtCluster;
482 // set global chi2 to max value in case of problem during track extrapolation
483 if (!extrapStatus) SetGlobalChi2(2.*MaxChi2());
488 //__________________________________________________________________________
489 Bool_t AliMUONTrack::IsValid(UInt_t requestedStationMask, Bool_t request2ChInSameSt45)
491 /// check the validity of the current track:
492 /// at least one cluster per requested station
493 /// and at least 2 chambers in stations 4 & 5 that contain cluster(s)
494 /// + if request2ChInSameSt45 = kTRUE: 2 chambers hit in the same station (4 or 5)
496 Int_t nClusters = GetNClusters();
497 AliMUONTrackParam *trackParam;
498 Int_t currentCh, currentSt, previousCh = -1, nChHitInSt4 = 0, nChHitInSt5 = 0;
499 UInt_t presentStationMask(0);
501 // first loop over clusters
502 for (Int_t i = 0; i < nClusters; i++) {
503 trackParam = (AliMUONTrackParam*) fTrackParamAtCluster->UncheckedAt(i);
505 currentCh = trackParam->GetClusterPtr()->GetChamberId();
506 currentSt = currentCh/2;
508 // build present station mask
509 presentStationMask |= ( 1 << currentSt );
511 // count the number of chambers hit in station 4 that contain cluster(s)
512 if (currentSt == 3 && currentCh != previousCh) {
514 previousCh = currentCh;
517 // count the number of chambers hit in station 5 that contain cluster(s)
518 if (currentSt == 4 && currentCh != previousCh) {
520 previousCh = currentCh;
525 // at least one cluster per requested station
526 if ((requestedStationMask & presentStationMask) != requestedStationMask) return kFALSE;
528 // 2 chambers hit in the same station (4 or 5)
529 if (request2ChInSameSt45) return (nChHitInSt4 == 2 || nChHitInSt5 == 2);
530 // or 2 chambers hit in station 4 & 5 together
531 else return (nChHitInSt4+nChHitInSt5 >= 2);
535 //__________________________________________________________________________
536 void AliMUONTrack::TagRemovableClusters(UInt_t requestedStationMask) {
537 /// Identify clusters that can be removed from the track,
538 /// with the only requirements to have at least 1 cluster per requested station
539 /// and at least 2 chambers over 4 in stations 4 & 5 that contain cluster(s)
541 Int_t nClusters = GetNClusters();
542 AliMUONTrackParam *trackParam, *nextTrackParam;
543 Int_t currentCh, nextCh, currentSt, nextSt, previousCh = -1, nChHitInSt45 = 0;
545 // first loop over clusters
546 for (Int_t i = 0; i < nClusters; i++) {
547 trackParam = (AliMUONTrackParam*) fTrackParamAtCluster->UncheckedAt(i);
549 currentCh = trackParam->GetClusterPtr()->GetChamberId();
550 currentSt = currentCh/2;
552 // reset flags to kFALSE for all clusters in required station
553 if ((1 << currentSt) & requestedStationMask) trackParam->SetRemovable(kFALSE);
554 else trackParam->SetRemovable(kTRUE);
556 // count the number of chambers in station 4 & 5 that contain cluster(s)
557 if (currentCh > 5 && currentCh != previousCh) {
559 previousCh = currentCh;
564 // second loop over clusters
565 for (Int_t i = 0; i < nClusters; i++) {
566 trackParam = (AliMUONTrackParam*) fTrackParamAtCluster->UncheckedAt(i);
568 currentCh = trackParam->GetClusterPtr()->GetChamberId();
569 currentSt = currentCh/2;
571 // make sure they are more than 2 clusters in 2 different chambers of stations 4 & 5
572 // but 2 clusters in he same chamber will still be flagged as removable
573 if (nChHitInSt45 < 3 && currentSt > 2) {
575 if (i == nClusters-1) {
577 trackParam->SetRemovable(kFALSE);
581 nextTrackParam = (AliMUONTrackParam*) fTrackParamAtCluster->UncheckedAt(i+1);
582 nextCh = nextTrackParam->GetClusterPtr()->GetChamberId();
584 // set clusters in the same chamber as being removable
585 if (nextCh == currentCh) {
586 trackParam->SetRemovable(kTRUE);
587 nextTrackParam->SetRemovable(kTRUE);
588 i++; // skip cluster already checked
590 trackParam->SetRemovable(kFALSE);
597 // skip clusters already flag as removable
598 if (trackParam->IsRemovable()) continue;
600 // loop over next track parameters
601 for (Int_t j = i+1; j < nClusters; j++) {
602 nextTrackParam = (AliMUONTrackParam*) fTrackParamAtCluster->UncheckedAt(j);
604 nextCh = nextTrackParam->GetClusterPtr()->GetChamberId();
607 // set clusters in the same station as being removable
608 if (nextSt == currentSt) {
609 trackParam->SetRemovable(kTRUE);
610 nextTrackParam->SetRemovable(kTRUE);
611 i++; // skip cluster already checked
622 //__________________________________________________________________________
623 Bool_t AliMUONTrack::ComputeLocalChi2(Bool_t accountForMCS)
625 /// Compute each cluster contribution to the chi2 of the track
626 /// accounting for multiple scattering or not according to the flag
627 /// - Also recompute the weight matrices of the attached clusters if accountForMCS=kTRUE
628 /// - Assume that track parameters at each cluster are corrects
629 /// - Return kFALSE if computation failed
630 AliDebug(1,"Enter ComputeLocalChi2");
632 if (!fTrackParamAtCluster) {
633 AliWarning("no cluster attached to this track");
637 if (accountForMCS) { // Compute local chi2 taking into account multiple scattering effects
639 // Compute MCS covariance matrix only once
640 Int_t nClusters = GetNClusters();
641 TMatrixD mcsCovariances(nClusters,nClusters);
642 ComputeMCSCovariances(mcsCovariances);
644 // Make sure cluster weights are consistent with following calculations
645 if (!ComputeClusterWeights(&mcsCovariances)) {
646 AliWarning("cannot take into account the multiple scattering effects");
647 return ComputeLocalChi2(kFALSE);
650 // Compute chi2 of the track
651 Double_t globalChi2 = ComputeGlobalChi2(kTRUE);
652 if (globalChi2 < 0.) return kFALSE;
654 // Loop over removable clusters and compute their local chi2
655 AliMUONTrackParam* trackParamAtCluster;
656 AliMUONTrackParam* trackParamAtCluster1;
657 AliMUONVCluster *cluster, *discardedCluster;
658 Int_t iCluster1, iCluster2, iCurrentCluster1, iCurrentCluster2;
659 TMatrixD clusterWeightsNB(nClusters-1,nClusters-1);
660 TMatrixD clusterWeightsB(nClusters-1,nClusters-1);
661 Double_t *dX = new Double_t[nClusters-1];
662 Double_t *dY = new Double_t[nClusters-1];
663 Double_t globalChi2b;
664 for (Int_t iCluster = 0; iCluster < nClusters ; iCluster++) {
665 trackParamAtCluster = static_cast<AliMUONTrackParam*>(fTrackParamAtCluster->UncheckedAt(iCluster));
667 discardedCluster = trackParamAtCluster->GetClusterPtr();
669 // Recompute cluster weights without the current cluster
670 if (!ComputeClusterWeights(clusterWeightsNB, clusterWeightsB, &mcsCovariances, discardedCluster)) {
671 AliWarning("cannot take into account the multiple scattering effects");
674 return ComputeLocalChi2(kFALSE);
677 // Compute track chi2 without the current cluster
679 iCurrentCluster1 = 0;
680 for (iCluster1 = 0; iCluster1 < nClusters ; iCluster1++) {
681 trackParamAtCluster1 = (AliMUONTrackParam*) fTrackParamAtCluster->UncheckedAt(iCluster1);
682 cluster = trackParamAtCluster1->GetClusterPtr();
684 if (cluster == discardedCluster) continue;
686 // Compute and save residuals
687 dX[iCurrentCluster1] = cluster->GetX() - trackParamAtCluster1->GetNonBendingCoor();
688 dY[iCurrentCluster1] = cluster->GetY() - trackParamAtCluster1->GetBendingCoor();
690 iCurrentCluster2 = 0;
691 for (iCluster2 = 0; iCluster2 < iCluster1; iCluster2++) {
692 cluster = ((AliMUONTrackParam*) fTrackParamAtCluster->UncheckedAt(iCluster2))->GetClusterPtr();
694 if (cluster == discardedCluster) continue;
696 // Add contribution from covariances
697 globalChi2b += (clusterWeightsNB(iCurrentCluster1, iCurrentCluster2) +
698 clusterWeightsNB(iCurrentCluster2, iCurrentCluster1)) * dX[iCurrentCluster1] * dX[iCurrentCluster2] +
699 (clusterWeightsB(iCurrentCluster1, iCurrentCluster2) +
700 clusterWeightsB(iCurrentCluster2, iCurrentCluster1)) * dY[iCurrentCluster1] * dY[iCurrentCluster2];
705 // Add contribution from variances
706 globalChi2b += clusterWeightsNB(iCurrentCluster1, iCurrentCluster1) * dX[iCurrentCluster1] * dX[iCurrentCluster1] +
707 clusterWeightsB(iCurrentCluster1, iCurrentCluster1) * dY[iCurrentCluster1] * dY[iCurrentCluster1];
713 trackParamAtCluster->SetLocalChi2(globalChi2 - globalChi2b);
719 } else { // without multiple scattering effects
721 Int_t nClusters = GetNClusters();
722 AliMUONTrackParam* trackParamAtCluster;
723 AliMUONVCluster *discardedCluster;
725 for (Int_t iCluster = 0; iCluster < nClusters ; iCluster++) {
726 trackParamAtCluster = static_cast<AliMUONTrackParam*>(fTrackParamAtCluster->UncheckedAt(iCluster));
728 discardedCluster = trackParamAtCluster->GetClusterPtr();
731 dX = discardedCluster->GetX() - trackParamAtCluster->GetNonBendingCoor();
732 dY = discardedCluster->GetY() - trackParamAtCluster->GetBendingCoor();
735 trackParamAtCluster->SetLocalChi2(dX * dX / discardedCluster->GetErrX2() + dY * dY / discardedCluster->GetErrY2());
744 //__________________________________________________________________________
745 Double_t AliMUONTrack::ComputeGlobalChi2(Bool_t accountForMCS)
747 /// Compute the chi2 of the track accounting for multiple scattering or not according to the flag
748 /// - Assume that track parameters at each cluster are corrects
749 /// - Assume the cluster weights matrices are corrects
750 /// - Return a value of chi2 higher than the maximum allowed if computation failed
751 AliDebug(1,"Enter ComputeGlobalChi2");
753 if (!fTrackParamAtCluster) {
754 AliWarning("no cluster attached to this track");
762 // Check the weight matrices. If weight matrices are not available compute chi2 without MCS
763 if (!fClusterWeightsNonBending || !fClusterWeightsBending) {
764 AliWarning("cluster weights including multiple scattering effects are not available\n\t\t --> compute chi2 WITHOUT multiple scattering");
765 return ComputeGlobalChi2(kFALSE);
767 Int_t nClusters = GetNClusters();
768 if (fClusterWeightsNonBending->GetNrows() != nClusters || fClusterWeightsBending->GetNcols() != nClusters) {
769 AliWarning("cluster weights including multiple scattering effects are not available\n\t\t --> compute chi2 WITHOUT multiple scattering");
770 return ComputeGlobalChi2(kFALSE);
774 AliMUONVCluster *cluster;
775 Double_t *dX = new Double_t[nClusters];
776 Double_t *dY = new Double_t[nClusters];
777 AliMUONTrackParam* trackParamAtCluster;
778 for (Int_t iCluster1 = 0; iCluster1 < nClusters; iCluster1++) {
779 trackParamAtCluster = (AliMUONTrackParam*) fTrackParamAtCluster->UncheckedAt(iCluster1);
780 cluster = trackParamAtCluster->GetClusterPtr();
781 dX[iCluster1] = cluster->GetX() - trackParamAtCluster->GetNonBendingCoor();
782 dY[iCluster1] = cluster->GetY() - trackParamAtCluster->GetBendingCoor();
783 for (Int_t iCluster2 = 0; iCluster2 < iCluster1; iCluster2++) {
784 chi2 += ((*fClusterWeightsNonBending)(iCluster1, iCluster2) + (*fClusterWeightsNonBending)(iCluster2, iCluster1)) * dX[iCluster1] * dX[iCluster2] +
785 ((*fClusterWeightsBending)(iCluster1, iCluster2) + (*fClusterWeightsBending)(iCluster2, iCluster1)) * dY[iCluster1] * dY[iCluster2];
787 chi2 += ((*fClusterWeightsNonBending)(iCluster1, iCluster1) * dX[iCluster1] * dX[iCluster1]) +
788 ((*fClusterWeightsBending)(iCluster1, iCluster1) * dY[iCluster1] * dY[iCluster1]);
795 AliMUONVCluster *cluster;
797 AliMUONTrackParam* trackParamAtCluster;
798 Int_t nClusters = GetNClusters();
799 for (Int_t iCluster = 0; iCluster < nClusters ; iCluster++) {
800 trackParamAtCluster = (AliMUONTrackParam*) fTrackParamAtCluster->UncheckedAt(iCluster);
801 cluster = trackParamAtCluster->GetClusterPtr();
802 dX = cluster->GetX() - trackParamAtCluster->GetNonBendingCoor();
803 dY = cluster->GetY() - trackParamAtCluster->GetBendingCoor();
804 chi2 += dX * dX / cluster->GetErrX2() + dY * dY / cluster->GetErrY2();
813 //__________________________________________________________________________
814 Bool_t AliMUONTrack::ComputeClusterWeights(TMatrixD* mcsCovariances)
816 /// Compute the weight matrices of the attached clusters, in non bending and bending direction,
817 /// accounting for multiple scattering correlations and cluster resolution
818 /// - Use the provided MCS covariance matrix if any (otherwise build it temporarily)
819 /// - Assume that track parameters at each cluster are corrects
820 /// - Return kFALSE if computation failed
821 AliDebug(1,"Enter ComputeClusterWeights1");
823 if (!fTrackParamAtCluster) {
824 AliWarning("no cluster attached to this track");
829 Int_t nClusters = GetNClusters();
830 if (!fClusterWeightsNonBending) fClusterWeightsNonBending = new TMatrixD(nClusters,nClusters);
831 if (!fClusterWeightsBending) fClusterWeightsBending = new TMatrixD(nClusters,nClusters);
833 // Compute weights matrices
834 if (!ComputeClusterWeights(*fClusterWeightsNonBending, *fClusterWeightsBending, mcsCovariances)) return kFALSE;
840 //__________________________________________________________________________
841 Bool_t AliMUONTrack::ComputeClusterWeights(TMatrixD& clusterWeightsNB, TMatrixD& clusterWeightsB,
842 TMatrixD* mcsCovariances, const AliMUONVCluster* discardedCluster) const
844 /// Compute the weight matrices, in non bending and bending direction,
845 /// of the other attached clusters assuming the discarded one does not exist
846 /// accounting for multiple scattering correlations and cluster resolution
847 /// - Use the provided MCS covariance matrix if any (otherwise build it temporarily)
848 /// - Return kFALSE if computation failed
849 AliDebug(1,"Enter ComputeClusterWeights2");
851 // Check MCS covariance matrix and recompute it if need
852 Int_t nClusters = GetNClusters();
853 Bool_t deleteMCSCov = kFALSE;
854 if (!mcsCovariances) {
855 mcsCovariances = new TMatrixD(nClusters,nClusters);
856 deleteMCSCov = kTRUE;
857 ComputeMCSCovariances(*mcsCovariances);
860 // Resize the weights matrices; alocate memory
861 if (discardedCluster) {
862 clusterWeightsNB.ResizeTo(nClusters-1,nClusters-1);
863 clusterWeightsB.ResizeTo(nClusters-1,nClusters-1);
865 clusterWeightsNB.ResizeTo(nClusters,nClusters);
866 clusterWeightsB.ResizeTo(nClusters,nClusters);
870 AliMUONVCluster *cluster1, *cluster2;
871 Int_t iCurrentCluster1, iCurrentCluster2;
873 // Compute the covariance matrices
874 iCurrentCluster1 = 0;
875 for (Int_t iCluster1 = 0; iCluster1 < nClusters; iCluster1++) {
876 cluster1 = ((AliMUONTrackParam*) fTrackParamAtCluster->UncheckedAt(iCluster1))->GetClusterPtr();
878 if (cluster1 == discardedCluster) continue;
880 // Loop over next clusters
881 iCurrentCluster2 = iCurrentCluster1;
882 for (Int_t iCluster2 = iCluster1; iCluster2 < nClusters; iCluster2++) {
883 cluster2 = ((AliMUONTrackParam*) fTrackParamAtCluster->UncheckedAt(iCluster2))->GetClusterPtr();
885 if (cluster2 == discardedCluster) continue;
887 // Fill with MCS covariances
888 clusterWeightsNB(iCurrentCluster1, iCurrentCluster2) = (*mcsCovariances)(iCluster1,iCluster2);
890 // Equal contribution from multiple scattering in non bending and bending directions
891 clusterWeightsB(iCurrentCluster1, iCurrentCluster2) = clusterWeightsNB(iCurrentCluster1, iCurrentCluster2);
893 // Add contribution from cluster resolution to diagonal element and symmetrize the matrix
894 if (iCurrentCluster1 == iCurrentCluster2) {
896 // In non bending plane
897 clusterWeightsNB(iCurrentCluster1, iCurrentCluster1) += cluster1->GetErrX2();
899 clusterWeightsB(iCurrentCluster1, iCurrentCluster1) += cluster1->GetErrY2();
903 // In non bending plane
904 clusterWeightsNB(iCurrentCluster2, iCurrentCluster1) = clusterWeightsNB(iCurrentCluster1, iCurrentCluster2);
906 clusterWeightsB(iCurrentCluster2, iCurrentCluster1) = clusterWeightsB(iCurrentCluster1, iCurrentCluster2);
916 // Inversion of covariance matrices to get the weights
917 if (clusterWeightsNB.Determinant() != 0 && clusterWeightsB.Determinant() != 0) {
918 clusterWeightsNB.Invert();
919 clusterWeightsB.Invert();
921 AliWarning(" Determinant = 0");
922 clusterWeightsNB.ResizeTo(0,0);
923 clusterWeightsB.ResizeTo(0,0);
924 if(deleteMCSCov) delete mcsCovariances;
928 if(deleteMCSCov) delete mcsCovariances;
934 //__________________________________________________________________________
935 void AliMUONTrack::ComputeMCSCovariances(TMatrixD& mcsCovariances) const
937 /// Compute the multiple scattering covariance matrix
938 /// (assume that track parameters at each cluster are corrects)
939 AliDebug(1,"Enter ComputeMCSCovariances");
941 // Reset the size of the covariance matrix if needed
942 Int_t nClusters = GetNClusters();
943 if (mcsCovariances.GetNrows() != nClusters) mcsCovariances.ResizeTo(nClusters,nClusters);
946 Int_t nChambers = AliMUONConstants::NTrackingCh();
947 AliMUONTrackParam* trackParamAtCluster;
948 AliMUONTrackParam extrapTrackParam;
949 Int_t currentChamber = 0, expectedChamber = 0, size = 0;
950 Double_t *mcsAngle2 = new Double_t[2*nChambers];
951 Double_t *zMCS = new Double_t[2*nChambers];
952 Int_t *indices = new Int_t[2*nClusters];
954 // Compute multiple scattering dispersion angle at each chamber
955 // and save the z position where it is calculated
956 for (Int_t iCluster = 0; iCluster < nClusters; iCluster++) {
957 trackParamAtCluster = (AliMUONTrackParam*) fTrackParamAtCluster->UncheckedAt(iCluster);
959 // look for missing chambers if any
960 currentChamber = trackParamAtCluster->GetClusterPtr()->GetChamberId();
961 while (currentChamber > expectedChamber) {
963 // Save the z position where MCS dispersion is calculated
964 zMCS[size] = AliMUONConstants::DefaultChamberZ(expectedChamber);
966 // Do not take into account MCS in chambers prior the first cluster
969 // Get track parameters at missing chamber z
970 extrapTrackParam = *trackParamAtCluster;
971 AliMUONTrackExtrap::ExtrapToZ(&extrapTrackParam, zMCS[size]);
973 // Save multiple scattering dispersion angle in missing chamber
974 mcsAngle2[size] = AliMUONTrackExtrap::GetMCSAngle2(extrapTrackParam,AliMUONConstants::ChamberThicknessInX0(expectedChamber),1.);
976 } else mcsAngle2[size] = 0.;
982 // Save z position where MCS dispersion is calculated
983 zMCS[size] = trackParamAtCluster->GetZ();
985 // Save multiple scattering dispersion angle in current chamber
986 mcsAngle2[size] = AliMUONTrackExtrap::GetMCSAngle2(*trackParamAtCluster,AliMUONConstants::ChamberThicknessInX0(currentChamber),1.);
988 // Save indice in zMCS array corresponding to the current cluster
989 indices[iCluster] = size;
991 expectedChamber = currentChamber + 1;
995 // complete array of z if last cluster is on the last but one chamber
996 if (currentChamber != nChambers-1) zMCS[size++] = AliMUONConstants::DefaultChamberZ(nChambers-1);
998 // Compute the covariance matrix
999 for (Int_t iCluster1 = 0; iCluster1 < nClusters; iCluster1++) {
1001 for (Int_t iCluster2 = iCluster1; iCluster2 < nClusters; iCluster2++) {
1003 // Initialization to 0 (diagonal plus upper triangular part)
1004 mcsCovariances(iCluster1,iCluster2) = 0.;
1006 // Compute contribution from multiple scattering in upstream chambers
1007 for (Int_t k = 0; k < indices[iCluster1]; k++) {
1008 mcsCovariances(iCluster1,iCluster2) += (zMCS[indices[iCluster1]] - zMCS[k]) * (zMCS[indices[iCluster2]] - zMCS[k]) * mcsAngle2[k];
1011 // Symetrize the matrix
1012 mcsCovariances(iCluster2,iCluster1) = mcsCovariances(iCluster1,iCluster2);
1017 delete [] mcsAngle2;
1023 //__________________________________________________________________________
1024 Int_t AliMUONTrack::ClustersInCommon(AliMUONTrack* track, Int_t stMin, Int_t stMax) const
1026 /// Returns the number of clusters in common in stations [stMin, stMax]
1027 /// between the current track ("this") and the track pointed to by "track".
1029 if (!track || !track->fTrackParamAtCluster || !this->fTrackParamAtCluster) return 0;
1031 Int_t chMin = 2 * stMin;
1032 Int_t chMax = 2 * stMax + 1;
1033 Int_t clustersInCommon = 0;
1035 // Loop over clusters of first track
1036 Int_t nCl1 = this->GetNClusters();
1037 for(Int_t iCl1 = 0; iCl1 < nCl1; iCl1++) {
1038 AliMUONVCluster* cl1 = ((AliMUONTrackParam*) this->fTrackParamAtCluster->UncheckedAt(iCl1))->GetClusterPtr();
1040 Int_t chCl1 = cl1->GetChamberId();
1041 if (chCl1 < chMin || chCl1 > chMax) continue;
1043 // Loop over clusters of second track
1044 Int_t nCl2 = track->GetNClusters();
1045 for(Int_t iCl2 = 0; iCl2 < nCl2; iCl2++) {
1046 AliMUONVCluster* cl2 = ((AliMUONTrackParam*) track->fTrackParamAtCluster->UncheckedAt(iCl2))->GetClusterPtr();
1048 Int_t chCl2 = cl2->GetChamberId();
1049 if (chCl2 < chMin || chCl2 > chMax) continue;
1051 // Increment "clustersInCommon" if both clusters have the same ID
1052 if (cl1->GetUniqueID() == cl2->GetUniqueID()) {
1061 return clustersInCommon;
1064 //__________________________________________________________________________
1065 Int_t AliMUONTrack::GetNDF() const
1067 /// return the number of degrees of freedom
1069 Int_t ndf = 2 * GetNClusters() - 5;
1070 return (ndf > 0) ? ndf : 0;
1073 //__________________________________________________________________________
1074 Double_t AliMUONTrack::GetNormalizedChi2() const
1076 /// return the chi2 value divided by the number of degrees of freedom (or FLT_MAX if ndf <= 0)
1078 Double_t ndf = (Double_t) GetNDF();
1079 return (ndf > 0.) ? fGlobalChi2 / ndf : 2.*MaxChi2();
1082 //__________________________________________________________________________
1083 Int_t AliMUONTrack::FindCompatibleClusters(const AliMUONTrack &track, Double_t sigmaCut, Bool_t compatibleCluster[10]) const
1085 /// Try to match clusters from this track with clusters from the given track within the provided sigma cut:
1086 /// - Fill the array compatibleCluster[iCh] with kTRUE if a compatible cluster has been found in chamber iCh.
1087 /// - Return the number of clusters of "this" track matched with one cluster of the given track.
1088 AliMUONVCluster *cluster1, *cluster2;
1089 Double_t chi2, dX, dY;
1090 Double_t chi2Max = sigmaCut * sigmaCut;
1093 Int_t nMatchClusters = 0;
1094 for ( Int_t ch = 0; ch < AliMUONConstants::NTrackingCh(); ch++) compatibleCluster[ch] = kFALSE;
1096 if (!track.fTrackParamAtCluster || !this->fTrackParamAtCluster) return nMatchClusters;
1098 // Loop over clusters of first track
1099 Int_t nCl1 = this->GetNClusters();
1100 for(Int_t iCl1 = 0; iCl1 < nCl1; iCl1++) {
1101 cluster1 = static_cast<AliMUONTrackParam*>(this->fTrackParamAtCluster->UncheckedAt(iCl1))->GetClusterPtr();
1103 // Loop over clusters of second track
1104 Int_t nCl2 = track.GetNClusters();
1105 for(Int_t iCl2 = 0; iCl2 < nCl2; iCl2++) {
1106 cluster2 = static_cast<AliMUONTrackParam*>(track.fTrackParamAtCluster->UncheckedAt(iCl2))->GetClusterPtr();
1109 if (cluster1->GetDetElemId() != cluster2->GetDetElemId()) continue;
1112 dX = cluster1->GetX() - cluster2->GetX();
1113 dY = cluster1->GetY() - cluster2->GetY();
1114 chi2 = dX * dX / (cluster1->GetErrX2() + cluster2->GetErrX2()) + dY * dY / (cluster1->GetErrY2() + cluster2->GetErrY2());
1115 if (chi2 > 2. * chi2Max) continue; // 2 because 2 quantities in chi2
1117 compatibleCluster[cluster1->GetChamberId()] = kTRUE;
1124 return nMatchClusters;
1127 //__________________________________________________________________________
1128 Bool_t AliMUONTrack::Match(AliMUONTrack &track, Double_t sigmaCut, Int_t &nMatchClusters) const
1130 /// Try to match this track with the given track. Matching conditions:
1131 /// - more than 50% of clusters from this track matched with clusters from the given track
1132 /// - at least 1 cluster matched before and 1 cluster matched after the dipole
1134 Bool_t compTrack[10];
1135 nMatchClusters = FindCompatibleClusters(track, sigmaCut, compTrack);
1137 if ((compTrack[0] || compTrack[1] || compTrack[2] || compTrack[3]) && // at least 1 cluster matched in st 1 & 2
1138 (compTrack[6] || compTrack[7] || compTrack[8] || compTrack[9]) && // at least 1 cluster matched in st 4 & 5
1139 2 * nMatchClusters > GetNClusters()) return kTRUE; // more than 50% of clusters matched
1144 //__________________________________________________________________________
1145 void AliMUONTrack::SetTrackParamAtVertex(const AliMUONTrackParam* trackParam)
1147 /// set track parameters at vertex
1148 if (trackParam == 0x0) return;
1149 if (fTrackParamAtVertex) *fTrackParamAtVertex = *trackParam;
1150 else fTrackParamAtVertex = new AliMUONTrackParam(*trackParam);
1153 //__________________________________________________________________________
1154 void AliMUONTrack::RecursiveDump() const
1156 /// Recursive dump of AliMUONTrack, i.e. with dump of trackParamAtCluster and attached clusters
1157 AliMUONTrackParam *trackParamAtCluster;
1158 AliMUONVCluster *cluster;
1159 cout << "Recursive dump of Track: " << this << endl;
1162 for (Int_t iCluster = 0; iCluster < GetNClusters(); iCluster++) {
1163 trackParamAtCluster = (AliMUONTrackParam*) ((*fTrackParamAtCluster)[iCluster]);
1164 // trackParamAtCluster
1165 cout << "trackParamAtCluster: " << trackParamAtCluster << " (index: " << iCluster << ")" << endl;
1166 trackParamAtCluster->Dump();
1167 cluster = trackParamAtCluster->GetClusterPtr();
1169 cout << "cluster: " << cluster << endl;
1175 //_____________________________________________-
1176 void AliMUONTrack::Print(Option_t*) const
1178 /// Printing Track information
1180 streamsize curW = cout.width();
1181 streamsize curPrecision = cout.precision();
1182 cout << "<AliMUONTrack> No.Clusters=" << setw(2) << GetNClusters() <<
1183 ", Match2Trig=" << setw(1) << GetMatchTrigger() <<
1184 ", LoTrgNum=" << setw(3) << LoCircuit() <<
1185 ", Chi2-tracking-trigger=" << setw(8) << setprecision(5) << GetChi2MatchTrigger();
1186 cout << Form(" HitTriggerPattern %x",fHitsPatternInTrigCh);
1187 cout << Form(" MClabel=%d",fTrackID) << endl;
1188 if (fTrackParamAtCluster) fTrackParamAtCluster->First()->Print("FULL");
1190 cout.precision(curPrecision);
1193 //__________________________________________________________________________
1194 void AliMUONTrack::SetLocalTrigger(Int_t loCirc, Int_t loStripX, Int_t loStripY, Int_t loDev, Int_t loLpt, Int_t loHpt, UChar_t respWithoutChamber)
1196 /// pack the local trigger information and store
1198 if (loCirc < 0) return;
1201 fLocalTrigger += loCirc;
1202 fLocalTrigger += loStripX << 8;
1203 fLocalTrigger += loStripY << 13;
1204 fLocalTrigger += loDev << 17;
1205 fLocalTrigger += loLpt << 22;
1206 fLocalTrigger += loHpt << 24;
1207 fLocalTrigger += respWithoutChamber << 26;
1211 //__________________________________________________________________________
1212 void AliMUONTrack::FindMCLabel()
1214 /// Determine the MC label from the label of the attached clusters and fill fMCLabel data member:
1215 /// More than 50% of clusters, including 1 before and 1 after the dipole, must share the same label
1217 Int_t nClusters = GetNClusters();
1218 Int_t halfCluster = nClusters/2;
1223 // loop over first clusters (if nClusters left < (nClusters-halfCluster) the conditions cannot be fulfilled)
1224 for (Int_t iCluster1 = 0; iCluster1 < nClusters-halfCluster; iCluster1++) {
1225 AliMUONVCluster* cluster1 = ((AliMUONTrackParam*) fTrackParamAtCluster->UncheckedAt(iCluster1))->GetClusterPtr();
1227 // if the first cluster is not on station 1 or 2 the conditions cannot be fulfilled
1228 if (cluster1->GetChamberId() > 3) return;
1230 Int_t label1 = cluster1->GetMCLabel();
1231 if (label1 < 0) continue;
1233 Int_t nIdenticalLabel = 1;
1235 // Loop over next clusters
1236 for (Int_t iCluster2 = iCluster1+1; iCluster2 < nClusters; iCluster2++) {
1237 AliMUONVCluster* cluster2 = ((AliMUONTrackParam*) fTrackParamAtCluster->UncheckedAt(iCluster2))->GetClusterPtr();
1239 if (cluster2->GetMCLabel() != label1) continue;
1243 // stop as soon as conditions are fulfilled
1244 if (nIdenticalLabel > halfCluster && cluster2->GetChamberId() > 5) {