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