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