1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
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 **************************************************************************/
18 ///////////////////////////////////////////////////
20 // Reconstructed track
26 ///////////////////////////////////////////////////
28 #include "AliMUONTrack.h"
30 #include "AliMUONTrackParam.h"
31 #include "AliMUONHitForRec.h"
32 #include "AliMUONObjectPair.h"
33 #include "AliMUONConstants.h"
34 #include "AliMUONTrackExtrap.h"
41 #include <Riostream.h>
44 ClassImp(AliMUONTrack) // Class implementation in ROOT context
47 //__________________________________________________________________________
48 AliMUONTrack::AliMUONTrack()
50 fTrackParamAtVertex(),
51 fTrackParamAtHit(0x0),
54 fFitWithVertex(kFALSE),
57 fHitWeightsNonBending(0x0),
58 fHitWeightsBending(0x0),
63 fChi2MatchTrigger(0.),
65 fHitsPatternInTrigCh(0),
68 /// Default constructor
71 //__________________________________________________________________________
72 AliMUONTrack::AliMUONTrack(AliMUONObjectPair *segment)
74 fTrackParamAtVertex(),
75 fTrackParamAtHit(0x0),
78 fFitWithVertex(kFALSE),
81 fHitWeightsNonBending(0x0),
82 fHitWeightsBending(0x0),
87 fChi2MatchTrigger(0.),
89 fHitsPatternInTrigCh(0),
92 /// Constructor from thw hitForRec's
94 fTrackParamAtHit = new TClonesArray("AliMUONTrackParam",10);
95 fTrackParamAtHit->SetOwner(kTRUE);
96 fHitForRecAtHit = new TClonesArray("AliMUONHitForRec",10);
97 fHitForRecAtHit->SetOwner(kTRUE);
99 if (!segment) return; //AZ
101 // Pointers to hits from the segment
102 AliMUONHitForRec* hit1 = (AliMUONHitForRec*) segment->First();
103 AliMUONHitForRec* hit2 = (AliMUONHitForRec*) segment->Second();
105 // check sorting in -Z (spectro z<0)
106 if (hit1->GetZ() < hit2->GetZ()) {
108 hit2 = (AliMUONHitForRec*) segment->First();
111 // order the hits into the track according to the station the segment belong to
112 //(the hit first attached is the one from which we will start the tracking procedure)
113 if (hit1->GetChamberNumber() == 8) {
114 AddTrackParamAtHit(0,hit1);
115 AddTrackParamAtHit(0,hit2);
117 AddTrackParamAtHit(0,hit2);
118 AddTrackParamAtHit(0,hit1);
121 AliMUONTrackParam* trackParamAtFirstHit = (AliMUONTrackParam*) fTrackParamAtHit->First();
122 AliMUONHitForRec* firstHit = trackParamAtFirstHit->GetHitForRecPtr();
123 AliMUONTrackParam* trackParamAtLastHit = (AliMUONTrackParam*) fTrackParamAtHit->Last();
124 AliMUONHitForRec* lastHit = trackParamAtLastHit->GetHitForRecPtr();
127 // Compute track parameters
128 Double_t dZ = firstHit->GetZ() - lastHit->GetZ();
130 Double_t nonBendingCoor1 = firstHit->GetNonBendingCoor();
131 Double_t nonBendingCoor2 = lastHit->GetNonBendingCoor();
132 Double_t nonBendingSlope = (nonBendingCoor1 - nonBendingCoor2) / dZ;
134 Double_t bendingCoor1 = firstHit->GetBendingCoor();
135 Double_t bendingCoor2 = lastHit->GetBendingCoor();
136 Double_t bendingSlope = (bendingCoor1 - bendingCoor2) / dZ;
137 // Inverse bending momentum
138 Double_t bendingImpact = bendingCoor1 - firstHit->GetZ() * bendingSlope;
139 Double_t inverseBendingMomentum = 1. / AliMUONTrackExtrap::GetBendingMomentumFromImpactParam(bendingImpact);
142 // Set track parameters at first hit
143 trackParamAtFirstHit->SetNonBendingCoor(nonBendingCoor1);
144 trackParamAtFirstHit->SetNonBendingSlope(nonBendingSlope);
145 trackParamAtFirstHit->SetBendingCoor(bendingCoor1);
146 trackParamAtFirstHit->SetBendingSlope(bendingSlope);
147 trackParamAtFirstHit->SetInverseBendingMomentum(inverseBendingMomentum);
150 // Set track parameters at last hit
151 trackParamAtLastHit->SetNonBendingCoor(nonBendingCoor2);
152 trackParamAtLastHit->SetNonBendingSlope(nonBendingSlope);
153 trackParamAtLastHit->SetBendingCoor(bendingCoor2);
154 trackParamAtLastHit->SetBendingSlope(bendingSlope);
155 trackParamAtLastHit->SetInverseBendingMomentum(inverseBendingMomentum);
158 // Compute and set track parameters covariances at first hit
159 TMatrixD paramCov1(5,5);
162 paramCov1(0,0) = firstHit->GetNonBendingReso2();
163 paramCov1(0,1) = firstHit->GetNonBendingReso2() / dZ;
164 paramCov1(1,0) = paramCov1(0,1);
165 paramCov1(1,1) = ( firstHit->GetNonBendingReso2() + lastHit->GetNonBendingReso2() ) / dZ / dZ;
167 paramCov1(2,2) = firstHit->GetBendingReso2();
168 paramCov1(2,3) = firstHit->GetBendingReso2() / dZ;
169 paramCov1(3,2) = paramCov1(2,3);
170 paramCov1(3,3) = ( firstHit->GetBendingReso2() + lastHit->GetBendingReso2() ) / dZ / dZ;
171 // Inverse bending momentum (50% error)
172 paramCov1(4,4) = 0.5*inverseBendingMomentum * 0.5*inverseBendingMomentum;
174 trackParamAtFirstHit->SetCovariances(paramCov1);
177 // Compute and set track parameters covariances at last hit (as if the first hit did not exist)
178 TMatrixD paramCov2(5,5);
181 paramCov2(0,0) = paramCov1(0,0);
182 paramCov2(1,1) = 100.*paramCov1(1,1);
184 paramCov2(2,2) = paramCov1(2,2);
185 paramCov2(3,3) = 100.*paramCov1(3,3);
186 // Inverse bending momentum
187 paramCov2(4,4) = paramCov1(4,4);
189 trackParamAtLastHit->SetCovariances(paramCov2);
192 // Flag first hit as being removable
193 trackParamAtFirstHit->SetRemovable(kTRUE);
195 // Flag last hit as being removable
196 trackParamAtLastHit->SetRemovable(kTRUE);
200 //__________________________________________________________________________
201 AliMUONTrack::AliMUONTrack (const AliMUONTrack& track)
203 fTrackParamAtVertex(track.fTrackParamAtVertex),
204 fTrackParamAtHit(0x0),
205 fHitForRecAtHit(0x0),
206 fNTrackHits(track.fNTrackHits),
207 fFitWithVertex(track.fFitWithVertex),
209 fFitWithMCS(track.fFitWithMCS),
210 fHitWeightsNonBending(0x0),
211 fHitWeightsBending(0x0),
212 fGlobalChi2(track.fGlobalChi2),
213 fImproved(track.fImproved),
214 fMatchTrigger(track.fMatchTrigger),
215 floTrgNum(track.floTrgNum),
216 fChi2MatchTrigger(track.fChi2MatchTrigger),
217 fTrackID(track.fTrackID),
218 fHitsPatternInTrigCh(track.fHitsPatternInTrigCh),
219 fLocalTrigger(track.fLocalTrigger)
224 // necessary to make a copy of the objects and not only the pointers in TClonesArray.
225 if (track.fTrackParamAtHit) {
226 maxIndex = (track.fTrackParamAtHit)->GetEntriesFast();
227 fTrackParamAtHit = new TClonesArray("AliMUONTrackParam",maxIndex);
228 for (Int_t index = 0; index < maxIndex; index++) {
229 new ((*fTrackParamAtHit)[index]) AliMUONTrackParam(*(AliMUONTrackParam*)track.fTrackParamAtHit->At(index));
233 // necessary to make a copy of the objects and not only the pointers in TClonesArray.
234 if (track.fHitForRecAtHit) {
235 maxIndex = (track.fHitForRecAtHit)->GetEntriesFast();
236 fHitForRecAtHit = new TClonesArray("AliMUONHitForRec",maxIndex);
237 for (Int_t index = 0; index < maxIndex; index++) {
238 new ((*fHitForRecAtHit)[index]) AliMUONHitForRec(*(AliMUONHitForRec*)track.fHitForRecAtHit->At(index));
242 // copy vertex used during the tracking procedure if any
243 if (track.fVertex) fVertex = new AliMUONHitForRec(*(track.fVertex));
245 // copy hit weights matrices if any
246 if (track.fHitWeightsNonBending) fHitWeightsNonBending = new TMatrixD(*(track.fHitWeightsNonBending));
247 if (track.fHitWeightsBending) fHitWeightsBending = new TMatrixD(*(track.fHitWeightsBending));
251 //__________________________________________________________________________
252 AliMUONTrack & AliMUONTrack::operator=(const AliMUONTrack& track)
254 /// Asignment operator
255 // check assignement to self
259 // base class assignement
260 TObject::operator=(track);
262 fTrackParamAtVertex = track.fTrackParamAtVertex;
266 // necessary to make a copy of the objects and not only the pointers in TClonesArray.
267 if (track.fTrackParamAtHit) {
268 if (fTrackParamAtHit) fTrackParamAtHit->Clear();
269 else fTrackParamAtHit = new TClonesArray("AliMUONTrackParam",10);
270 maxIndex = (track.fTrackParamAtHit)->GetEntriesFast();
271 for (Int_t index = 0; index < maxIndex; index++) {
272 new ((*fTrackParamAtHit)[fTrackParamAtHit->GetEntriesFast()])
273 AliMUONTrackParam(*(AliMUONTrackParam*)(track.fTrackParamAtHit)->At(index));
275 } else if (fTrackParamAtHit) {
276 delete fTrackParamAtHit;
277 fTrackParamAtHit = 0x0;
280 // necessary to make a copy of the objects and not only the pointers in TClonesArray.
281 if (track.fHitForRecAtHit) {
282 if (fHitForRecAtHit) fHitForRecAtHit->Clear();
283 else fHitForRecAtHit = new TClonesArray("AliMUONHitForRec",10);
284 maxIndex = (track.fHitForRecAtHit)->GetEntriesFast();
285 for (Int_t index = 0; index < maxIndex; index++) {
286 new ((*fHitForRecAtHit)[fHitForRecAtHit->GetEntriesFast()])
287 AliMUONHitForRec(*(AliMUONHitForRec*)(track.fHitForRecAtHit)->At(index));
289 } else if (fHitForRecAtHit) {
290 delete fHitForRecAtHit;
291 fHitForRecAtHit = 0x0;
294 // copy vertex used during the tracking procedure if any.
296 if (fVertex) *fVertex = *(track.fVertex);
297 else fVertex = new AliMUONHitForRec(*(track.fVertex));
298 } else if (fVertex) {
303 // copy hit weights matrix if any
304 if (track.fHitWeightsNonBending) {
305 if (fHitWeightsNonBending) {
306 fHitWeightsNonBending->ResizeTo(*(track.fHitWeightsNonBending));
307 *fHitWeightsNonBending = *(track.fHitWeightsNonBending);
308 } else fHitWeightsNonBending = new TMatrixD(*(track.fHitWeightsNonBending));
309 } else if (fHitWeightsNonBending) {
310 delete fHitWeightsNonBending;
311 fHitWeightsNonBending = 0x0;
314 // copy hit weights matrix if any
315 if (track.fHitWeightsBending) {
316 if (fHitWeightsBending) {
317 fHitWeightsBending->ResizeTo(*(track.fHitWeightsBending));
318 *fHitWeightsBending = *(track.fHitWeightsBending);
319 } else fHitWeightsBending = new TMatrixD(*(track.fHitWeightsBending));
320 } else if (fHitWeightsBending) {
321 delete fHitWeightsBending;
322 fHitWeightsBending = 0x0;
325 fNTrackHits = track.fNTrackHits;
326 fFitWithVertex = track.fFitWithVertex;
327 fFitWithMCS = track.fFitWithMCS;
328 fGlobalChi2 = track.fGlobalChi2;
329 fImproved = track.fImproved;
330 fMatchTrigger = track.fMatchTrigger;
331 floTrgNum = track.floTrgNum;
332 fChi2MatchTrigger = track.fChi2MatchTrigger;
333 fTrackID = track.fTrackID;
334 fHitsPatternInTrigCh = track.fHitsPatternInTrigCh;
335 fLocalTrigger = track.fLocalTrigger;
340 //__________________________________________________________________________
341 AliMUONTrack::~AliMUONTrack()
344 delete fTrackParamAtHit;
345 delete fHitForRecAtHit;
347 delete fHitWeightsNonBending;
348 delete fHitWeightsBending;
351 //__________________________________________________________________________
352 void AliMUONTrack::Clear(Option_t* opt)
355 if ( fTrackParamAtHit ) fTrackParamAtHit->Clear(opt);
356 if ( fHitForRecAtHit ) fHitForRecAtHit->Clear(opt);
357 delete fVertex; fVertex = 0x0;
358 delete fHitWeightsNonBending; fHitWeightsNonBending = 0x0;
359 delete fHitWeightsBending; fHitWeightsBending = 0x0;
362 //__________________________________________________________________________
363 void AliMUONTrack::AddTrackParamAtHit(const AliMUONTrackParam *trackParam, AliMUONHitForRec *hitForRec)
365 /// Add TrackParamAtHit if "trackParam" != NULL
366 /// else create empty TrackParamAtHit and set the z position to the one of "hitForRec" if any
367 /// Update link to HitForRec if "hitForRec" != NULL
368 if (!fTrackParamAtHit) {
369 fTrackParamAtHit = new TClonesArray("AliMUONTrackParam",10);
372 AliMUONTrackParam* trackParamAtHit;
374 trackParamAtHit = new ((*fTrackParamAtHit)[fNTrackHits]) AliMUONTrackParam(*trackParam);
376 if (hitForRec->GetZ() != trackParam->GetZ())
377 AliWarning("Added track parameters at a different z position than the one of the attached hit");
380 trackParamAtHit = new ((*fTrackParamAtHit)[fNTrackHits]) AliMUONTrackParam();
381 if (hitForRec) trackParamAtHit->SetZ(hitForRec->GetZ());
383 if (hitForRec) trackParamAtHit->SetHitForRecPtr(hitForRec);
387 //__________________________________________________________________________
388 void AliMUONTrack::RemoveTrackParamAtHit(AliMUONTrackParam *trackParam)
390 /// Remove trackParam from the array of TrackParamAtHit
391 if (!fTrackParamAtHit) {
392 AliWarning("array fTrackParamAtHit does not exist");
396 if (!fTrackParamAtHit->Remove(trackParam)) {
397 AliWarning("object to remove does not exist in array fTrackParamAtHit");
401 fTrackParamAtHit->Compress();
405 //__________________________________________________________________________
406 void AliMUONTrack::AddHitForRecAtHit(const AliMUONHitForRec *hitForRec)
408 /// Add hitForRec to the array of hitForRec at hit
409 if (!fHitForRecAtHit)
410 fHitForRecAtHit = new TClonesArray("AliMUONHitForRec",10);
413 AliFatal("AliMUONTrack::AddHitForRecAtHit: hitForRec == NULL");
415 new ((*fHitForRecAtHit)[fHitForRecAtHit->GetEntriesFast()]) AliMUONHitForRec(*hitForRec);
418 //__________________________________________________________________________
419 void AliMUONTrack::UpdateTrackParamAtHit()
421 /// Update track parameters at each attached hit
423 if (fNTrackHits == 0) {
424 AliWarning("no hit attached to the track");
429 AliMUONTrackParam* startingTrackParam = (AliMUONTrackParam*) fTrackParamAtHit->First();
430 AliMUONTrackParam* trackParamAtHit = (AliMUONTrackParam*) fTrackParamAtHit->After(startingTrackParam);
431 while (trackParamAtHit) {
434 z = trackParamAtHit->GetZ();
436 // reset track parameters and their covariances
437 trackParamAtHit->SetParameters(startingTrackParam->GetParameters());
438 trackParamAtHit->SetZ(startingTrackParam->GetZ());
440 // extrapolation to the given z
441 AliMUONTrackExtrap::ExtrapToZ(trackParamAtHit, z);
444 startingTrackParam = trackParamAtHit;
445 trackParamAtHit = (AliMUONTrackParam*) (fTrackParamAtHit->After(trackParamAtHit));
450 //__________________________________________________________________________
451 void AliMUONTrack::UpdateCovTrackParamAtHit()
453 /// Update track parameters and their covariances at each attached hit
455 if (fNTrackHits == 0) {
456 AliWarning("no hit attached to the track");
461 AliMUONTrackParam* startingTrackParam = (AliMUONTrackParam*) fTrackParamAtHit->First();
462 AliMUONTrackParam* trackParamAtHit = (AliMUONTrackParam*) fTrackParamAtHit->After(startingTrackParam);
463 while (trackParamAtHit) {
466 z = trackParamAtHit->GetZ();
468 // reset track parameters and their covariances
469 trackParamAtHit->SetParameters(startingTrackParam->GetParameters());
470 trackParamAtHit->SetZ(startingTrackParam->GetZ());
471 trackParamAtHit->SetCovariances(startingTrackParam->GetCovariances());
473 // extrapolation to the given z
474 AliMUONTrackExtrap::ExtrapToZCov(trackParamAtHit, z);
477 startingTrackParam = trackParamAtHit;
478 trackParamAtHit = (AliMUONTrackParam*) (fTrackParamAtHit->After(trackParamAtHit));
483 //__________________________________________________________________________
484 void AliMUONTrack::SetVertex(const AliMUONHitForRec* vertex)
486 /// Set the vertex used during the tracking procedure
487 if (!fVertex) fVertex = new AliMUONHitForRec(*vertex);
488 else *fVertex = *vertex;
492 //__________________________________________________________________________
493 Bool_t AliMUONTrack::ComputeLocalChi2(Bool_t accountForMCS)
495 /// Compute the removable hit contribution to the chi2 of the track
496 /// accounting for multiple scattering or not according to the flag
497 /// - Also recompute the weight matrices of the attached hits if accountForMCS=kTRUE
498 /// - Assume that track parameters at each hit are corrects
499 /// - Return kFALSE if computation failed
501 // Check hits (if the first one exist, assume that the other ones exit too!)
502 AliMUONTrackParam* trackParamAtHit = (AliMUONTrackParam*) fTrackParamAtHit->First();
503 if (!trackParamAtHit->GetHitForRecPtr()) {
504 AliWarning("hit is missing");
508 if (accountForMCS) { // Compute local chi2 taking into account multiple scattering effects
510 // Compute MCS covariance matrix only once
511 TMatrixD mcsCovariances(AliMUONConstants::NTrackingCh(),AliMUONConstants::NTrackingCh());
512 ComputeMCSCovariances(mcsCovariances);
514 // Make sure hit weights are consistent with following calculations
515 if (!ComputeHitWeights(&mcsCovariances)) {
516 AliWarning("cannot take into account the multiple scattering effects");
517 return ComputeLocalChi2(kFALSE);
520 // Compute chi2 of the track
521 Double_t globalChi2 = ComputeGlobalChi2(kTRUE);
522 if (globalChi2 < 0.) return kFALSE;
524 // Loop over removable hits and compute their local chi2
525 AliMUONTrackParam* trackParamAtHit1;
526 AliMUONHitForRec *hitForRec, *discardedHit;
527 Int_t hitNumber1, hitNumber2, currentHitNumber1, currentHitNumber2;
528 TMatrixD hitWeightsNB(fNTrackHits-1,fNTrackHits-1);
529 TMatrixD hitWeightsB(fNTrackHits-1,fNTrackHits-1);
530 Double_t *dX = new Double_t[fNTrackHits-1];
531 Double_t *dY = new Double_t[fNTrackHits-1];
532 Double_t globalChi2b;
533 while (trackParamAtHit) {
535 discardedHit = trackParamAtHit->GetHitForRecPtr();
537 // Recompute hit weights without the current hit
538 if (!ComputeHitWeights(hitWeightsNB, hitWeightsB, &mcsCovariances, discardedHit)) {
539 AliWarning("cannot take into account the multiple scattering effects");
540 ComputeLocalChi2(kFALSE);
543 // Compute track chi2 without the current hit
545 currentHitNumber1 = 0;
546 for (hitNumber1 = 0; hitNumber1 < fNTrackHits ; hitNumber1++) {
547 trackParamAtHit1 = (AliMUONTrackParam*) fTrackParamAtHit->UncheckedAt(hitNumber1);
548 hitForRec = trackParamAtHit1->GetHitForRecPtr();
550 if (hitForRec == discardedHit) continue;
552 // Compute and save residuals
553 dX[currentHitNumber1] = hitForRec->GetNonBendingCoor() - trackParamAtHit1->GetNonBendingCoor();
554 dY[currentHitNumber1] = hitForRec->GetBendingCoor() - trackParamAtHit1->GetBendingCoor();
556 currentHitNumber2 = 0;
557 for (hitNumber2 = 0; hitNumber2 < hitNumber1; hitNumber2++) {
558 hitForRec = ((AliMUONTrackParam*) fTrackParamAtHit->UncheckedAt(hitNumber2))->GetHitForRecPtr();
560 if (hitForRec == discardedHit) continue;
562 // Add contribution from covariances
563 globalChi2b += (hitWeightsNB(currentHitNumber1, currentHitNumber2) +
564 hitWeightsNB(currentHitNumber2, currentHitNumber1)) * dX[currentHitNumber1] * dX[currentHitNumber2] +
565 (hitWeightsB(currentHitNumber1, currentHitNumber2) +
566 hitWeightsB(currentHitNumber2, currentHitNumber1)) * dY[currentHitNumber1] * dY[currentHitNumber2];
571 // Add contribution from variances
572 globalChi2b += hitWeightsNB(currentHitNumber1, currentHitNumber1) * dX[currentHitNumber1] * dX[currentHitNumber1] +
573 hitWeightsB(currentHitNumber1, currentHitNumber1) * dY[currentHitNumber1] * dY[currentHitNumber1];
579 trackParamAtHit->SetLocalChi2(globalChi2 - globalChi2b);
581 trackParamAtHit = (AliMUONTrackParam*) fTrackParamAtHit->After(trackParamAtHit);
587 } else { // without multiple scattering effects
589 AliMUONHitForRec *discardedHit;
591 while (trackParamAtHit) {
593 discardedHit = trackParamAtHit->GetHitForRecPtr();
596 dX = discardedHit->GetNonBendingCoor() - trackParamAtHit->GetNonBendingCoor();
597 dY = discardedHit->GetBendingCoor() - trackParamAtHit->GetBendingCoor();
600 trackParamAtHit->SetLocalChi2(dX * dX / discardedHit->GetNonBendingReso2() + dY * dY / discardedHit->GetBendingReso2());
602 trackParamAtHit = (AliMUONTrackParam*) fTrackParamAtHit->After(trackParamAtHit);
612 //__________________________________________________________________________
613 Double_t AliMUONTrack::ComputeGlobalChi2(Bool_t accountForMCS)
615 /// Compute the chi2 of the track accounting for multiple scattering or not according to the flag
616 /// - Assume that track parameters at each hit are corrects
617 /// - Assume the hits weights matrices are corrects
618 /// - Return negative value if chi2 computation failed
620 // Check hits (if the first one exist, assume that the other ones exit too!)
621 AliMUONTrackParam* trackParamAtHit = (AliMUONTrackParam*) fTrackParamAtHit->First();
622 if (!trackParamAtHit->GetHitForRecPtr()) {
623 AliWarning("hit is missing");
631 // Check the weight matrices
632 Bool_t weightsAvailable = kTRUE;
633 if (!fHitWeightsNonBending || !fHitWeightsBending) weightsAvailable = kFALSE;
634 else if (fHitWeightsNonBending->GetNrows() != fNTrackHits || fHitWeightsNonBending->GetNcols() != fNTrackHits ||
635 fHitWeightsBending->GetNrows() != fNTrackHits || fHitWeightsBending->GetNcols() != fNTrackHits) weightsAvailable = kFALSE;
637 // if weight matrices are not available compute chi2 without MCS
638 if (!weightsAvailable) {
639 AliWarning("hit weights including multiple scattering effects are not available\n\t\t --> compute chi2 WITHOUT multiple scattering");
640 return ComputeGlobalChi2(kFALSE);
644 AliMUONHitForRec *hitForRec;
645 Double_t *dX = new Double_t[fNTrackHits];
646 Double_t *dY = new Double_t[fNTrackHits];
647 Int_t hitNumber1, hitNumber2;
648 for (hitNumber1 = 0; hitNumber1 < fNTrackHits ; hitNumber1++) {
649 trackParamAtHit = (AliMUONTrackParam*) fTrackParamAtHit->UncheckedAt(hitNumber1);
650 hitForRec = trackParamAtHit->GetHitForRecPtr();
651 dX[hitNumber1] = hitForRec->GetNonBendingCoor() - trackParamAtHit->GetNonBendingCoor();
652 dY[hitNumber1] = hitForRec->GetBendingCoor() - trackParamAtHit->GetBendingCoor();
653 for (hitNumber2 = 0; hitNumber2 < hitNumber1; hitNumber2++) {
654 chi2 += ((*fHitWeightsNonBending)(hitNumber1, hitNumber2) + (*fHitWeightsNonBending)(hitNumber2, hitNumber1)) * dX[hitNumber1] * dX[hitNumber2] +
655 ((*fHitWeightsBending)(hitNumber1, hitNumber2) + (*fHitWeightsBending)(hitNumber2, hitNumber1)) * dY[hitNumber1] * dY[hitNumber2];
657 chi2 += ((*fHitWeightsNonBending)(hitNumber1, hitNumber1) * dX[hitNumber1] * dX[hitNumber1]) +
658 ((*fHitWeightsBending)(hitNumber1, hitNumber1) * dY[hitNumber1] * dY[hitNumber1]);
665 AliMUONHitForRec *hitForRec;
667 for (Int_t hitNumber = 0; hitNumber < fNTrackHits ; hitNumber++) {
668 trackParamAtHit = (AliMUONTrackParam*) fTrackParamAtHit->UncheckedAt(hitNumber);
669 hitForRec = trackParamAtHit->GetHitForRecPtr();
670 dX = hitForRec->GetNonBendingCoor() - trackParamAtHit->GetNonBendingCoor();
671 dY = hitForRec->GetBendingCoor() - trackParamAtHit->GetBendingCoor();
672 chi2 += dX * dX / hitForRec->GetNonBendingReso2() + dY * dY / hitForRec->GetBendingReso2();
681 //__________________________________________________________________________
682 Bool_t AliMUONTrack::ComputeHitWeights(TMatrixD* mcsCovariances)
684 /// Compute the weight matrices of the attached hits, in non bending and bending direction,
685 /// accounting for multiple scattering correlations and hits resolution
686 /// - Use the provided MCS covariance matrix if any (otherwise build it temporarily)
687 /// - Assume that track parameters at each hit are corrects
688 /// - Return kFALSE if computation failed
691 if (!fHitWeightsNonBending) fHitWeightsNonBending = new TMatrixD(fNTrackHits,fNTrackHits);
692 if (!fHitWeightsBending) fHitWeightsBending = new TMatrixD(fNTrackHits,fNTrackHits);
694 // Check hits (if the first one exist, assume that the other ones exit too!)
695 if (!((AliMUONTrackParam*) fTrackParamAtHit->First())->GetHitForRecPtr()) {
696 AliWarning("hit is missing");
697 fHitWeightsNonBending->ResizeTo(0,0);
698 fHitWeightsBending->ResizeTo(0,0);
702 // Compute weights matrices
703 if (!ComputeHitWeights(*fHitWeightsNonBending, *fHitWeightsBending, mcsCovariances)) return kFALSE;
709 //__________________________________________________________________________
710 Bool_t AliMUONTrack::ComputeHitWeights(TMatrixD& hitWeightsNB, TMatrixD& hitWeightsB, TMatrixD* mcsCovariances, AliMUONHitForRec* discardedHit) const
712 /// Compute the weight matrices, in non bending and bending direction,
713 /// of the other attached hits assuming the discarded one does not exist
714 /// accounting for multiple scattering correlations and hits resolution
715 /// - Use the provided MCS covariance matrix if any (otherwise build it temporarily)
716 /// - Return kFALSE if computation failed
718 // Check MCS covariance matrix and recompute it if need
719 Bool_t deleteMCSCov = kFALSE;
720 if (!mcsCovariances) {
722 // build MCS covariance matrix
723 mcsCovariances = new TMatrixD(AliMUONConstants::NTrackingCh(),AliMUONConstants::NTrackingCh());
724 deleteMCSCov = kTRUE;
725 ComputeMCSCovariances(*mcsCovariances);
729 // check MCS covariance matrix size
730 if (mcsCovariances->GetNrows() != AliMUONConstants::NTrackingCh() || mcsCovariances->GetNcols() != AliMUONConstants::NTrackingCh()) {
731 ComputeMCSCovariances(*mcsCovariances);
736 // Resize the weights matrices; alocate memory
738 hitWeightsNB.ResizeTo(fNTrackHits-1,fNTrackHits-1);
739 hitWeightsB.ResizeTo(fNTrackHits-1,fNTrackHits-1);
741 hitWeightsNB.ResizeTo(fNTrackHits,fNTrackHits);
742 hitWeightsB.ResizeTo(fNTrackHits,fNTrackHits);
746 AliMUONHitForRec *hitForRec1, *hitForRec2;
747 Int_t chamber1, chamber2, currentHitNumber1, currentHitNumber2;
749 // Compute the covariance matrices
750 currentHitNumber1 = 0;
751 for (Int_t hitNumber1 = 0; hitNumber1 < fNTrackHits; hitNumber1++) {
752 hitForRec1 = ((AliMUONTrackParam*) fTrackParamAtHit->UncheckedAt(hitNumber1))->GetHitForRecPtr();
754 if (hitForRec1 == discardedHit) continue;
756 chamber1 = hitForRec1->GetChamberNumber();
758 // Loop over next hits
759 currentHitNumber2 = currentHitNumber1;
760 for (Int_t hitNumber2 = hitNumber1; hitNumber2 < fNTrackHits; hitNumber2++) {
761 hitForRec2 = ((AliMUONTrackParam*) fTrackParamAtHit->UncheckedAt(hitNumber2))->GetHitForRecPtr();
763 if (hitForRec2 == discardedHit) continue;
765 chamber2 = hitForRec2->GetChamberNumber();
767 // Fill with MCS covariances
768 hitWeightsNB(currentHitNumber1, currentHitNumber2) = (*mcsCovariances)(chamber1,chamber2);
770 // Equal contribution from multiple scattering in non bending and bending directions
771 hitWeightsB(currentHitNumber1, currentHitNumber2) = hitWeightsNB(currentHitNumber1, currentHitNumber2);
773 // Add contribution from hit resolution to diagonal element and symmetrize the matrix
774 if (currentHitNumber1 == currentHitNumber2) {
776 // In non bending plane
777 hitWeightsNB(currentHitNumber1, currentHitNumber1) += hitForRec1->GetNonBendingReso2();
779 hitWeightsB(currentHitNumber1, currentHitNumber1) += hitForRec1->GetBendingReso2();
783 // In non bending plane
784 hitWeightsNB(currentHitNumber2, currentHitNumber1) = hitWeightsNB(currentHitNumber1, currentHitNumber2);
786 hitWeightsB(currentHitNumber2, currentHitNumber1) = hitWeightsB(currentHitNumber1, currentHitNumber2);
796 // Inversion of covariance matrices to get the weights
797 if (hitWeightsNB.Determinant() != 0 && hitWeightsB.Determinant() != 0) {
798 hitWeightsNB.Invert();
799 hitWeightsB.Invert();
801 AliWarning(" Determinant = 0");
802 hitWeightsNB.ResizeTo(0,0);
803 hitWeightsB.ResizeTo(0,0);
804 if(deleteMCSCov) delete mcsCovariances;
808 if(deleteMCSCov) delete mcsCovariances;
814 //__________________________________________________________________________
815 void AliMUONTrack::ComputeMCSCovariances(TMatrixD& mcsCovariances) const
817 /// Compute the multiple scattering covariance matrix
818 /// - Assume that track parameters at each hit are corrects
819 /// - Return kFALSE if computation failed
821 // Make sure the size of the covariance matrix is correct
822 Int_t nChambers = AliMUONConstants::NTrackingCh();
823 mcsCovariances.ResizeTo(nChambers,nChambers);
825 // check for too many track hits
826 if (fNTrackHits > nChambers) {
827 AliWarning("more than 1 hit per chamber!!");
828 mcsCovariances.Zero();
833 AliMUONTrackParam* trackParamAtHit;
834 AliMUONHitForRec *hitForRec;
835 AliMUONTrackParam extrapTrackParam;
836 Int_t currentChamber, expectedChamber;
837 Double_t *mcsAngle2 = new Double_t[nChambers];
838 Double_t *zMCS = new Double_t[nChambers];
840 // Compute multiple scattering dispersion angle at each chamber
841 // and save the z position where it is calculated
844 for (Int_t hitNumber = 0; hitNumber < fNTrackHits; hitNumber++) {
845 trackParamAtHit = (AliMUONTrackParam*) fTrackParamAtHit->UncheckedAt(hitNumber);
846 hitForRec = trackParamAtHit->GetHitForRecPtr();
848 // look for missing chambers if any
849 currentChamber = hitForRec->GetChamberNumber();
850 while (currentChamber > expectedChamber) {
852 // Save the z position where MCS dispersion is calculated
853 zMCS[expectedChamber] = AliMUONConstants::DefaultChamberZ(expectedChamber);
855 // Do not take into account MCS in chambers prior the first hit
858 // Get track parameters at missing chamber z
859 extrapTrackParam = *trackParamAtHit;
860 AliMUONTrackExtrap::ExtrapToZ(&extrapTrackParam, zMCS[expectedChamber]);
862 // Save multiple scattering dispersion angle in missing chamber
863 mcsAngle2[expectedChamber] = AliMUONTrackExtrap::GetMCSAngle2(extrapTrackParam,AliMUONConstants::ChamberThicknessInX0(),1.);
865 } else mcsAngle2[expectedChamber] = 0.;
870 // Save z position where MCS dispersion is calculated
871 zMCS[currentChamber] = trackParamAtHit->GetZ();
873 // Save multiple scattering dispersion angle in current chamber
874 mcsAngle2[currentChamber] = AliMUONTrackExtrap::GetMCSAngle2(*trackParamAtHit,AliMUONConstants::ChamberThicknessInX0(),1.);
879 // complete array of z if last hit is on the last but one chamber
880 if (currentChamber != nChambers-1) zMCS[nChambers-1] = AliMUONConstants::DefaultChamberZ(nChambers-1);
883 // Compute the covariance matrix
884 for (Int_t chamber1 = 0; chamber1 < nChambers; chamber1++) {
886 for (Int_t chamber2 = chamber1; chamber2 < nChambers; chamber2++) {
888 // Initialization to 0 (diagonal plus upper triangular part)
889 mcsCovariances(chamber1, chamber2) = 0.;
891 // Compute contribution from multiple scattering in upstream chambers
892 for (currentChamber = 0; currentChamber < chamber1; currentChamber++) {
893 mcsCovariances(chamber1, chamber2) += (zMCS[chamber1] - zMCS[currentChamber]) * (zMCS[chamber2] - zMCS[currentChamber]) * mcsAngle2[currentChamber];
896 // Symetrize the matrix
897 mcsCovariances(chamber2, chamber1) = mcsCovariances(chamber1, chamber2);
907 //__________________________________________________________________________
908 Int_t AliMUONTrack::HitsInCommon(AliMUONTrack* track) const
910 /// Returns the number of hits in common between the current track ("this")
911 /// and the track pointed to by "track".
912 Int_t hitsInCommon = 0;
913 AliMUONTrackParam *trackParamAtHit1, *trackParamAtHit2;
914 // Loop over hits of first track
915 trackParamAtHit1 = (AliMUONTrackParam*) this->fTrackParamAtHit->First();
916 while (trackParamAtHit1) {
917 // Loop over hits of second track
918 trackParamAtHit2 = (AliMUONTrackParam*) track->fTrackParamAtHit->First();
919 while (trackParamAtHit2) {
920 // Increment "hitsInCommon" if both TrackParamAtHits point to the same HitForRec
921 if ((trackParamAtHit1->GetHitForRecPtr()) == (trackParamAtHit2->GetHitForRecPtr())) {
925 trackParamAtHit2 = (AliMUONTrackParam*) track->fTrackParamAtHit->After(trackParamAtHit2);
926 } // trackParamAtHit2
927 trackParamAtHit1 = (AliMUONTrackParam*) this->fTrackParamAtHit->After(trackParamAtHit1);
928 } // trackParamAtHit1
932 //__________________________________________________________________________
933 Double_t AliMUONTrack::GetNormalizedChi2() const
935 /// return the chi2 value divided by the number of degrees of freedom (or 1.e10 if ndf < 0)
937 Double_t numberOfDegFree = (2. * fNTrackHits - 5.);
938 if (numberOfDegFree > 0.) return fGlobalChi2 / numberOfDegFree;
942 //__________________________________________________________________________
943 Bool_t* AliMUONTrack::CompatibleTrack(AliMUONTrack * track, Double_t sigma2Cut) const
945 /// Return kTRUE/kFALSE for each chamber if hit is compatible or not
946 TClonesArray *hitArray, *thisHitArray;
947 AliMUONHitForRec *hit, *thisHit;
950 Float_t deltaZMax = 1.; // 1 cm
952 Bool_t *nCompHit = new Bool_t[AliMUONConstants::NTrackingCh()];
954 for ( Int_t ch = 0; ch < AliMUONConstants::NTrackingCh(); ch++) {
955 nCompHit[ch] = kFALSE;
958 thisHitArray = this->GetHitForRecAtHit();
960 hitArray = track->GetHitForRecAtHit();
962 for (Int_t iHthis = 0; iHthis < thisHitArray->GetEntriesFast(); iHthis++) {
963 thisHit = (AliMUONHitForRec*) thisHitArray->At(iHthis);
964 chamberNumber = thisHit->GetChamberNumber();
965 if (chamberNumber < 0 || chamberNumber > AliMUONConstants::NTrackingCh()) continue;
966 nCompHit[chamberNumber] = kFALSE;
967 for (Int_t iH = 0; iH < hitArray->GetEntriesFast(); iH++) {
968 hit = (AliMUONHitForRec*) hitArray->At(iH);
969 deltaZ = TMath::Abs(thisHit->GetZ() - hit->GetZ());
970 chi2 = thisHit->NormalizedChi2WithHitForRec(hit,sigma2Cut); // set cut to 4 sigmas
971 if (chi2 < 3. && deltaZ < deltaZMax) {
972 nCompHit[chamberNumber] = kTRUE;
981 //__________________________________________________________________________
982 void AliMUONTrack::RecursiveDump(void) const
984 /// Recursive dump of AliMUONTrack, i.e. with dump of TrackParamAtHit's and attached HitForRec's
985 AliMUONTrackParam *trackParamAtHit;
986 AliMUONHitForRec *hitForRec;
987 cout << "Recursive dump of Track: " << this << endl;
990 for (Int_t trackHitIndex = 0; trackHitIndex < fNTrackHits; trackHitIndex++) {
991 trackParamAtHit = (AliMUONTrackParam*) ((*fTrackParamAtHit)[trackHitIndex]);
993 cout << "TrackParamAtHit: " << trackParamAtHit << " (index: " << trackHitIndex << ")" << endl;
994 trackParamAtHit->Dump();
995 hitForRec = trackParamAtHit->GetHitForRecPtr();
997 cout << "HitForRec: " << hitForRec << endl;
1003 //_____________________________________________-
1004 void AliMUONTrack::Print(Option_t*) const
1006 /// Printing Track information
1008 cout << "<AliMUONTrack> No.Clusters=" << setw(2) << GetNTrackHits() <<
1009 ", Match2Trig=" << setw(1) << GetMatchTrigger() <<
1010 ", LoTrgNum=" << setw(3) << GetLoTrgNum() <<
1011 ", Chi2-tracking-trigger=" << setw(8) << setprecision(5) << GetChi2MatchTrigger();
1012 cout << Form(" HitTriggerPattern %x",fHitsPatternInTrigCh) << endl;
1013 GetTrackParamAtHit()->First()->Print("FULL");
1016 //__________________________________________________________________________
1017 void AliMUONTrack::SetLocalTrigger(Int_t loCirc, Int_t loStripX, Int_t loStripY, Int_t loDev, Int_t loLpt, Int_t loHpt)
1019 /// pack the local trigger information and store
1021 if (loCirc < 0 || loCirc > 233) return;
1024 fLocalTrigger += loCirc;
1025 fLocalTrigger += loStripX << 8;
1026 fLocalTrigger += loStripY << 13;
1027 fLocalTrigger += loDev << 17;
1028 fLocalTrigger += loLpt << 22;
1029 fLocalTrigger += loHpt << 24;