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