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