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) ((AliMUONTrackParam*) fTrackParamAtHit->UncheckedAt(fNTrackHits))->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 // compute chi2 of removable hits only
594 if (!trackParamAtHit->IsRemovable()) {
595 trackParamAtHit = (AliMUONTrackParam*) fTrackParamAtHit->After(trackParamAtHit);
599 discardedHit = trackParamAtHit->GetHitForRecPtr();
602 dX = discardedHit->GetNonBendingCoor() - trackParamAtHit->GetNonBendingCoor();
603 dY = discardedHit->GetBendingCoor() - trackParamAtHit->GetBendingCoor();
606 trackParamAtHit->SetLocalChi2(dX * dX / discardedHit->GetNonBendingReso2() + dY * dY / discardedHit->GetBendingReso2());
608 trackParamAtHit = (AliMUONTrackParam*) fTrackParamAtHit->After(trackParamAtHit);
618 //__________________________________________________________________________
619 Double_t AliMUONTrack::ComputeGlobalChi2(Bool_t accountForMCS)
621 /// Compute the chi2 of the track accounting for multiple scattering or not according to the flag
622 /// - Assume that track parameters at each hit are corrects
623 /// - Assume the hits weights matrices are corrects
624 /// - Return negative value if chi2 computation failed
626 // Check hits (if the first one exist, assume that the other ones exit too!)
627 AliMUONTrackParam* trackParamAtHit = (AliMUONTrackParam*) fTrackParamAtHit->First();
628 if (!trackParamAtHit->GetHitForRecPtr()) {
629 AliWarning("hit is missing");
637 // Check the weight matrices
638 Bool_t weightsAvailable = kTRUE;
639 if (!fHitWeightsNonBending || !fHitWeightsBending) weightsAvailable = kFALSE;
640 else if (fHitWeightsNonBending->GetNrows() != fNTrackHits || fHitWeightsNonBending->GetNcols() != fNTrackHits ||
641 fHitWeightsBending->GetNrows() != fNTrackHits || fHitWeightsBending->GetNcols() != fNTrackHits) weightsAvailable = kFALSE;
643 // if weight matrices are not available compute chi2 without MCS
644 if (!weightsAvailable) {
645 AliWarning("hit weights including multiple scattering effects are not available\n\t\t --> compute chi2 WITHOUT multiple scattering");
646 return ComputeGlobalChi2(kFALSE);
650 AliMUONHitForRec *hitForRec;
651 Double_t *dX = new Double_t[fNTrackHits];
652 Double_t *dY = new Double_t[fNTrackHits];
653 Int_t hitNumber1, hitNumber2;
654 for (hitNumber1 = 0; hitNumber1 < fNTrackHits ; hitNumber1++) {
655 trackParamAtHit = (AliMUONTrackParam*) fTrackParamAtHit->UncheckedAt(hitNumber1);
656 hitForRec = trackParamAtHit->GetHitForRecPtr();
657 dX[hitNumber1] = hitForRec->GetNonBendingCoor() - trackParamAtHit->GetNonBendingCoor();
658 dY[hitNumber1] = hitForRec->GetBendingCoor() - trackParamAtHit->GetBendingCoor();
659 for (hitNumber2 = 0; hitNumber2 < hitNumber1; hitNumber2++) {
660 chi2 += ((*fHitWeightsNonBending)(hitNumber1, hitNumber2) + (*fHitWeightsNonBending)(hitNumber2, hitNumber1)) * dX[hitNumber1] * dX[hitNumber2] +
661 ((*fHitWeightsBending)(hitNumber1, hitNumber2) + (*fHitWeightsBending)(hitNumber2, hitNumber1)) * dY[hitNumber1] * dY[hitNumber2];
663 chi2 += ((*fHitWeightsNonBending)(hitNumber1, hitNumber1) * dX[hitNumber1] * dX[hitNumber1]) +
664 ((*fHitWeightsBending)(hitNumber1, hitNumber1) * dY[hitNumber1] * dY[hitNumber1]);
671 AliMUONHitForRec *hitForRec;
673 for (Int_t hitNumber = 0; hitNumber < fNTrackHits ; hitNumber++) {
674 trackParamAtHit = (AliMUONTrackParam*) fTrackParamAtHit->UncheckedAt(hitNumber);
675 hitForRec = trackParamAtHit->GetHitForRecPtr();
676 dX = hitForRec->GetNonBendingCoor() - trackParamAtHit->GetNonBendingCoor();
677 dY = hitForRec->GetBendingCoor() - trackParamAtHit->GetBendingCoor();
678 chi2 += dX * dX / hitForRec->GetNonBendingReso2() + dY * dY / hitForRec->GetBendingReso2();
687 //__________________________________________________________________________
688 Bool_t AliMUONTrack::ComputeHitWeights(TMatrixD* mcsCovariances)
690 /// Compute the weight matrices of the attached hits, in non bending and bending direction,
691 /// accounting for multiple scattering correlations and hits resolution
692 /// - Use the provided MCS covariance matrix if any (otherwise build it temporarily)
693 /// - Assume that track parameters at each hit are corrects
694 /// - Return kFALSE if computation failed
697 if (!fHitWeightsNonBending) fHitWeightsNonBending = new TMatrixD(fNTrackHits,fNTrackHits);
698 if (!fHitWeightsBending) fHitWeightsBending = new TMatrixD(fNTrackHits,fNTrackHits);
700 // Check hits (if the first one exist, assume that the other ones exit too!)
701 if (!((AliMUONTrackParam*) fTrackParamAtHit->First())->GetHitForRecPtr()) {
702 AliWarning("hit is missing");
703 fHitWeightsNonBending->ResizeTo(0,0);
704 fHitWeightsBending->ResizeTo(0,0);
708 // Compute weights matrices
709 if (!ComputeHitWeights(*fHitWeightsNonBending, *fHitWeightsBending, mcsCovariances)) return kFALSE;
715 //__________________________________________________________________________
716 Bool_t AliMUONTrack::ComputeHitWeights(TMatrixD& hitWeightsNB, TMatrixD& hitWeightsB, TMatrixD* mcsCovariances, AliMUONHitForRec* discardedHit) const
718 /// Compute the weight matrices, in non bending and bending direction,
719 /// of the other attached hits assuming the discarded one does not exist
720 /// accounting for multiple scattering correlations and hits resolution
721 /// - Use the provided MCS covariance matrix if any (otherwise build it temporarily)
722 /// - Return kFALSE if computation failed
724 // Check MCS covariance matrix and recompute it if need
725 Bool_t deleteMCSCov = kFALSE;
726 if (!mcsCovariances) {
728 // build MCS covariance matrix
729 mcsCovariances = new TMatrixD(AliMUONConstants::NTrackingCh(),AliMUONConstants::NTrackingCh());
730 deleteMCSCov = kTRUE;
731 ComputeMCSCovariances(*mcsCovariances);
735 // check MCS covariance matrix size
736 if (mcsCovariances->GetNrows() != AliMUONConstants::NTrackingCh() || mcsCovariances->GetNcols() != AliMUONConstants::NTrackingCh()) {
737 ComputeMCSCovariances(*mcsCovariances);
742 // Resize the weights matrices; alocate memory
744 hitWeightsNB.ResizeTo(fNTrackHits-1,fNTrackHits-1);
745 hitWeightsB.ResizeTo(fNTrackHits-1,fNTrackHits-1);
747 hitWeightsNB.ResizeTo(fNTrackHits,fNTrackHits);
748 hitWeightsB.ResizeTo(fNTrackHits,fNTrackHits);
752 AliMUONHitForRec *hitForRec1, *hitForRec2;
753 Int_t chamber1, chamber2, currentHitNumber1, currentHitNumber2;
755 // Compute the covariance matrices
756 currentHitNumber1 = 0;
757 for (Int_t hitNumber1 = 0; hitNumber1 < fNTrackHits; hitNumber1++) {
758 hitForRec1 = ((AliMUONTrackParam*) fTrackParamAtHit->UncheckedAt(hitNumber1))->GetHitForRecPtr();
760 if (hitForRec1 == discardedHit) continue;
762 chamber1 = hitForRec1->GetChamberNumber();
764 // Loop over next hits
765 currentHitNumber2 = currentHitNumber1;
766 for (Int_t hitNumber2 = hitNumber1; hitNumber2 < fNTrackHits; hitNumber2++) {
767 hitForRec2 = ((AliMUONTrackParam*) fTrackParamAtHit->UncheckedAt(hitNumber2))->GetHitForRecPtr();
769 if (hitForRec2 == discardedHit) continue;
771 chamber2 = hitForRec2->GetChamberNumber();
773 // Fill with MCS covariances
774 hitWeightsNB(currentHitNumber1, currentHitNumber2) = (*mcsCovariances)(chamber1,chamber2);
776 // Equal contribution from multiple scattering in non bending and bending directions
777 hitWeightsB(currentHitNumber1, currentHitNumber2) = hitWeightsNB(currentHitNumber1, currentHitNumber2);
779 // Add contribution from hit resolution to diagonal element and symmetrize the matrix
780 if (currentHitNumber1 == currentHitNumber2) {
782 // In non bending plane
783 hitWeightsNB(currentHitNumber1, currentHitNumber1) += hitForRec1->GetNonBendingReso2();
785 hitWeightsB(currentHitNumber1, currentHitNumber1) += hitForRec1->GetBendingReso2();
789 // In non bending plane
790 hitWeightsNB(currentHitNumber2, currentHitNumber1) = hitWeightsNB(currentHitNumber1, currentHitNumber2);
792 hitWeightsB(currentHitNumber2, currentHitNumber1) = hitWeightsB(currentHitNumber1, currentHitNumber2);
802 // Inversion of covariance matrices to get the weights
803 if (hitWeightsNB.Determinant() != 0 && hitWeightsB.Determinant() != 0) {
804 hitWeightsNB.Invert();
805 hitWeightsB.Invert();
807 AliWarning(" Determinant = 0");
808 hitWeightsNB.ResizeTo(0,0);
809 hitWeightsB.ResizeTo(0,0);
810 if(deleteMCSCov) delete mcsCovariances;
814 if(deleteMCSCov) delete mcsCovariances;
820 //__________________________________________________________________________
821 void AliMUONTrack::ComputeMCSCovariances(TMatrixD& mcsCovariances) const
823 /// Compute the multiple scattering covariance matrix
824 /// - Assume that track parameters at each hit are corrects
825 /// - Return kFALSE if computation failed
827 // Make sure the size of the covariance matrix is correct
828 Int_t nChambers = AliMUONConstants::NTrackingCh();
829 mcsCovariances.ResizeTo(nChambers,nChambers);
831 // check for too many track hits
832 if (fNTrackHits > nChambers) {
833 AliWarning("more than 1 hit per chamber!!");
834 mcsCovariances.Zero();
839 AliMUONTrackParam* trackParamAtHit;
840 AliMUONHitForRec *hitForRec;
841 AliMUONTrackParam extrapTrackParam;
842 Int_t currentChamber, expectedChamber;
843 Double_t *mcsAngle2 = new Double_t[nChambers];
844 Double_t *zMCS = new Double_t[nChambers];
846 // Compute multiple scattering dispersion angle at each chamber
847 // and save the z position where it is calculated
850 for (Int_t hitNumber = 0; hitNumber < fNTrackHits; hitNumber++) {
851 trackParamAtHit = (AliMUONTrackParam*) fTrackParamAtHit->UncheckedAt(hitNumber);
852 hitForRec = trackParamAtHit->GetHitForRecPtr();
854 // look for missing chambers if any
855 currentChamber = hitForRec->GetChamberNumber();
856 while (currentChamber > expectedChamber) {
858 // Save the z position where MCS dispersion is calculated
859 zMCS[expectedChamber] = AliMUONConstants::DefaultChamberZ(expectedChamber);
861 // Do not take into account MCS in chambers prior the first hit
864 // Get track parameters at missing chamber z
865 extrapTrackParam = *trackParamAtHit;
866 AliMUONTrackExtrap::ExtrapToZ(&extrapTrackParam, zMCS[expectedChamber]);
868 // Save multiple scattering dispersion angle in missing chamber
869 mcsAngle2[expectedChamber] = AliMUONTrackExtrap::GetMCSAngle2(extrapTrackParam,AliMUONConstants::ChamberThicknessInX0(),1.);
871 } else mcsAngle2[expectedChamber] = 0.;
876 // Save z position where MCS dispersion is calculated
877 zMCS[currentChamber] = trackParamAtHit->GetZ();
879 // Save multiple scattering dispersion angle in current chamber
880 mcsAngle2[currentChamber] = AliMUONTrackExtrap::GetMCSAngle2(*trackParamAtHit,AliMUONConstants::ChamberThicknessInX0(),1.);
885 // complete array of z if last hit is on the last but one chamber
886 if (currentChamber != nChambers-1) zMCS[nChambers-1] = AliMUONConstants::DefaultChamberZ(nChambers-1);
889 // Compute the covariance matrix
890 for (Int_t chamber1 = 0; chamber1 < nChambers; chamber1++) {
892 for (Int_t chamber2 = chamber1; chamber2 < nChambers; chamber2++) {
894 // Initialization to 0 (diagonal plus upper triangular part)
895 mcsCovariances(chamber1, chamber2) = 0.;
897 // Compute contribution from multiple scattering in upstream chambers
898 for (currentChamber = 0; currentChamber < chamber1; currentChamber++) {
899 mcsCovariances(chamber1, chamber2) += (zMCS[chamber1] - zMCS[currentChamber]) * (zMCS[chamber2] - zMCS[currentChamber]) * mcsAngle2[currentChamber];
902 // Symetrize the matrix
903 mcsCovariances(chamber2, chamber1) = mcsCovariances(chamber1, chamber2);
913 //__________________________________________________________________________
914 Int_t AliMUONTrack::HitsInCommon(AliMUONTrack* track) const
916 /// Returns the number of hits in common between the current track ("this")
917 /// and the track pointed to by "track".
918 Int_t hitsInCommon = 0;
919 AliMUONTrackParam *trackParamAtHit1, *trackParamAtHit2;
920 // Loop over hits of first track
921 trackParamAtHit1 = (AliMUONTrackParam*) this->fTrackParamAtHit->First();
922 while (trackParamAtHit1) {
923 // Loop over hits of second track
924 trackParamAtHit2 = (AliMUONTrackParam*) track->fTrackParamAtHit->First();
925 while (trackParamAtHit2) {
926 // Increment "hitsInCommon" if both TrackParamAtHits point to the same HitForRec
927 if ((trackParamAtHit1->GetHitForRecPtr()) == (trackParamAtHit2->GetHitForRecPtr())) {
931 trackParamAtHit2 = (AliMUONTrackParam*) track->fTrackParamAtHit->After(trackParamAtHit2);
932 } // trackParamAtHit2
933 trackParamAtHit1 = (AliMUONTrackParam*) this->fTrackParamAtHit->After(trackParamAtHit1);
934 } // trackParamAtHit1
938 //__________________________________________________________________________
939 Double_t AliMUONTrack::GetNormalizedChi2() const
941 /// return the chi2 value divided by the number of degrees of freedom (or 1.e10 if ndf < 0)
943 Double_t numberOfDegFree = (2. * fNTrackHits - 5.);
944 if (numberOfDegFree > 0.) return fGlobalChi2 / numberOfDegFree;
948 //__________________________________________________________________________
949 Bool_t* AliMUONTrack::CompatibleTrack(AliMUONTrack * track, Double_t sigma2Cut) const
951 /// Return kTRUE/kFALSE for each chamber if hit is compatible or not
952 TClonesArray *hitArray, *thisHitArray;
953 AliMUONHitForRec *hit, *thisHit;
956 Float_t deltaZMax = 1.; // 1 cm
958 Bool_t *nCompHit = new Bool_t[AliMUONConstants::NTrackingCh()];
960 for ( Int_t ch = 0; ch < AliMUONConstants::NTrackingCh(); ch++) {
961 nCompHit[ch] = kFALSE;
964 thisHitArray = this->GetHitForRecAtHit();
966 hitArray = track->GetHitForRecAtHit();
968 for (Int_t iHthis = 0; iHthis < thisHitArray->GetEntriesFast(); iHthis++) {
969 thisHit = (AliMUONHitForRec*) thisHitArray->At(iHthis);
970 chamberNumber = thisHit->GetChamberNumber();
971 if (chamberNumber < 0 || chamberNumber > AliMUONConstants::NTrackingCh()) continue;
972 nCompHit[chamberNumber] = kFALSE;
973 for (Int_t iH = 0; iH < hitArray->GetEntriesFast(); iH++) {
974 hit = (AliMUONHitForRec*) hitArray->At(iH);
975 deltaZ = TMath::Abs(thisHit->GetZ() - hit->GetZ());
976 chi2 = thisHit->NormalizedChi2WithHitForRec(hit,sigma2Cut); // set cut to 4 sigmas
977 if (chi2 < 3. && deltaZ < deltaZMax) {
978 nCompHit[chamberNumber] = kTRUE;
987 //__________________________________________________________________________
988 void AliMUONTrack::RecursiveDump(void) const
990 /// Recursive dump of AliMUONTrack, i.e. with dump of TrackParamAtHit's and attached HitForRec's
991 AliMUONTrackParam *trackParamAtHit;
992 AliMUONHitForRec *hitForRec;
993 cout << "Recursive dump of Track: " << this << endl;
996 for (Int_t trackHitIndex = 0; trackHitIndex < fNTrackHits; trackHitIndex++) {
997 trackParamAtHit = (AliMUONTrackParam*) ((*fTrackParamAtHit)[trackHitIndex]);
999 cout << "TrackParamAtHit: " << trackParamAtHit << " (index: " << trackHitIndex << ")" << endl;
1000 trackParamAtHit->Dump();
1001 hitForRec = trackParamAtHit->GetHitForRecPtr();
1003 cout << "HitForRec: " << hitForRec << endl;
1009 //_____________________________________________-
1010 void AliMUONTrack::Print(Option_t*) const
1012 /// Printing Track information
1014 cout << "<AliMUONTrack> No.Clusters=" << setw(2) << GetNTrackHits() <<
1015 ", Match2Trig=" << setw(1) << GetMatchTrigger() <<
1016 ", LoTrgNum=" << setw(3) << GetLoTrgNum() <<
1017 ", Chi2-tracking-trigger=" << setw(8) << setprecision(5) << GetChi2MatchTrigger();
1018 cout << Form(" HitTriggerPattern %x",fHitsPatternInTrigCh) << endl;
1019 GetTrackParamAtHit()->First()->Print("FULL");
1022 //__________________________________________________________________________
1023 void AliMUONTrack::SetLocalTrigger(Int_t loCirc, Int_t loStripX, Int_t loStripY, Int_t loDev, Int_t loLpt, Int_t loHpt)
1025 /// pack the local trigger information and store
1027 if (loCirc < 0 || loCirc > 233) return;
1030 fLocalTrigger += loCirc;
1031 fLocalTrigger += loStripX << 8;
1032 fLocalTrigger += loStripY << 13;
1033 fLocalTrigger += loDev << 17;
1034 fLocalTrigger += loLpt << 22;
1035 fLocalTrigger += loHpt << 24;