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