]> git.uio.no Git - u/mrichter/AliRoot.git/blame - MUON/AliMUONTrack.cxx
AliEveTrackCounter, AliEveTrackCounterEditor
[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 //__________________________________________________________________________
a0dc65b4 70AliMUONTrack::AliMUONTrack(AliMUONObjectPair *segment, Double_t bendingVertexDispersion)
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)
a0dc65b4 145 paramCov(4,4) = ( ( bendingVertexDispersion*bendingVertexDispersion +
9bf6860b 146 (z1 * z1 * lastCluster->GetErrY2() + z2 * z2 * firstCluster->GetErrY2()) / dZ / dZ) /
a0dc65b4 147 bendingImpact / bendingImpact + 0.1 * 0.1) * inverseBendingMomentum * inverseBendingMomentum ;
9bf6860b 148 paramCov(2,4) = - z2 * firstCluster->GetErrY2() * inverseBendingMomentum / bendingImpact / dZ;
149 paramCov(4,2) = paramCov(2,4);
150 paramCov(3,4) = - (z1 * lastCluster->GetErrY2() + z2 * firstCluster->GetErrY2()) * inverseBendingMomentum / bendingImpact / dZ / dZ;
151 paramCov(4,3) = paramCov(3,4);
ea94c18b 152
ea94c18b 153 // Set covariances
9bf6860b 154 trackParamAtFirstCluster.SetCovariances(paramCov);
ea94c18b 155
9bf6860b 156 // Compute and set track parameters covariances at last cluster
157 paramCov(1,0) = - paramCov(1,0);
158 paramCov(0,1) = - paramCov(0,1);
159 paramCov(3,2) = - paramCov(3,2);
160 paramCov(2,3) = - paramCov(2,3);
161 paramCov(2,4) = z1 * lastCluster->GetErrY2() * inverseBendingMomentum / bendingImpact / dZ;
162 paramCov(4,2) = paramCov(2,4);
163 trackParamAtLastCluster.SetCovariances(paramCov);
ea94c18b 164
96ebe67e 165 // Add track parameters at clusters
166 AddTrackParamAtCluster(trackParamAtFirstCluster,*firstCluster);
167 AddTrackParamAtCluster(trackParamAtLastCluster,*lastCluster);
de2cd600 168
a9e2aefa 169}
170
61fed964 171//__________________________________________________________________________
96ebe67e 172AliMUONTrack::AliMUONTrack(const AliMUONTrack& track)
ea94c18b 173 : TObject(track),
7332f213 174 fTrackParamAtCluster(0x0),
ea94c18b 175 fFitWithVertex(track.fFitWithVertex),
96ebe67e 176 fVertexErrXY2(),
ea94c18b 177 fFitWithMCS(track.fFitWithMCS),
96ebe67e 178 fClusterWeightsNonBending(0x0),
179 fClusterWeightsBending(0x0),
ea94c18b 180 fGlobalChi2(track.fGlobalChi2),
181 fImproved(track.fImproved),
182 fMatchTrigger(track.fMatchTrigger),
183 floTrgNum(track.floTrgNum),
184 fChi2MatchTrigger(track.fChi2MatchTrigger),
185 fTrackID(track.fTrackID),
96ebe67e 186 fTrackParamAtVertex(0x0),
ea94c18b 187 fHitsPatternInTrigCh(track.fHitsPatternInTrigCh),
188 fLocalTrigger(track.fLocalTrigger)
a9e2aefa 189{
2457f726 190 ///copy constructor
de2cd600 191
e516b01d 192 // necessary to make a copy of the objects and not only the pointers in TClonesArray.
7332f213 193 if (track.fTrackParamAtCluster) {
194 fTrackParamAtCluster = new TClonesArray("AliMUONTrackParam",10);
195 AliMUONTrackParam *trackParamAtCluster = (AliMUONTrackParam*) track.fTrackParamAtCluster->First();
196 while (trackParamAtCluster) {
197 new ((*fTrackParamAtCluster)[GetNClusters()]) AliMUONTrackParam(*trackParamAtCluster);
198 trackParamAtCluster = (AliMUONTrackParam*) track.fTrackParamAtCluster->After(trackParamAtCluster);
199 }
208f139e 200 }
201
96ebe67e 202 // copy vertex resolution square used during the tracking procedure
203 fVertexErrXY2[0] = track.fVertexErrXY2[0];
204 fVertexErrXY2[1] = track.fVertexErrXY2[1];
208f139e 205
96ebe67e 206 // copy cluster weights matrices if any
207 if (track.fClusterWeightsNonBending) fClusterWeightsNonBending = new TMatrixD(*(track.fClusterWeightsNonBending));
208 if (track.fClusterWeightsBending) fClusterWeightsBending = new TMatrixD(*(track.fClusterWeightsBending));
ea94c18b 209
96ebe67e 210 // copy track parameters at vertex if any
211 if (track.fTrackParamAtVertex) fTrackParamAtVertex = new AliMUONTrackParam(*(track.fTrackParamAtVertex));
208f139e 212
a9e2aefa 213}
214
956019b6 215 //__________________________________________________________________________
ea94c18b 216AliMUONTrack & AliMUONTrack::operator=(const AliMUONTrack& track)
a9e2aefa 217{
2457f726 218 /// Asignment operator
30178c30 219 // check assignement to self
ea94c18b 220 if (this == &track)
a9e2aefa 221 return *this;
61adb9bd 222
30178c30 223 // base class assignement
ea94c18b 224 TObject::operator=(track);
7332f213 225
226 // clear memory
227 Clear();
228
229 // necessary to make a copy of the objects and not only the pointers in TClonesArray
230 if (track.fTrackParamAtCluster) {
231 fTrackParamAtCluster = new TClonesArray("AliMUONTrackParam",10);
232 AliMUONTrackParam *trackParamAtCluster = (AliMUONTrackParam*) track.fTrackParamAtCluster->First();
233 while (trackParamAtCluster) {
234 new ((*fTrackParamAtCluster)[GetNClusters()]) AliMUONTrackParam(*trackParamAtCluster);
235 trackParamAtCluster = (AliMUONTrackParam*) track.fTrackParamAtCluster->After(trackParamAtCluster);
236 }
208f139e 237 }
238
96ebe67e 239 // copy cluster weights matrix if any
240 if (track.fClusterWeightsNonBending) {
241 if (fClusterWeightsNonBending) {
242 fClusterWeightsNonBending->ResizeTo(*(track.fClusterWeightsNonBending));
243 *fClusterWeightsNonBending = *(track.fClusterWeightsNonBending);
244 } else fClusterWeightsNonBending = new TMatrixD(*(track.fClusterWeightsNonBending));
208f139e 245 }
246
96ebe67e 247 // copy cluster weights matrix if any
248 if (track.fClusterWeightsBending) {
249 if (fClusterWeightsBending) {
250 fClusterWeightsBending->ResizeTo(*(track.fClusterWeightsBending));
251 *fClusterWeightsBending = *(track.fClusterWeightsBending);
252 } else fClusterWeightsBending = new TMatrixD(*(track.fClusterWeightsBending));
ea94c18b 253 }
254
96ebe67e 255 // copy track parameters at vertex if any
256 if (track.fTrackParamAtVertex) {
257 if (fTrackParamAtVertex) *fTrackParamAtVertex = *(track.fTrackParamAtVertex);
258 else fTrackParamAtVertex = new AliMUONTrackParam(*(track.fTrackParamAtVertex));
ea94c18b 259 }
de2cd600 260
ea94c18b 261 fFitWithVertex = track.fFitWithVertex;
96ebe67e 262 fVertexErrXY2[0] = track.fVertexErrXY2[0];
263 fVertexErrXY2[1] = track.fVertexErrXY2[1];
ea94c18b 264 fFitWithMCS = track.fFitWithMCS;
265 fGlobalChi2 = track.fGlobalChi2;
266 fImproved = track.fImproved;
267 fMatchTrigger = track.fMatchTrigger;
268 floTrgNum = track.floTrgNum;
269 fChi2MatchTrigger = track.fChi2MatchTrigger;
270 fTrackID = track.fTrackID;
271 fHitsPatternInTrigCh = track.fHitsPatternInTrigCh;
272 fLocalTrigger = track.fLocalTrigger;
30178c30 273
61adb9bd 274 return *this;
a9e2aefa 275}
276
8429a5e4 277 //__________________________________________________________________________
ea94c18b 278AliMUONTrack::~AliMUONTrack()
279{
280 /// Destructor
96ebe67e 281 delete fTrackParamAtCluster;
282 delete fClusterWeightsNonBending;
283 delete fClusterWeightsBending;
284 delete fTrackParamAtVertex;
ea94c18b 285}
286
287 //__________________________________________________________________________
288void AliMUONTrack::Clear(Option_t* opt)
289{
290 /// Clear arrays
7332f213 291 if (opt && opt[0] == 'C' && fTrackParamAtCluster) fTrackParamAtCluster->Clear("C");
292 else {
293 delete fTrackParamAtCluster;
294 fTrackParamAtCluster = 0x0;
295 }
96ebe67e 296 delete fClusterWeightsNonBending; fClusterWeightsNonBending = 0x0;
297 delete fClusterWeightsBending; fClusterWeightsBending = 0x0;
298 delete fTrackParamAtVertex; fTrackParamAtVertex = 0x0;
ea94c18b 299}
300
b1fea02e 301 //__________________________________________________________________________
302void AliMUONTrack::Reset()
303{
304 /// Reset to default values
305 SetUniqueID(0);
306 fFitWithVertex = kFALSE;
307 fVertexErrXY2[0] = 0.;
308 fVertexErrXY2[1] = 0.;
309 fFitWithMCS = kFALSE;
310 fGlobalChi2 = -1.;
311 fImproved = kFALSE;
312 fMatchTrigger = -1;
313 floTrgNum = -1;
314 fChi2MatchTrigger = 0.;
315 fTrackID = 0;
316 fHitsPatternInTrigCh = 0;
317 fLocalTrigger = 0;
318 delete fTrackParamAtCluster; fTrackParamAtCluster = 0x0;
319 delete fClusterWeightsNonBending; fClusterWeightsNonBending = 0x0;
320 delete fClusterWeightsBending; fClusterWeightsBending = 0x0;
321 delete fTrackParamAtVertex; fTrackParamAtVertex = 0x0;
322}
323
7332f213 324 //__________________________________________________________________________
325TClonesArray* AliMUONTrack::GetTrackParamAtCluster() const
326{
327 /// return array of track parameters at cluster (create it if needed)
328 if (!fTrackParamAtCluster) fTrackParamAtCluster = new TClonesArray("AliMUONTrackParam",10);
329 return fTrackParamAtCluster;
330}
331
ea94c18b 332 //__________________________________________________________________________
96ebe67e 333void AliMUONTrack::AddTrackParamAtCluster(const AliMUONTrackParam &trackParam, AliMUONVCluster &cluster, Bool_t copy)
8429a5e4 334{
96ebe67e 335 /// Copy given track parameters into a new TrackParamAtCluster
336 /// Link parameters with the associated cluster
337 /// If copy=kTRUE: the cluster is copied then passed the trackParam which become its owner
338 /// otherwise: make sure to do not delete the cluster until it is used by the track
339
340 // check chamber ID of the associated cluster
341 if (cluster.GetChamberId() < 0 || cluster.GetChamberId() > AliMUONConstants::NTrackingCh()) {
342 AliError(Form("Chamber ID of the associated cluster is not valid (ChamberId=%d)",cluster.GetChamberId()));
ea94c18b 343 return;
344 }
345
96ebe67e 346 // check whether track parameters are given at the correct cluster z position
347 if (cluster.GetZ() != trackParam.GetZ()) {
348 AliError("track parameters are given at a different z position than the one of the associated cluster");
ea94c18b 349 return;
350 }
351
96ebe67e 352 // add parameters to the array of track parameters
7332f213 353 if (!fTrackParamAtCluster) fTrackParamAtCluster = new TClonesArray("AliMUONTrackParam",10);
96ebe67e 354 AliMUONTrackParam* trackParamAtCluster = new ((*fTrackParamAtCluster)[GetNClusters()]) AliMUONTrackParam(trackParam);
355
356 // link parameters with the associated cluster or its copy
357 if (copy) {
1467f4ba 358 AliMUONVCluster *clusterCopy = static_cast<AliMUONVCluster*>(cluster.Clone());
96ebe67e 359 trackParamAtCluster->SetClusterPtr(clusterCopy, kTRUE);
360 } else trackParamAtCluster->SetClusterPtr(&cluster);
7332f213 361
362 // sort the array of track parameters
363 fTrackParamAtCluster->Sort();
ea94c18b 364}
365
956019b6 366 //__________________________________________________________________________
96ebe67e 367void AliMUONTrack::RemoveTrackParamAtCluster(AliMUONTrackParam *trackParam)
956019b6 368{
96ebe67e 369 /// Remove trackParam from the array of TrackParamAtCluster
7332f213 370 if (!fTrackParamAtCluster || !fTrackParamAtCluster->Remove(trackParam)) {
96ebe67e 371 AliWarning("object to remove does not exist in array fTrackParamAtCluster");
372 return;
373 }
de2cd600 374
96ebe67e 375 fTrackParamAtCluster->Compress();
04b5ea16 376}
377
ea94c18b 378 //__________________________________________________________________________
96ebe67e 379void AliMUONTrack::UpdateTrackParamAtCluster()
d2b1e7bb 380{
96ebe67e 381 /// Update track parameters at each attached cluster
ea94c18b 382
96ebe67e 383 if (GetNClusters() == 0) {
384 AliWarning("no cluster attached to the track");
ea94c18b 385 return;
386 }
387
96ebe67e 388 AliMUONTrackParam* startingTrackParam = (AliMUONTrackParam*) fTrackParamAtCluster->First();
389 AliMUONTrackParam* trackParamAtCluster = (AliMUONTrackParam*) fTrackParamAtCluster->After(startingTrackParam);
390 while (trackParamAtCluster) {
ea94c18b 391
392 // reset track parameters and their covariances
96ebe67e 393 trackParamAtCluster->SetParameters(startingTrackParam->GetParameters());
394 trackParamAtCluster->SetZ(startingTrackParam->GetZ());
ea94c18b 395
396 // extrapolation to the given z
96ebe67e 397 AliMUONTrackExtrap::ExtrapToZ(trackParamAtCluster, trackParamAtCluster->GetClusterPtr()->GetZ());
ea94c18b 398
399 // prepare next step
96ebe67e 400 startingTrackParam = trackParamAtCluster;
401 trackParamAtCluster = (AliMUONTrackParam*) (fTrackParamAtCluster->After(trackParamAtCluster));
ea94c18b 402 }
403
d2b1e7bb 404}
405
b8dc484b 406 //__________________________________________________________________________
96ebe67e 407void AliMUONTrack::UpdateCovTrackParamAtCluster()
ea94c18b 408{
96ebe67e 409 /// Update track parameters and their covariances at each attached cluster
410 /// Include effects of multiple scattering in chambers
ea94c18b 411
96ebe67e 412 if (GetNClusters() == 0) {
413 AliWarning("no cluster attached to the track");
ea94c18b 414 return;
415 }
416
96ebe67e 417 AliMUONTrackParam* startingTrackParam = (AliMUONTrackParam*) fTrackParamAtCluster->First();
418 AliMUONTrackParam* trackParamAtCluster = (AliMUONTrackParam*) fTrackParamAtCluster->After(startingTrackParam);
419 Int_t expectedChamber = startingTrackParam->GetClusterPtr()->GetChamberId() + 1;
420 Int_t currentChamber;
421 while (trackParamAtCluster) {
ea94c18b 422
423 // reset track parameters and their covariances
96ebe67e 424 trackParamAtCluster->SetParameters(startingTrackParam->GetParameters());
425 trackParamAtCluster->SetZ(startingTrackParam->GetZ());
426 trackParamAtCluster->SetCovariances(startingTrackParam->GetCovariances());
ea94c18b 427
96ebe67e 428 // add MCS effect
429 AliMUONTrackExtrap::AddMCSEffect(trackParamAtCluster,AliMUONConstants::ChamberThicknessInX0(),1.);
430
431 // add MCS in missing chambers if any
432 currentChamber = trackParamAtCluster->GetClusterPtr()->GetChamberId();
433 while (currentChamber > expectedChamber) {
434 // extrapolation to the missing chamber
435 AliMUONTrackExtrap::ExtrapToZCov(trackParamAtCluster, AliMUONConstants::DefaultChamberZ(expectedChamber));
436 // add MCS effect
437 AliMUONTrackExtrap::AddMCSEffect(trackParamAtCluster,AliMUONConstants::ChamberThicknessInX0(),1.);
438 expectedChamber++;
439 }
440
441 // extrapolation to the z of the current cluster
442 AliMUONTrackExtrap::ExtrapToZCov(trackParamAtCluster, trackParamAtCluster->GetClusterPtr()->GetZ());
ea94c18b 443
444 // prepare next step
96ebe67e 445 expectedChamber = currentChamber + 1;
446 startingTrackParam = trackParamAtCluster;
447 trackParamAtCluster = (AliMUONTrackParam*) (fTrackParamAtCluster->After(trackParamAtCluster));
ea94c18b 448 }
96ebe67e 449
7332f213 450}
451
452 //__________________________________________________________________________
a0dc65b4 453Bool_t AliMUONTrack::IsValid(UInt_t requestedStationMask)
7332f213 454{
9bf6860b 455 /// check the validity of the current track (at least one cluster per requested station)
7332f213 456
457 Int_t nClusters = GetNClusters();
458 AliMUONTrackParam *trackParam;
a0dc65b4 459 Int_t currentStation(0);
7332f213 460
a0dc65b4 461 UInt_t m(0);
462
463 for (Int_t i = 0; i < nClusters; i++)
464 {
7332f213 465 trackParam = (AliMUONTrackParam*) fTrackParamAtCluster->UncheckedAt(i);
466
9bf6860b 467 // skip unrequested stations
a0dc65b4 468// while (expectedStation < AliMUONConstants::NTrackingSt() &&
469// !AliMUONReconstructor::GetRecoParam()->RequestStation(expectedStation)) expectedStation++;
470//
471
7332f213 472 currentStation = trackParam->GetClusterPtr()->GetChamberId()/2;
473
a0dc65b4 474 m |= ( 1 << currentStation );
7332f213 475
476 }
477
a0dc65b4 478 return ( (requestedStationMask & m) == requestedStationMask ) ;
7332f213 479}
480
481 //__________________________________________________________________________
a0dc65b4 482void AliMUONTrack::TagRemovableClusters(UInt_t requestedStationMask) {
7332f213 483 /// Identify clusters that can be removed from the track,
9bf6860b 484 /// with the only requirement to have at least 1 cluster per requested station
7332f213 485
486 Int_t nClusters = GetNClusters();
487 AliMUONTrackParam *trackParam, *nextTrackParam;
488 Int_t currentCh, nextCh;
489
9bf6860b 490 // reset flags to kFALSE for all clusters in required station
7332f213 491 for (Int_t i = 0; i < nClusters; i++) {
492 trackParam = (AliMUONTrackParam*) fTrackParamAtCluster->UncheckedAt(i);
a0dc65b4 493 Int_t stationId = ( 1 << (trackParam->GetClusterPtr()->GetChamberId()/2) );
494 UInt_t m = ( 1 << stationId );
495 if ( m & requestedStationMask )
9bf6860b 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