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