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