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