]> git.uio.no Git - u/mrichter/AliRoot.git/blame - MUON/AliMUONTrack.cxx
New class for AOD<->MC association
[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
a9e2aefa 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
8429a5e4 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
b1fea02e 300 //__________________________________________________________________________
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
7332f213 323 //__________________________________________________________________________
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
ea94c18b 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
956019b6 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
b8dc484b 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
7332f213 449}
450
451 //__________________________________________________________________________
a0dc65b4 452Bool_t AliMUONTrack::IsValid(UInt_t requestedStationMask)
7332f213 453{
3d7acbb7 454 /// check the validity of the current track:
455 /// at least one cluster per requested station
456 /// and at least 2 chambers in stations 4 & 5 that contain cluster(s)
7332f213 457
458 Int_t nClusters = GetNClusters();
459 AliMUONTrackParam *trackParam;
3d7acbb7 460 Int_t currentCh, currentSt, previousCh = -1, nChHitInSt45 = 0;
ad3c6eda 461 UInt_t presentStationMask(0);
7332f213 462
3d7acbb7 463 // first loop over clusters
ad3c6eda 464 for (Int_t i = 0; i < nClusters; i++) {
7332f213 465 trackParam = (AliMUONTrackParam*) fTrackParamAtCluster->UncheckedAt(i);
3d7acbb7 466
467 currentCh = trackParam->GetClusterPtr()->GetChamberId();
468 currentSt = currentCh/2;
469
470 // build present station mask
471 presentStationMask |= ( 1 << currentSt );
472
473 // count the number of chambers in station 4 & 5 that contain cluster(s)
474 if (currentCh > 5 && currentCh != previousCh) {
475 nChHitInSt45++;
476 previousCh = currentCh;
477 }
478
7332f213 479 }
480
3d7acbb7 481 return (((requestedStationMask & presentStationMask) == requestedStationMask) && (nChHitInSt45 >= 2));
7332f213 482}
483
484 //__________________________________________________________________________
a0dc65b4 485void AliMUONTrack::TagRemovableClusters(UInt_t requestedStationMask) {
7332f213 486 /// Identify clusters that can be removed from the track,
3d7acbb7 487 /// with the only requirements to have at least 1 cluster per requested station
488 /// and at least 2 chambers over 4 in stations 4 & 5 that contain cluster(s)
7332f213 489
490 Int_t nClusters = GetNClusters();
491 AliMUONTrackParam *trackParam, *nextTrackParam;
3d7acbb7 492 Int_t currentCh, nextCh, currentSt, nextSt, previousCh = -1, nChHitInSt45 = 0;
7332f213 493
3d7acbb7 494 // first loop over clusters
7332f213 495 for (Int_t i = 0; i < nClusters; i++) {
496 trackParam = (AliMUONTrackParam*) fTrackParamAtCluster->UncheckedAt(i);
3d7acbb7 497
498 currentCh = trackParam->GetClusterPtr()->GetChamberId();
499 currentSt = currentCh/2;
500
501 // reset flags to kFALSE for all clusters in required station
502 if ((1 << currentSt) & requestedStationMask) trackParam->SetRemovable(kFALSE);
9bf6860b 503 else trackParam->SetRemovable(kTRUE);
3d7acbb7 504
505 // count the number of chambers in station 4 & 5 that contain cluster(s)
506 if (currentCh > 5 && currentCh != previousCh) {
507 nChHitInSt45++;
508 previousCh = currentCh;
509 }
510
7332f213 511 }
512
3d7acbb7 513 // second loop over clusters
7332f213 514 for (Int_t i = 0; i < nClusters; i++) {
515 trackParam = (AliMUONTrackParam*) fTrackParamAtCluster->UncheckedAt(i);
516
517 currentCh = trackParam->GetClusterPtr()->GetChamberId();
3d7acbb7 518 currentSt = currentCh/2;
7332f213 519
3d7acbb7 520 // make sure they are more than 2 clusters in 2 different chambers of stations 4 & 5
521 // but 2 clusters in he same chamber will still be flagged as removable
522 if (nChHitInSt45 < 3 && currentSt > 2) {
7332f213 523
3d7acbb7 524 if (i == nClusters-1) {
525
526 trackParam->SetRemovable(kFALSE);
7332f213 527
3d7acbb7 528 } else {
529
530 nextTrackParam = (AliMUONTrackParam*) fTrackParamAtCluster->UncheckedAt(i+1);
531 nextCh = nextTrackParam->GetClusterPtr()->GetChamberId();
532
533 // set clusters in the same chamber as being removable
534 if (nextCh == currentCh) {
535 trackParam->SetRemovable(kTRUE);
536 nextTrackParam->SetRemovable(kTRUE);
537 i++; // skip cluster already checked
538 } else {
539 trackParam->SetRemovable(kFALSE);
540 }
541
542 }
7332f213 543
3d7acbb7 544 } else {
545
546 // skip clusters already flag as removable
547 if (trackParam->IsRemovable()) continue;
548
549 // loop over next track parameters
550 for (Int_t j = i+1; j < nClusters; j++) {
551 nextTrackParam = (AliMUONTrackParam*) fTrackParamAtCluster->UncheckedAt(j);
552
553 nextCh = nextTrackParam->GetClusterPtr()->GetChamberId();
554 nextSt = nextCh/2;
555
556 // set clusters in the same station as being removable
557 if (nextSt == currentSt) {
558 trackParam->SetRemovable(kTRUE);
559 nextTrackParam->SetRemovable(kTRUE);
560 i++; // skip cluster already checked
561 }
562
563 }
7332f213 564
565 }
3d7acbb7 566
7332f213 567 }
568
208f139e 569}
570
ea94c18b 571 //__________________________________________________________________________
572Bool_t AliMUONTrack::ComputeLocalChi2(Bool_t accountForMCS)
573{
96ebe67e 574 /// Compute each cluster contribution to the chi2 of the track
ea94c18b 575 /// accounting for multiple scattering or not according to the flag
96ebe67e 576 /// - Also recompute the weight matrices of the attached clusters if accountForMCS=kTRUE
577 /// - Assume that track parameters at each cluster are corrects
ea94c18b 578 /// - Return kFALSE if computation failed
7332f213 579 AliDebug(1,"Enter ComputeLocalChi2");
580
581 if (!fTrackParamAtCluster) {
582 AliWarning("no cluster attached to this track");
583 return kFALSE;
584 }
ea94c18b 585
ea94c18b 586 if (accountForMCS) { // Compute local chi2 taking into account multiple scattering effects
587
588 // Compute MCS covariance matrix only once
96ebe67e 589 Int_t nClusters = GetNClusters();
590 TMatrixD mcsCovariances(nClusters,nClusters);
ea94c18b 591 ComputeMCSCovariances(mcsCovariances);
592
96ebe67e 593 // Make sure cluster weights are consistent with following calculations
594 if (!ComputeClusterWeights(&mcsCovariances)) {
ea94c18b 595 AliWarning("cannot take into account the multiple scattering effects");
596 return ComputeLocalChi2(kFALSE);
597 }
598
599 // Compute chi2 of the track
600 Double_t globalChi2 = ComputeGlobalChi2(kTRUE);
601 if (globalChi2 < 0.) return kFALSE;
602
96ebe67e 603 // Loop over removable clusters and compute their local chi2
604 AliMUONTrackParam* trackParamAtCluster1;
605 AliMUONVCluster *cluster, *discardedCluster;
606 Int_t iCluster1, iCluster2, iCurrentCluster1, iCurrentCluster2;
c812dd48 607 TMatrixD clusterWeightsNB(nClusters-1,nClusters-1);
608 TMatrixD clusterWeightsB(nClusters-1,nClusters-1);
96ebe67e 609 Double_t *dX = new Double_t[nClusters-1];
610 Double_t *dY = new Double_t[nClusters-1];
ea94c18b 611 Double_t globalChi2b;
96ebe67e 612 AliMUONTrackParam* trackParamAtCluster = (AliMUONTrackParam*) fTrackParamAtCluster->First();
613 while (trackParamAtCluster) {
ea94c18b 614
96ebe67e 615 discardedCluster = trackParamAtCluster->GetClusterPtr();
ea94c18b 616
96ebe67e 617 // Recompute cluster weights without the current cluster
c812dd48 618 if (!ComputeClusterWeights(clusterWeightsNB, clusterWeightsB, &mcsCovariances, discardedCluster)) {
ea94c18b 619 AliWarning("cannot take into account the multiple scattering effects");
96ebe67e 620 delete [] dX;
621 delete [] dY;
622 return ComputeLocalChi2(kFALSE);
ea94c18b 623 }
624
96ebe67e 625 // Compute track chi2 without the current cluster
ea94c18b 626 globalChi2b = 0.;
96ebe67e 627 iCurrentCluster1 = 0;
628 for (iCluster1 = 0; iCluster1 < nClusters ; iCluster1++) {
629 trackParamAtCluster1 = (AliMUONTrackParam*) fTrackParamAtCluster->UncheckedAt(iCluster1);
630 cluster = trackParamAtCluster1->GetClusterPtr();
ea94c18b 631
96ebe67e 632 if (cluster == discardedCluster) continue;
ea94c18b 633
634 // Compute and save residuals
96ebe67e 635 dX[iCurrentCluster1] = cluster->GetX() - trackParamAtCluster1->GetNonBendingCoor();
636 dY[iCurrentCluster1] = cluster->GetY() - trackParamAtCluster1->GetBendingCoor();
ea94c18b 637
96ebe67e 638 iCurrentCluster2 = 0;
639 for (iCluster2 = 0; iCluster2 < iCluster1; iCluster2++) {
640 cluster = ((AliMUONTrackParam*) fTrackParamAtCluster->UncheckedAt(iCluster2))->GetClusterPtr();
ea94c18b 641
96ebe67e 642 if (cluster == discardedCluster) continue;
ea94c18b 643
644 // Add contribution from covariances
c812dd48 645 globalChi2b += (clusterWeightsNB(iCurrentCluster1, iCurrentCluster2) +
646 clusterWeightsNB(iCurrentCluster2, iCurrentCluster1)) * dX[iCurrentCluster1] * dX[iCurrentCluster2] +
647 (clusterWeightsB(iCurrentCluster1, iCurrentCluster2) +
648 clusterWeightsB(iCurrentCluster2, iCurrentCluster1)) * dY[iCurrentCluster1] * dY[iCurrentCluster2];
ea94c18b 649
96ebe67e 650 iCurrentCluster2++;
ea94c18b 651 }
652
653 // Add contribution from variances
c812dd48 654 globalChi2b += clusterWeightsNB(iCurrentCluster1, iCurrentCluster1) * dX[iCurrentCluster1] * dX[iCurrentCluster1] +
655 clusterWeightsB(iCurrentCluster1, iCurrentCluster1) * dY[iCurrentCluster1] * dY[iCurrentCluster1];
ea94c18b 656
96ebe67e 657 iCurrentCluster1++;
ea94c18b 658 }
659
660 // Set local chi2
96ebe67e 661 trackParamAtCluster->SetLocalChi2(globalChi2 - globalChi2b);
ea94c18b 662
96ebe67e 663 trackParamAtCluster = (AliMUONTrackParam*) fTrackParamAtCluster->After(trackParamAtCluster);
ea94c18b 664 }
665
666 delete [] dX;
667 delete [] dY;
668
669 } else { // without multiple scattering effects
670
96ebe67e 671 AliMUONVCluster *discardedCluster;
ea94c18b 672 Double_t dX, dY;
96ebe67e 673 AliMUONTrackParam* trackParamAtCluster = (AliMUONTrackParam*) fTrackParamAtCluster->First();
674 while (trackParamAtCluster) {
ea94c18b 675
96ebe67e 676 discardedCluster = trackParamAtCluster->GetClusterPtr();
ea94c18b 677
678 // Compute residuals
96ebe67e 679 dX = discardedCluster->GetX() - trackParamAtCluster->GetNonBendingCoor();
680 dY = discardedCluster->GetY() - trackParamAtCluster->GetBendingCoor();
ea94c18b 681
682 // Set local chi2
96ebe67e 683 trackParamAtCluster->SetLocalChi2(dX * dX / discardedCluster->GetErrX2() + dY * dY / discardedCluster->GetErrY2());
ea94c18b 684
96ebe67e 685 trackParamAtCluster = (AliMUONTrackParam*) fTrackParamAtCluster->After(trackParamAtCluster);
ea94c18b 686 }
687
688 }
689
ea94c18b 690 return kTRUE;
691
692}
693
694 //__________________________________________________________________________
695Double_t AliMUONTrack::ComputeGlobalChi2(Bool_t accountForMCS)
696{
697 /// Compute the chi2 of the track accounting for multiple scattering or not according to the flag
96ebe67e 698 /// - Assume that track parameters at each cluster are corrects
699 /// - Assume the cluster weights matrices are corrects
ea94c18b 700 /// - Return negative value if chi2 computation failed
7332f213 701 AliDebug(1,"Enter ComputeGlobalChi2");
702
703 if (!fTrackParamAtCluster) {
704 AliWarning("no cluster attached to this track");
705 return 1.e10;
706 }
ea94c18b 707
ea94c18b 708 Double_t chi2 = 0.;
709
710 if (accountForMCS) {
711
b709ac13 712 // Check the weight matrices. If weight matrices are not available compute chi2 without MCS
96ebe67e 713 if (!fClusterWeightsNonBending || !fClusterWeightsBending) {
714 AliWarning("cluster weights including multiple scattering effects are not available\n\t\t --> compute chi2 WITHOUT multiple scattering");
b709ac13 715 return ComputeGlobalChi2(kFALSE);
716 }
96ebe67e 717 Int_t nClusters = GetNClusters();
718 if (fClusterWeightsNonBending->GetNrows() != nClusters || fClusterWeightsBending->GetNcols() != nClusters) {
719 AliWarning("cluster weights including multiple scattering effects are not available\n\t\t --> compute chi2 WITHOUT multiple scattering");
ea94c18b 720 return ComputeGlobalChi2(kFALSE);
721 }
722
723 // Compute chi2
96ebe67e 724 AliMUONVCluster *cluster;
725 Double_t *dX = new Double_t[nClusters];
726 Double_t *dY = new Double_t[nClusters];
727 AliMUONTrackParam* trackParamAtCluster;
728 for (Int_t iCluster1 = 0; iCluster1 < nClusters; iCluster1++) {
729 trackParamAtCluster = (AliMUONTrackParam*) fTrackParamAtCluster->UncheckedAt(iCluster1);
730 cluster = trackParamAtCluster->GetClusterPtr();
731 dX[iCluster1] = cluster->GetX() - trackParamAtCluster->GetNonBendingCoor();
732 dY[iCluster1] = cluster->GetY() - trackParamAtCluster->GetBendingCoor();
733 for (Int_t iCluster2 = 0; iCluster2 < iCluster1; iCluster2++) {
734 chi2 += ((*fClusterWeightsNonBending)(iCluster1, iCluster2) + (*fClusterWeightsNonBending)(iCluster2, iCluster1)) * dX[iCluster1] * dX[iCluster2] +
735 ((*fClusterWeightsBending)(iCluster1, iCluster2) + (*fClusterWeightsBending)(iCluster2, iCluster1)) * dY[iCluster1] * dY[iCluster2];
ea94c18b 736 }
96ebe67e 737 chi2 += ((*fClusterWeightsNonBending)(iCluster1, iCluster1) * dX[iCluster1] * dX[iCluster1]) +
738 ((*fClusterWeightsBending)(iCluster1, iCluster1) * dY[iCluster1] * dY[iCluster1]);
ea94c18b 739 }
740 delete [] dX;
741 delete [] dY;
742
743 } else {
744
96ebe67e 745 AliMUONVCluster *cluster;
ea94c18b 746 Double_t dX, dY;
96ebe67e 747 AliMUONTrackParam* trackParamAtCluster;
748 Int_t nClusters = GetNClusters();
749 for (Int_t iCluster = 0; iCluster < nClusters ; iCluster++) {
750 trackParamAtCluster = (AliMUONTrackParam*) fTrackParamAtCluster->UncheckedAt(iCluster);
751 cluster = trackParamAtCluster->GetClusterPtr();
752 dX = cluster->GetX() - trackParamAtCluster->GetNonBendingCoor();
753 dY = cluster->GetY() - trackParamAtCluster->GetBendingCoor();
754 chi2 += dX * dX / cluster->GetErrX2() + dY * dY / cluster->GetErrY2();
ea94c18b 755 }
756
757 }
758
759 return chi2;
760
761}
762
763 //__________________________________________________________________________
96ebe67e 764Bool_t AliMUONTrack::ComputeClusterWeights(TMatrixD* mcsCovariances)
ea94c18b 765{
96ebe67e 766 /// Compute the weight matrices of the attached clusters, in non bending and bending direction,
767 /// accounting for multiple scattering correlations and cluster resolution
ea94c18b 768 /// - Use the provided MCS covariance matrix if any (otherwise build it temporarily)
96ebe67e 769 /// - Assume that track parameters at each cluster are corrects
ea94c18b 770 /// - Return kFALSE if computation failed
7332f213 771 AliDebug(1,"Enter ComputeClusterWeights1");
772
773 if (!fTrackParamAtCluster) {
774 AliWarning("no cluster attached to this track");
775 return kFALSE;
776 }
ea94c18b 777
778 // Alocate memory
96ebe67e 779 Int_t nClusters = GetNClusters();
780 if (!fClusterWeightsNonBending) fClusterWeightsNonBending = new TMatrixD(nClusters,nClusters);
781 if (!fClusterWeightsBending) fClusterWeightsBending = new TMatrixD(nClusters,nClusters);
ea94c18b 782
783 // Compute weights matrices
96ebe67e 784 if (!ComputeClusterWeights(*fClusterWeightsNonBending, *fClusterWeightsBending, mcsCovariances)) return kFALSE;
ea94c18b 785
786 return kTRUE;
787
788}
789
790 //__________________________________________________________________________
c812dd48 791Bool_t AliMUONTrack::ComputeClusterWeights(TMatrixD& clusterWeightsNB, TMatrixD& clusterWeightsB,
96ebe67e 792 TMatrixD* mcsCovariances, AliMUONVCluster* discardedCluster) const
ea94c18b 793{
794 /// Compute the weight matrices, in non bending and bending direction,
96ebe67e 795 /// of the other attached clusters assuming the discarded one does not exist
796 /// accounting for multiple scattering correlations and cluster resolution
ea94c18b 797 /// - Use the provided MCS covariance matrix if any (otherwise build it temporarily)
798 /// - Return kFALSE if computation failed
7332f213 799 AliDebug(1,"Enter ComputeClusterWeights2");
ea94c18b 800
801 // Check MCS covariance matrix and recompute it if need
96ebe67e 802 Int_t nClusters = GetNClusters();
ea94c18b 803 Bool_t deleteMCSCov = kFALSE;
804 if (!mcsCovariances) {
96ebe67e 805 mcsCovariances = new TMatrixD(nClusters,nClusters);
ea94c18b 806 deleteMCSCov = kTRUE;
807 ComputeMCSCovariances(*mcsCovariances);
ea94c18b 808 }
809
810 // Resize the weights matrices; alocate memory
96ebe67e 811 if (discardedCluster) {
c812dd48 812 clusterWeightsNB.ResizeTo(nClusters-1,nClusters-1);
813 clusterWeightsB.ResizeTo(nClusters-1,nClusters-1);
ea94c18b 814 } else {
c812dd48 815 clusterWeightsNB.ResizeTo(nClusters,nClusters);
816 clusterWeightsB.ResizeTo(nClusters,nClusters);
ea94c18b 817 }
818
819 // Define variables
96ebe67e 820 AliMUONVCluster *cluster1, *cluster2;
821 Int_t iCurrentCluster1, iCurrentCluster2;
ea94c18b 822
823 // Compute the covariance matrices
96ebe67e 824 iCurrentCluster1 = 0;
825 for (Int_t iCluster1 = 0; iCluster1 < nClusters; iCluster1++) {
826 cluster1 = ((AliMUONTrackParam*) fTrackParamAtCluster->UncheckedAt(iCluster1))->GetClusterPtr();
ea94c18b 827
96ebe67e 828 if (cluster1 == discardedCluster) continue;
ea94c18b 829
96ebe67e 830 // Loop over next clusters
831 iCurrentCluster2 = iCurrentCluster1;
832 for (Int_t iCluster2 = iCluster1; iCluster2 < nClusters; iCluster2++) {
833 cluster2 = ((AliMUONTrackParam*) fTrackParamAtCluster->UncheckedAt(iCluster2))->GetClusterPtr();
ea94c18b 834
96ebe67e 835 if (cluster2 == discardedCluster) continue;
ea94c18b 836
ea94c18b 837 // Fill with MCS covariances
c812dd48 838 clusterWeightsNB(iCurrentCluster1, iCurrentCluster2) = (*mcsCovariances)(iCluster1,iCluster2);
ea94c18b 839
840 // Equal contribution from multiple scattering in non bending and bending directions
c812dd48 841 clusterWeightsB(iCurrentCluster1, iCurrentCluster2) = clusterWeightsNB(iCurrentCluster1, iCurrentCluster2);
ea94c18b 842
96ebe67e 843 // Add contribution from cluster resolution to diagonal element and symmetrize the matrix
844 if (iCurrentCluster1 == iCurrentCluster2) {
ea94c18b 845
846 // In non bending plane
c812dd48 847 clusterWeightsNB(iCurrentCluster1, iCurrentCluster1) += cluster1->GetErrX2();
ea94c18b 848 // In bending plane
c812dd48 849 clusterWeightsB(iCurrentCluster1, iCurrentCluster1) += cluster1->GetErrY2();
ea94c18b 850
851 } else {
852
853 // In non bending plane
c812dd48 854 clusterWeightsNB(iCurrentCluster2, iCurrentCluster1) = clusterWeightsNB(iCurrentCluster1, iCurrentCluster2);
ea94c18b 855 // In bending plane
c812dd48 856 clusterWeightsB(iCurrentCluster2, iCurrentCluster1) = clusterWeightsB(iCurrentCluster1, iCurrentCluster2);
ea94c18b 857
858 }
859
96ebe67e 860 iCurrentCluster2++;
ea94c18b 861 }
862
96ebe67e 863 iCurrentCluster1++;
ea94c18b 864 }
865
866 // Inversion of covariance matrices to get the weights
c812dd48 867 if (clusterWeightsNB.Determinant() != 0 && clusterWeightsB.Determinant() != 0) {
868 clusterWeightsNB.Invert();
869 clusterWeightsB.Invert();
ea94c18b 870 } else {
871 AliWarning(" Determinant = 0");
c812dd48 872 clusterWeightsNB.ResizeTo(0,0);
873 clusterWeightsB.ResizeTo(0,0);
ea94c18b 874 if(deleteMCSCov) delete mcsCovariances;
875 return kFALSE;
876 }
877
878 if(deleteMCSCov) delete mcsCovariances;
879
880 return kTRUE;
881
882}
883
884 //__________________________________________________________________________
885void AliMUONTrack::ComputeMCSCovariances(TMatrixD& mcsCovariances) const
886{
887 /// Compute the multiple scattering covariance matrix
96ebe67e 888 /// (assume that track parameters at each cluster are corrects)
7332f213 889 AliDebug(1,"Enter ComputeMCSCovariances");
ea94c18b 890
b709ac13 891 // Reset the size of the covariance matrix if needed
96ebe67e 892 Int_t nClusters = GetNClusters();
893 if (mcsCovariances.GetNrows() != nClusters) mcsCovariances.ResizeTo(nClusters,nClusters);
ea94c18b 894
895 // Define variables
b709ac13 896 Int_t nChambers = AliMUONConstants::NTrackingCh();
96ebe67e 897 AliMUONTrackParam* trackParamAtCluster;
ea94c18b 898 AliMUONTrackParam extrapTrackParam;
b709ac13 899 Int_t currentChamber = 0, expectedChamber = 0, size = 0;
900 Double_t *mcsAngle2 = new Double_t[2*nChambers];
901 Double_t *zMCS = new Double_t[2*nChambers];
96ebe67e 902 Int_t *indices = new Int_t[2*nClusters];
ea94c18b 903
904 // Compute multiple scattering dispersion angle at each chamber
905 // and save the z position where it is calculated
96ebe67e 906 for (Int_t iCluster = 0; iCluster < nClusters; iCluster++) {
907 trackParamAtCluster = (AliMUONTrackParam*) fTrackParamAtCluster->UncheckedAt(iCluster);
ea94c18b 908
909 // look for missing chambers if any
96ebe67e 910 currentChamber = trackParamAtCluster->GetClusterPtr()->GetChamberId();
ea94c18b 911 while (currentChamber > expectedChamber) {
912
913 // Save the z position where MCS dispersion is calculated
b709ac13 914 zMCS[size] = AliMUONConstants::DefaultChamberZ(expectedChamber);
ea94c18b 915
96ebe67e 916 // Do not take into account MCS in chambers prior the first cluster
917 if (iCluster > 0) {
ea94c18b 918
919 // Get track parameters at missing chamber z
96ebe67e 920 extrapTrackParam = *trackParamAtCluster;
921 AliMUONTrackExtrap::ExtrapToZ(&extrapTrackParam, zMCS[size]);
ea94c18b 922
923 // Save multiple scattering dispersion angle in missing chamber
b709ac13 924 mcsAngle2[size] = AliMUONTrackExtrap::GetMCSAngle2(extrapTrackParam,AliMUONConstants::ChamberThicknessInX0(),1.);
ea94c18b 925
b709ac13 926 } else mcsAngle2[size] = 0.;
ea94c18b 927
928 expectedChamber++;
b709ac13 929 size++;
ea94c18b 930 }
931
932 // Save z position where MCS dispersion is calculated
96ebe67e 933 zMCS[size] = trackParamAtCluster->GetZ();
ea94c18b 934
935 // Save multiple scattering dispersion angle in current chamber
96ebe67e 936 mcsAngle2[size] = AliMUONTrackExtrap::GetMCSAngle2(*trackParamAtCluster,AliMUONConstants::ChamberThicknessInX0(),1.);
b709ac13 937
938 // Save indice in zMCS array corresponding to the current cluster
96ebe67e 939 indices[iCluster] = size;
ea94c18b 940
b709ac13 941 expectedChamber = currentChamber + 1;
942 size++;
ea94c18b 943 }
944
96ebe67e 945 // complete array of z if last cluster is on the last but one chamber
b709ac13 946 if (currentChamber != nChambers-1) zMCS[size++] = AliMUONConstants::DefaultChamberZ(nChambers-1);
ea94c18b 947
948 // Compute the covariance matrix
96ebe67e 949 for (Int_t iCluster1 = 0; iCluster1 < nClusters; iCluster1++) {
ea94c18b 950
96ebe67e 951 for (Int_t iCluster2 = iCluster1; iCluster2 < nClusters; iCluster2++) {
ea94c18b 952
953 // Initialization to 0 (diagonal plus upper triangular part)
96ebe67e 954 mcsCovariances(iCluster1,iCluster2) = 0.;
ea94c18b 955
956 // Compute contribution from multiple scattering in upstream chambers
96ebe67e 957 for (Int_t k = 0; k < indices[iCluster1]; k++) {
958 mcsCovariances(iCluster1,iCluster2) += (zMCS[indices[iCluster1]] - zMCS[k]) * (zMCS[indices[iCluster2]] - zMCS[k]) * mcsAngle2[k];
ea94c18b 959 }
960
961 // Symetrize the matrix
96ebe67e 962 mcsCovariances(iCluster2,iCluster1) = mcsCovariances(iCluster1,iCluster2);
ea94c18b 963 }
964
965 }
966
967 delete [] mcsAngle2;
968 delete [] zMCS;
b709ac13 969 delete [] indices;
ea94c18b 970
971}
972
208f139e 973 //__________________________________________________________________________
96ebe67e 974Int_t AliMUONTrack::ClustersInCommon(AliMUONTrack* track) const
208f139e 975{
96ebe67e 976 /// Returns the number of clusters in common between the current track ("this")
208f139e 977 /// and the track pointed to by "track".
7332f213 978 if (!fTrackParamAtCluster || !this->fTrackParamAtCluster) return 0;
96ebe67e 979 Int_t clustersInCommon = 0;
980 AliMUONTrackParam *trackParamAtCluster1, *trackParamAtCluster2;
981 // Loop over clusters of first track
982 trackParamAtCluster1 = (AliMUONTrackParam*) this->fTrackParamAtCluster->First();
983 while (trackParamAtCluster1) {
984 // Loop over clusters of second track
985 trackParamAtCluster2 = (AliMUONTrackParam*) track->fTrackParamAtCluster->First();
986 while (trackParamAtCluster2) {
987 // Increment "clustersInCommon" if both trackParamAtCluster1 & 2 point to the same cluster
988 if ((trackParamAtCluster1->GetClusterPtr()) == (trackParamAtCluster2->GetClusterPtr())) {
989 clustersInCommon++;
208f139e 990 break;
991 }
96ebe67e 992 trackParamAtCluster2 = (AliMUONTrackParam*) track->fTrackParamAtCluster->After(trackParamAtCluster2);
993 } // trackParamAtCluster2
994 trackParamAtCluster1 = (AliMUONTrackParam*) this->fTrackParamAtCluster->After(trackParamAtCluster1);
995 } // trackParamAtCluster1
996 return clustersInCommon;
208f139e 997}
998
ea94c18b 999 //__________________________________________________________________________
1000Double_t AliMUONTrack::GetNormalizedChi2() const
1001{
1002 /// return the chi2 value divided by the number of degrees of freedom (or 1.e10 if ndf < 0)
1003
96ebe67e 1004 Double_t numberOfDegFree = (2. * GetNClusters() - 5.);
ea94c18b 1005 if (numberOfDegFree > 0.) return fGlobalChi2 / numberOfDegFree;
9bf6860b 1006 else return fGlobalChi2; // system is under-constraint
ea94c18b 1007}
1008
208f139e 1009 //__________________________________________________________________________
61fed964 1010Bool_t* AliMUONTrack::CompatibleTrack(AliMUONTrack *track, Double_t sigmaCut) const
b8dc484b 1011{
96ebe67e 1012 /// for each chamber: return kTRUE (kFALSE) if clusters are compatible (not compatible)
1013 AliMUONTrackParam *trackParamAtCluster1, *trackParamAtCluster2;
1014 AliMUONVCluster *cluster1, *cluster2;
1015 Double_t chi2, dX, dY, dZ;
61fed964 1016 Double_t chi2Max = sigmaCut * sigmaCut;
96ebe67e 1017 Double_t dZMax = 1.; // 1 cm
1018
1019 Bool_t *compatibleCluster = new Bool_t[AliMUONConstants::NTrackingCh()];
1020 for ( Int_t ch = 0; ch < AliMUONConstants::NTrackingCh(); ch++) compatibleCluster[ch] = kFALSE;
b8dc484b 1021
7332f213 1022 if (!fTrackParamAtCluster || !this->fTrackParamAtCluster) return compatibleCluster;
1023
96ebe67e 1024 // Loop over clusters of first track
1025 trackParamAtCluster1 = (AliMUONTrackParam*) this->fTrackParamAtCluster->First();
1026 while (trackParamAtCluster1) {
1027
1028 cluster1 = trackParamAtCluster1->GetClusterPtr();
1029
1030 // Loop over clusters of second track
1031 trackParamAtCluster2 = (AliMUONTrackParam*) track->fTrackParamAtCluster->First();
1032 while (trackParamAtCluster2) {
1033
1034 cluster2 = trackParamAtCluster2->GetClusterPtr();
1035
1036 //prepare next step
1037 trackParamAtCluster2 = (AliMUONTrackParam*) track->fTrackParamAtCluster->After(trackParamAtCluster2);
1038
1039 // z direction
1040 dZ = cluster1->GetZ() - cluster2->GetZ();
1041 if (dZ > dZMax) continue;
1042
1043 // non bending direction
1044 dX = cluster1->GetX() - cluster2->GetX();
1045 chi2 = dX * dX / (cluster1->GetErrX2() + cluster2->GetErrX2());
1046 if (chi2 > chi2Max) continue;
1047
1048 // bending direction
1049 dY = cluster1->GetY() - cluster2->GetY();
1050 chi2 = dY * dY / (cluster1->GetErrY2() + cluster2->GetErrY2());
1051 if (chi2 > chi2Max) continue;
1052
1053 compatibleCluster[cluster1->GetChamberId()] = kTRUE;
1054 break;
1055 }
1056
1057 trackParamAtCluster1 = (AliMUONTrackParam*) this->fTrackParamAtCluster->After(trackParamAtCluster1);
b8dc484b 1058 }
1059
96ebe67e 1060 return compatibleCluster;
8429a5e4 1061}
1062
96ebe67e 1063//__________________________________________________________________________
1064void AliMUONTrack::SetTrackParamAtVertex(const AliMUONTrackParam* trackParam)
1065{
1066 /// set track parameters at vertex
1067 if (trackParam == 0x0) return;
1068 if (fTrackParamAtVertex) *fTrackParamAtVertex = *trackParam;
1069 else fTrackParamAtVertex = new AliMUONTrackParam(*trackParam);
1070}
1071
1072//__________________________________________________________________________
1073void AliMUONTrack::RecursiveDump() const
a9e2aefa 1074{
96ebe67e 1075 /// Recursive dump of AliMUONTrack, i.e. with dump of trackParamAtCluster and attached clusters
1076 AliMUONTrackParam *trackParamAtCluster;
1077 AliMUONVCluster *cluster;
de2cd600 1078 cout << "Recursive dump of Track: " << this << endl;
1079 // Track
1080 this->Dump();
96ebe67e 1081 for (Int_t iCluster = 0; iCluster < GetNClusters(); iCluster++) {
1082 trackParamAtCluster = (AliMUONTrackParam*) ((*fTrackParamAtCluster)[iCluster]);
1083 // trackParamAtCluster
1084 cout << "trackParamAtCluster: " << trackParamAtCluster << " (index: " << iCluster << ")" << endl;
1085 trackParamAtCluster->Dump();
1086 cluster = trackParamAtCluster->GetClusterPtr();
1087 // cluster
1088 cout << "cluster: " << cluster << endl;
1089 cluster->Print();
a9e2aefa 1090 }
de2cd600 1091 return;
a9e2aefa 1092}
04b5ea16 1093
6464217e 1094//_____________________________________________-
d2b1e7bb 1095void AliMUONTrack::Print(Option_t*) const
6464217e 1096{
2457f726 1097 /// Printing Track information
d2b1e7bb 1098
96ebe67e 1099 cout << "<AliMUONTrack> No.Clusters=" << setw(2) << GetNClusters() <<
6464217e 1100 ", Match2Trig=" << setw(1) << GetMatchTrigger() <<
c6ba19f7 1101 ", LoTrgNum=" << setw(3) << GetLoTrgNum() <<
d2b1e7bb 1102 ", Chi2-tracking-trigger=" << setw(8) << setprecision(5) << GetChi2MatchTrigger();
1103 cout << Form(" HitTriggerPattern %x",fHitsPatternInTrigCh) << endl;
7332f213 1104 if (fTrackParamAtCluster) fTrackParamAtCluster->First()->Print("FULL");
6464217e 1105}
423b32ca 1106
1107//__________________________________________________________________________
1108void AliMUONTrack::SetLocalTrigger(Int_t loCirc, Int_t loStripX, Int_t loStripY, Int_t loDev, Int_t loLpt, Int_t loHpt)
1109{
1110 /// pack the local trigger information and store
1111
01413742 1112 if (loCirc < 0) return;
423b32ca 1113
1114 fLocalTrigger = 0;
1115 fLocalTrigger += loCirc;
1116 fLocalTrigger += loStripX << 8;
1117 fLocalTrigger += loStripY << 13;
1118 fLocalTrigger += loDev << 17;
1119 fLocalTrigger += loLpt << 22;
1120 fLocalTrigger += loHpt << 24;
1121
1122}
1123