AliRoot Core  edcc906 (edcc906)
AliMUONTrackReconstructorK.cxx
Go to the documentation of this file.
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 
16 /* $Id$ */
17 
18 //-----------------------------------------------------------------------------
29 //-----------------------------------------------------------------------------
30 
32 
33 #include "AliMUONConstants.h"
34 #include "AliMUONVCluster.h"
35 #include "AliMUONVClusterServer.h"
36 #include "AliMUONVClusterStore.h"
37 #include "AliMUONTrack.h"
38 #include "AliMUONTrackParam.h"
39 #include "AliMUONTrackExtrap.h"
40 #include "AliMUONRecoParam.h"
42 
43 #include "AliMpArea.h"
44 
45 #include "AliLog.h"
46 
47 #include <Riostream.h>
48 #include <TMath.h>
49 #include <TMatrixD.h>
50 #include <TClonesArray.h>
51 
52 using std::endl;
53 using std::cout;
55 ClassImp(AliMUONTrackReconstructorK) // Class implementation in ROOT context
57 
58  //__________________________________________________________________________
60  const AliMUONGeometryTransformer* transformer)
61  : AliMUONVTrackReconstructor(recoParam, clusterServer, transformer)
62 {
64 }
65 
66  //__________________________________________________________________________
68 {
70 }
71 
72  //__________________________________________________________________________
74 {
79 
80  TClonesArray *segments;
81  AliMUONObjectPair *segment;
83  Int_t iCandidate = 0;
84  Bool_t clusterFound;
85 
86  AliDebug(1,"Enter MakeTrackCandidates");
87 
88  // Unless we're doing combined tracking, we'll clusterize all stations at once
89  Int_t firstChamber(0);
90  Int_t lastChamber(9);
91 
92  if (GetRecoParam()->CombineClusterTrackReco()) {
93  // ... Here's the exception : ask the clustering to reconstruct
94  // clusters *only* in station 4 and 5 for combined tracking
95  firstChamber = 6;
96  }
97 
98  for (Int_t i = firstChamber; i <= lastChamber; ++i )
99  {
100  if (fClusterServer && GetRecoParam()->UseChamber(i)) fClusterServer->Clusterize(i, clusterStore, AliMpArea(), GetRecoParam());
101  }
102 
103  // Loop over stations(1..) 5 and 4 and make track candidates
104  for (Int_t istat=4; istat>=3; istat--) {
105 
106  // Make segments in the station
107  segments = MakeSegmentsBetweenChambers(clusterStore, 2*istat, 2*istat+1);
108 
109  // Loop over segments
110  for (Int_t iSegment=0; iSegment<segments->GetEntriesFast(); iSegment++) {
111  AliDebug(1,Form("Making primary candidate(1..) %d",++iCandidate));
112  segment = (AliMUONObjectPair*) segments->UncheckedAt(iSegment);
113 
114  // Transform segments to tracks and put them at the end of fRecTracksPtr
115  track = new ((*fRecTracksPtr)[fRecTracksPtr->GetLast()+1]) AliMUONTrack(segment,GetRecoParam()->GetBendingVertexDispersion());
116  fNRecTracks++;
117 
118  // Look for compatible cluster(s) in the other station
119  if (GetRecoParam()->MakeTrackCandidatesFast()) clusterFound = FollowLinearTrackInStation(*track, clusterStore, 7-istat);
120  else clusterFound = FollowTrackInStation(*track, clusterStore, 7-istat);
121 
122  // Remove track if no cluster found on a requested station
123  // or abort tracking if there are too many candidates
124  if (GetRecoParam()->RequestStation(7-istat)) {
125  if (!clusterFound) {
126  fRecTracksPtr->Remove(track);
127  fNRecTracks--;
128  } else if (fNRecTracks > GetRecoParam()->GetMaxTrackCandidates()) {
129  AliError(Form("Too many track candidates (%d tracks). Stop tracking.", fNRecTracks));
130  return kFALSE;
131  }
132  } else {
133  if ((fNRecTracks + segments->GetEntriesFast() - iSegment - 1) > GetRecoParam()->GetMaxTrackCandidates()) {
134  AliError(Form("Too many track candidates (%d tracks). Stop tracking.", fNRecTracks + segments->GetEntriesFast() - iSegment - 1));
135  return kFALSE;
136  }
137  }
138 
139  }
140 
141  }
142 
143  AliDebug(1,Form("Number of candidates before cleaning = %d",fNRecTracks));
144 
145  // Keep all different tracks if required
146  if (GetRecoParam()->TrackAllTracks()) RemoveIdenticalTracks();
147 
148  // Retrace tracks using Kalman filter and select them if needed
149  Int_t nCurrentTracks = fRecTracksPtr->GetLast()+1;
150  for (Int_t iRecTrack = 0; iRecTrack < nCurrentTracks; iRecTrack++) {
151  track = (AliMUONTrack*) fRecTracksPtr->UncheckedAt(iRecTrack);
152 
153  // skip empty slots
154  if(!track) continue;
155 
156  // retrace tracks using Kalman filter and remove the ones for which extrap failed or that are out of limits
157  if (!RetraceTrack(*track,kTRUE) || !IsAcceptable(*((AliMUONTrackParam*)track->GetTrackParamAtCluster()->First()))) {
158  fRecTracksPtr->Remove(track);
159  fNRecTracks--;
160  }
161 
162  }
163 
164  // Keep only the best tracks if required
165  if (!GetRecoParam()->TrackAllTracks()) RemoveDoubleTracks();
166  else fRecTracksPtr->Compress();
167 
168  AliDebug(1,Form("Number of good candidates = %d",fNRecTracks));
169 
170  return kTRUE;
171 
172 }
173 
174  //__________________________________________________________________________
176 {
182 
183  TClonesArray *segments;
184  AliMUONObjectPair *segment;
186  Int_t iCandidate = 0, iCurrentTrack, nCurrentTracks;
187  Int_t initialNRecTracks = fNRecTracks;
188  Bool_t clusterFound;
189 
190  AliDebug(1,"Enter MakeMoreTrackCandidates");
191 
192  // Double loop over chambers in stations(1..) 4 and 5 to make track candidates
193  for (Int_t ich1 = 6; ich1 <= 7; ich1++) {
194  for (Int_t ich2 = 8; ich2 <= 9; ich2++) {
195 
196  // Make segments between ch1 and ch2
197  segments = MakeSegmentsBetweenChambers(clusterStore, ich1, ich2);
198 
200  RemoveUsedSegments(*segments);
201 
202  // Loop over segments
203  for (Int_t iSegment=0; iSegment<segments->GetEntriesFast(); iSegment++) {
204  AliDebug(1,Form("Making primary candidate(1..) %d",++iCandidate));
205  segment = (AliMUONObjectPair*) segments->UncheckedAt(iSegment);
206 
207  // Transform segments to tracks and put them at the end of fRecTracksPtr
208  iCurrentTrack = fRecTracksPtr->GetLast()+1;
209  track = new ((*fRecTracksPtr)[iCurrentTrack]) AliMUONTrack(segment,GetRecoParam()->GetBendingVertexDispersion());
210  fNRecTracks++;
211 
212  // Look for compatible cluster(s) in the second chamber of station 5
213  clusterFound = FollowLinearTrackInChamber(*track, clusterStore, 17-ich2);
214 
215  // skip the original track in case it has been removed
216  if (GetRecoParam()->TrackAllTracks() && clusterFound) iCurrentTrack++;
217 
218  // loop over every new tracks
219  nCurrentTracks = fRecTracksPtr->GetLast()+1;
220  while (iCurrentTrack < nCurrentTracks) {
221  track = (AliMUONTrack*) fRecTracksPtr->UncheckedAt(iCurrentTrack);
222 
223  // Look for compatible cluster(s) in the second chamber of station 4
224  FollowLinearTrackInChamber(*track, clusterStore, 13-ich1);
225 
226  iCurrentTrack++;
227  }
228 
229  // abort tracking if there are too many candidates
230  if ((fNRecTracks + segments->GetEntriesFast() - iSegment - 1) > GetRecoParam()->GetMaxTrackCandidates()) {
231  AliError(Form("Too many track candidates (%d tracks). Stop tracking.", fNRecTracks + segments->GetEntriesFast() - iSegment - 1));
232  return kFALSE;
233  }
234 
235  }
236 
237  }
238  }
239 
240  AliDebug(1,Form("Number of candidates before cleaning = %d",fNRecTracks));
241 
242  // Retrace tracks using Kalman filter (also compute track chi2) and select them
243  nCurrentTracks = fRecTracksPtr->GetLast()+1;
244  for (Int_t iRecTrack = initialNRecTracks; iRecTrack < nCurrentTracks; iRecTrack++) {
245  track = (AliMUONTrack*) fRecTracksPtr->UncheckedAt(iRecTrack);
246 
247  // skip empty slots
248  if(!track) continue;
249 
250  // retrace tracks using Kalman filter and remove the ones for which extrap failed or that are out of limits
251  if (!RetraceTrack(*track,kTRUE) || !IsAcceptable(*((AliMUONTrackParam*)track->GetTrackParamAtCluster()->First()))) {
252  fRecTracksPtr->Remove(track);
253  fNRecTracks--;
254  }
255 
256  }
257 
258  // Keep only the best tracks if required
259  if (!GetRecoParam()->TrackAllTracks()) RemoveDoubleTracks();
260  else fRecTracksPtr->Compress();
261 
262  AliDebug(1,Form("Number of good candidates = %d",fNRecTracks));
263 
264  return kTRUE;
265 
266 }
267 
268  //__________________________________________________________________________
269 Bool_t AliMUONTrackReconstructorK::RetraceTrack(AliMUONTrack &trackCandidate, Bool_t resetSeed)
270 {
273  AliDebug(1,"Enter RetraceTrack");
274 
275  AliMUONTrackParam* lastTrackParam = (AliMUONTrackParam*) trackCandidate.GetTrackParamAtCluster()->Last();
276 
277  // Reset the "seed" (= track parameters and their covariances at last cluster) if required
278  if (resetSeed) {
279 
280  // parameters at last cluster
281  AliMUONVCluster* cluster2 = lastTrackParam->GetClusterPtr();
282  Double_t x2 = cluster2->GetX();
283  Double_t y2 = cluster2->GetY();
284  Double_t z2 = cluster2->GetZ();
285 
286  // parameters at last but one cluster
287  AliMUONTrackParam* previousTrackParam = (AliMUONTrackParam*) trackCandidate.GetTrackParamAtCluster()->Before(lastTrackParam);
288  AliMUONVCluster* cluster1 = previousTrackParam->GetClusterPtr();
289  // make sure it is on the previous chamber (can have 2 clusters in the same chamber after "ComplementTrack")
290  if (cluster2->GetChamberId() == cluster1->GetChamberId()) {
291  previousTrackParam = (AliMUONTrackParam*) trackCandidate.GetTrackParamAtCluster()->Before(previousTrackParam);
292  cluster1 = previousTrackParam->GetClusterPtr();
293  }
294  Double_t x1 = cluster1->GetX();
295  Double_t y1 = cluster1->GetY();
296  Double_t z1 = cluster1->GetZ();
297 
298  // reset track parameters
299  Double_t dZ = z1 - z2;
300  lastTrackParam->SetNonBendingCoor(x2);
301  lastTrackParam->SetBendingCoor(y2);
302  lastTrackParam->SetZ(z2);
303  lastTrackParam->SetNonBendingSlope((x1 - x2) / dZ);
304  lastTrackParam->SetBendingSlope((y1 - y2) / dZ);
305  Double_t bendingImpact = y2 - z2 * lastTrackParam->GetBendingSlope();
306  Double_t inverseBendingMomentum = 1. / AliMUONTrackExtrap::GetBendingMomentumFromImpactParam(bendingImpact);
307  lastTrackParam->SetInverseBendingMomentum(inverseBendingMomentum);
308 
309  // => Reset track parameter covariances at last cluster (as if the other clusters did not exist)
310  TMatrixD lastParamCov(5,5);
311  lastParamCov.Zero();
312  // Non bending plane
313  lastParamCov(0,0) = cluster2->GetErrX2();
314  lastParamCov(0,1) = - cluster2->GetErrX2() / dZ;
315  lastParamCov(1,0) = lastParamCov(0,1);
316  lastParamCov(1,1) = ( 1000. * cluster1->GetErrX2() + cluster2->GetErrX2() ) / dZ / dZ;
317  // Bending plane
318  lastParamCov(2,2) = cluster2->GetErrY2();
319  lastParamCov(2,3) = - cluster2->GetErrY2() / dZ;
320  lastParamCov(3,2) = lastParamCov(2,3);
321  lastParamCov(3,3) = ( 1000. * cluster1->GetErrY2() + cluster2->GetErrY2() ) / dZ / dZ;
322  // Inverse bending momentum (vertex resolution + bending slope resolution + 10% error on dipole parameters+field)
324  lastParamCov(4,4) = ((GetRecoParam()->GetBendingVertexDispersion() *
326  (z1 * z1 * cluster2->GetErrY2() + z2 * z2 * 1000. * cluster1->GetErrY2()) / dZ / dZ) /
327  bendingImpact / bendingImpact + 0.1 * 0.1) * inverseBendingMomentum * inverseBendingMomentum;
328  lastParamCov(2,4) = z1 * cluster2->GetErrY2() * inverseBendingMomentum / bendingImpact / dZ;
329  lastParamCov(4,2) = lastParamCov(2,4);
330  lastParamCov(3,4) = - (z1 * cluster2->GetErrY2() + z2 * 1000. * cluster1->GetErrY2()) *
331  inverseBendingMomentum / bendingImpact / dZ / dZ;
332  lastParamCov(4,3) = lastParamCov(3,4);
333  } else lastParamCov(4,4) = inverseBendingMomentum*inverseBendingMomentum;
334  lastTrackParam->SetCovariances(lastParamCov);
335 
336  // Reset the track chi2
337  lastTrackParam->SetTrackChi2(0.);
338 
339  }
340 
341  // Redo the tracking
342  return RetracePartialTrack(trackCandidate, lastTrackParam);
343 
344 }
345 
346  //__________________________________________________________________________
347 Bool_t AliMUONTrackReconstructorK::RetracePartialTrack(AliMUONTrack &trackCandidate, const AliMUONTrackParam* startingTrackParam)
348 {
351  AliDebug(1,"Enter RetracePartialTrack");
352 
353  // Printout for debuging
354  if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
355  cout << "RetracePartialTrack: track chi2 before re-tracking: " << trackCandidate.GetGlobalChi2() << endl;
356  }
357 
358  // Reset the track chi2
359  trackCandidate.SetGlobalChi2(startingTrackParam->GetTrackChi2());
360 
361  // loop over attached clusters until the first one and recompute track parameters and covariances using kalman filter
362  Bool_t extrapStatus = kTRUE;
363  Int_t expectedChamber = startingTrackParam->GetClusterPtr()->GetChamberId() - 1;
364  Int_t currentChamber;
365  Double_t addChi2TrackAtCluster;
366  AliMUONTrackParam* trackParamAtCluster = (AliMUONTrackParam*) trackCandidate.GetTrackParamAtCluster()->Before(startingTrackParam);
367  while (trackParamAtCluster) {
368 
369  // reset track parameters and their covariances
370  trackParamAtCluster->SetParameters(startingTrackParam->GetParameters());
371  trackParamAtCluster->SetZ(startingTrackParam->GetZ());
372  trackParamAtCluster->SetCovariances(startingTrackParam->GetCovariances());
373 
374  // add MCS effect
375  AliMUONTrackExtrap::AddMCSEffect(trackParamAtCluster,AliMUONConstants::ChamberThicknessInX0(expectedChamber+1),-1.);
376 
377  // reset propagator for smoother
378  if (GetRecoParam()->UseSmoother()) trackParamAtCluster->ResetPropagator();
379 
380  // add MCS in missing chambers if any
381  currentChamber = trackParamAtCluster->GetClusterPtr()->GetChamberId();
382  while (currentChamber < expectedChamber) {
383  // extrapolation to the missing chamber (update the propagator)
384  if (!AliMUONTrackExtrap::ExtrapToZCov(trackParamAtCluster, AliMUONConstants::DefaultChamberZ(expectedChamber),
385  GetRecoParam()->UseSmoother())) extrapStatus = kFALSE;
386  // add MCS effect
387  AliMUONTrackExtrap::AddMCSEffect(trackParamAtCluster,AliMUONConstants::ChamberThicknessInX0(expectedChamber),-1.);
388  expectedChamber--;
389  }
390 
391  // extrapolation to the plane of the cluster attached to the current trackParamAtCluster (update the propagator)
392  if (!AliMUONTrackExtrap::ExtrapToZCov(trackParamAtCluster, trackParamAtCluster->GetClusterPtr()->GetZ(),
393  GetRecoParam()->UseSmoother())) extrapStatus = kFALSE;
394 
395  if (GetRecoParam()->UseSmoother()) {
396  // save extrapolated parameters for smoother
397  trackParamAtCluster->SetExtrapParameters(trackParamAtCluster->GetParameters());
398 
399  // save extrapolated covariance matrix for smoother
400  trackParamAtCluster->SetExtrapCovariances(trackParamAtCluster->GetCovariances());
401  }
402 
403  // Compute new track parameters using kalman filter
404  addChi2TrackAtCluster = RunKalmanFilter(*trackParamAtCluster);
405 
406  // Update the track chi2
407  trackCandidate.SetGlobalChi2(trackCandidate.GetGlobalChi2() + addChi2TrackAtCluster);
408  trackParamAtCluster->SetTrackChi2(trackCandidate.GetGlobalChi2());
409 
410  // prepare next step
411  expectedChamber = currentChamber - 1;
412  startingTrackParam = trackParamAtCluster;
413  trackParamAtCluster = (AliMUONTrackParam*) (trackCandidate.GetTrackParamAtCluster()->Before(startingTrackParam));
414  }
415 
416  // Printout for debuging
417  if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
418  cout << "RetracePartialTrack: track chi2 after re-tracking: " << trackCandidate.GetGlobalChi2() << endl;
419  }
420 
421  // set global chi2 to max value in case of problem during track extrapolation
422  if (!extrapStatus) trackCandidate.SetGlobalChi2(2.*AliMUONTrack::MaxChi2());
423  return extrapStatus;
424 
425 }
426 
427  //__________________________________________________________________________
429 {
431  AliDebug(1,"Enter FollowTracks");
432 
434  Int_t currentNRecTracks;
435 
436  for (Int_t station = 2; station >= 0; station--) {
437 
438  // Save the actual number of reconstructed track in case of
439  // tracks are added or suppressed during the tracking procedure
440  // !! Do not compress fRecTracksPtr until the end of the loop over tracks !!
441  currentNRecTracks = fNRecTracks;
442 
443  for (Int_t iRecTrack = 0; iRecTrack <currentNRecTracks; iRecTrack++) {
444  AliDebug(1,Form("FollowTracks: track candidate(1..) %d", iRecTrack+1));
445 
446  track = (AliMUONTrack*) fRecTracksPtr->UncheckedAt(iRecTrack);
447 
448  // Look for compatible cluster(s) in station(0..) "station"
449  if (!FollowTrackInStation(*track, clusterStore, station)) {
450 
451  // Try to recover track if required
452  if (GetRecoParam()->RecoverTracks()) {
453 
454  // work on a copy of the track if this station is not required
455  // to keep the case where no cluster is reconstructed as a possible candidate
456  if (!GetRecoParam()->RequestStation(station)) {
457  track = new ((*fRecTracksPtr)[fRecTracksPtr->GetLast()+1]) AliMUONTrack(*track);
458  fNRecTracks++;
459  }
460 
461  // try to recover
462  if (!RecoverTrack(*track, clusterStore, station)) {
463  // remove track if no cluster found
464  fRecTracksPtr->Remove(track);
465  fNRecTracks--;
466  }
467 
468  } else if (GetRecoParam()->RequestStation(station)) {
469  // remove track if no cluster found
470  fRecTracksPtr->Remove(track);
471  fNRecTracks--;
472  }
473 
474  }
475 
476  // abort tracking if there are too many candidates
477  if (GetRecoParam()->RequestStation(station)) {
478  if (fNRecTracks > GetRecoParam()->GetMaxTrackCandidates()) {
479  AliError(Form("Too many track candidates (%d tracks). Stop tracking.", fNRecTracks));
480  return kFALSE;
481  }
482  } else {
483  if ((fNRecTracks + currentNRecTracks - iRecTrack - 1) > GetRecoParam()->GetMaxTrackCandidates()) {
484  AliError(Form("Too many track candidates (%d tracks). Stop tracking.", fNRecTracks + currentNRecTracks - iRecTrack - 1));
485  return kFALSE;
486  }
487  }
488 
489  }
490 
491  fRecTracksPtr->Compress(); // this is essential before checking tracks
492 
493  AliDebug(1,Form("In stations(1..) %d: Number of candidates before cleaning = %d",station+1,fNRecTracks));
494 
495  // Keep only the best tracks if required
496  if (!GetRecoParam()->TrackAllTracks()) RemoveDoubleTracks();
497 
498  AliDebug(1,Form("In stations(1..) %d: Number of good candidates = %d",station+1,fNRecTracks));
499 
500  }
501 
502  return kTRUE;
503 
504 }
505 
506  //__________________________________________________________________________
507 Bool_t AliMUONTrackReconstructorK::FollowTrackInChamber(AliMUONTrack &trackCandidate, AliMUONVClusterStore& clusterStore, Int_t nextChamber)
508 {
516  AliDebug(1,Form("Enter FollowTrackInChamber(1..) %d", nextChamber+1));
517 
518  Double_t chi2OfCluster;
519  Double_t maxChi2OfCluster = 2. * GetRecoParam()->GetSigmaCutForTracking() *
520  GetRecoParam()->GetSigmaCutForTracking(); // 2 because 2 quantities in chi2
521  Double_t addChi2TrackAtCluster;
522  Double_t bestAddChi2TrackAtCluster = AliMUONTrack::MaxChi2();
523  Bool_t foundOneCluster = kFALSE;
524  AliMUONTrack *newTrack = 0x0;
525  AliMUONVCluster *cluster;
526  AliMUONTrackParam extrapTrackParamAtCh;
527  AliMUONTrackParam extrapTrackParamAtCluster;
528  AliMUONTrackParam bestTrackParamAtCluster;
529 
530  // Get track parameters according to the propagation direction
531  if (nextChamber > 7) extrapTrackParamAtCh = *(AliMUONTrackParam*)trackCandidate.GetTrackParamAtCluster()->Last();
532  else extrapTrackParamAtCh = *(AliMUONTrackParam*)trackCandidate.GetTrackParamAtCluster()->First();
533 
534  // Printout for debuging
535  if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 2) || (AliLog::GetGlobalDebugLevel() >= 2)) {
536  cout<<endl<<"Track parameters and covariances at first cluster:"<<endl;
537  extrapTrackParamAtCh.GetParameters().Print();
538  extrapTrackParamAtCh.GetCovariances().Print();
539  }
540 
541  // Add MCS effect
542  Int_t currentChamber = extrapTrackParamAtCh.GetClusterPtr()->GetChamberId();
543  AliMUONTrackExtrap::AddMCSEffect(&extrapTrackParamAtCh,AliMUONConstants::ChamberThicknessInX0(currentChamber),-1.);
544 
545  // reset propagator for smoother
546  if (GetRecoParam()->UseSmoother()) extrapTrackParamAtCh.ResetPropagator();
547 
548  // Add MCS in the missing chamber(s) if any
549  while (currentChamber > nextChamber + 1) {
550  // extrapolation to the missing chamber
551  currentChamber--;
552  if (!AliMUONTrackExtrap::ExtrapToZCov(&extrapTrackParamAtCh, AliMUONConstants::DefaultChamberZ(currentChamber),
553  GetRecoParam()->UseSmoother())) return kFALSE;
554  // add MCS effect
555  AliMUONTrackExtrap::AddMCSEffect(&extrapTrackParamAtCh,AliMUONConstants::ChamberThicknessInX0(currentChamber),-1.);
556  }
557 
558  //Extrapolate trackCandidate to chamber
559  if (!AliMUONTrackExtrap::ExtrapToZCov(&extrapTrackParamAtCh, AliMUONConstants::DefaultChamberZ(nextChamber),
560  GetRecoParam()->UseSmoother())) return kFALSE;
561 
562  // Printout for debuging
563  if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 2) || (AliLog::GetGlobalDebugLevel() >= 2)) {
564  cout<<endl<<"Track parameters and covariances at first cluster extrapolated to z = "<<AliMUONConstants::DefaultChamberZ(nextChamber)<<":"<<endl;
565  extrapTrackParamAtCh.GetParameters().Print();
566  extrapTrackParamAtCh.GetCovariances().Print();
567  }
568 
569  // Printout for debuging
570  if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
571  cout << "FollowTrackInChamber: look for clusters in chamber(1..): " << nextChamber+1 << endl;
572  }
573 
574  // Ask the clustering to reconstruct new clusters around the track position in the current chamber
575  // except for station 4 and 5 that are already entirely clusterized
576  if (GetRecoParam()->CombineClusterTrackReco()) {
577  if (nextChamber < 6) AskForNewClustersInChamber(extrapTrackParamAtCh, clusterStore, nextChamber);
578  }
579 
580  // Create iterators to loop over clusters in both chambers
581  TIter next(clusterStore.CreateChamberIterator(nextChamber,nextChamber));
582 
583  // look for candidates in chamber
584  while ( ( cluster = static_cast<AliMUONVCluster*>(next()) ) ) {
585 
586  // try to add the current cluster fast
587  if (!TryOneClusterFast(extrapTrackParamAtCh, cluster)) continue;
588 
589  // try to add the current cluster accuratly
590  chi2OfCluster = TryOneCluster(extrapTrackParamAtCh, cluster, extrapTrackParamAtCluster,
591  GetRecoParam()->UseSmoother());
592 
593  // if good chi2 then consider to add cluster
594  if (chi2OfCluster < maxChi2OfCluster) {
595 
596  if (GetRecoParam()->UseSmoother()) {
597  // save extrapolated parameters for smoother
598  extrapTrackParamAtCluster.SetExtrapParameters(extrapTrackParamAtCluster.GetParameters());
599 
600  // save extrapolated covariance matrix for smoother
601  extrapTrackParamAtCluster.SetExtrapCovariances(extrapTrackParamAtCluster.GetCovariances());
602  }
603 
604  // Compute new track parameters including new cluster using kalman filter
605  addChi2TrackAtCluster = RunKalmanFilter(extrapTrackParamAtCluster);
606 
607  // skip track out of limits
608  if (!IsAcceptable(extrapTrackParamAtCluster)) continue;
609 
610  // remember a cluster was found
611  foundOneCluster = kTRUE;
612 
613  // Printout for debuging
614  if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
615  cout << "FollowTrackInChamber: found one cluster in chamber(1..): " << nextChamber+1
616  << " (Chi2 = " << chi2OfCluster << ")" << endl;
617  cluster->Print();
618  }
619 
620  if (GetRecoParam()->TrackAllTracks()) {
621  // copy trackCandidate into a new track put at the end of fRecTracksPtr and add the new cluster
622  newTrack = new ((*fRecTracksPtr)[fRecTracksPtr->GetLast()+1]) AliMUONTrack(trackCandidate);
623  UpdateTrack(*newTrack,extrapTrackParamAtCluster,addChi2TrackAtCluster);
624  fNRecTracks++;
625 
626  // Printout for debuging
627  if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
628  cout << "FollowTrackInChamber: added one cluster in chamber(1..): " << nextChamber+1 << endl;
629  if (AliLog::GetGlobalDebugLevel() >= 3) newTrack->RecursiveDump();
630  }
631 
632  } else if (addChi2TrackAtCluster < bestAddChi2TrackAtCluster) {
633  // keep track of the best cluster
634  bestAddChi2TrackAtCluster = addChi2TrackAtCluster;
635  bestTrackParamAtCluster = extrapTrackParamAtCluster;
636  }
637 
638  }
639 
640  }
641 
642  // fill out the best track if required else clean up the fRecTracksPtr array
643  if (!GetRecoParam()->TrackAllTracks()) {
644  if (foundOneCluster) {
645  UpdateTrack(trackCandidate,bestTrackParamAtCluster,bestAddChi2TrackAtCluster);
646 
647  // Printout for debuging
648  if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
649  cout << "FollowTrackInChamber: added the best cluster in chamber(1..): " << bestTrackParamAtCluster.GetClusterPtr()->GetChamberId()+1 << endl;
650  if (AliLog::GetGlobalDebugLevel() >= 3) trackCandidate.RecursiveDump();
651  }
652 
653  } else return kFALSE;
654 
655  } else if (foundOneCluster) {
656 
657  // remove obsolete track
658  fRecTracksPtr->Remove(&trackCandidate);
659  fNRecTracks--;
660 
661  } else return kFALSE;
662 
663  return kTRUE;
664 
665 }
666 
667  //__________________________________________________________________________
668 Bool_t AliMUONTrackReconstructorK::FollowTrackInStation(AliMUONTrack &trackCandidate, AliMUONVClusterStore& clusterStore, Int_t nextStation)
669 {
677  AliDebug(1,Form("Enter FollowTrackInStation(1..) %d", nextStation+1));
678 
679  // Order the chamber according to the propagation direction (tracking starts with chamber 2):
680  // - nextStation == station(1...) 5 => forward propagation
681  // - nextStation < station(1...) 5 => backward propagation
682  Int_t ch1, ch2;
683  if (nextStation==4) {
684  ch1 = 2*nextStation+1;
685  ch2 = 2*nextStation;
686  } else {
687  ch1 = 2*nextStation;
688  ch2 = 2*nextStation+1;
689  }
690 
691  Double_t chi2OfCluster;
692  Double_t maxChi2OfCluster = 2. * GetRecoParam()->GetSigmaCutForTracking() *
693  GetRecoParam()->GetSigmaCutForTracking(); // 2 because 2 quantities in chi2
694  Double_t addChi2TrackAtCluster1;
695  Double_t addChi2TrackAtCluster2;
696  Double_t bestAddChi2TrackAtCluster1 = AliMUONTrack::MaxChi2();
697  Double_t bestAddChi2TrackAtCluster2 = AliMUONTrack::MaxChi2();
698  Bool_t foundOneCluster = kFALSE;
699  Bool_t foundTwoClusters = kFALSE;
700  AliMUONTrack *newTrack = 0x0;
701  AliMUONVCluster *clusterCh1, *clusterCh2;
702  AliMUONTrackParam extrapTrackParam;
703  AliMUONTrackParam extrapTrackParamAtCh;
704  AliMUONTrackParam extrapTrackParamAtCluster1;
705  AliMUONTrackParam extrapTrackParamAtCluster2;
706  AliMUONTrackParam bestTrackParamAtCluster1;
707  AliMUONTrackParam bestTrackParamAtCluster2;
708 
709  // Get track parameters according to the propagation direction
710  if (nextStation==4) extrapTrackParamAtCh = *(AliMUONTrackParam*)trackCandidate.GetTrackParamAtCluster()->Last();
711  else extrapTrackParamAtCh = *(AliMUONTrackParam*)trackCandidate.GetTrackParamAtCluster()->First();
712 
713  // Printout for debuging
714  if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 2) || (AliLog::GetGlobalDebugLevel() >= 2)) {
715  cout<<endl<<"Track parameters and covariances at first cluster:"<<endl;
716  extrapTrackParamAtCh.GetParameters().Print();
717  extrapTrackParamAtCh.GetCovariances().Print();
718  }
719 
720  // Add MCS effect
721  Int_t currentChamber = extrapTrackParamAtCh.GetClusterPtr()->GetChamberId();
722  AliMUONTrackExtrap::AddMCSEffect(&extrapTrackParamAtCh,AliMUONConstants::ChamberThicknessInX0(currentChamber),-1.);
723 
724  // reset propagator for smoother
725  if (GetRecoParam()->UseSmoother()) extrapTrackParamAtCh.ResetPropagator();
726 
727  // Add MCS in the missing chamber(s) if any
728  while (ch1 < ch2 && currentChamber > ch2 + 1) {
729  // extrapolation to the missing chamber
730  currentChamber--;
731  if (!AliMUONTrackExtrap::ExtrapToZCov(&extrapTrackParamAtCh, AliMUONConstants::DefaultChamberZ(currentChamber),
732  GetRecoParam()->UseSmoother())) return kFALSE;
733  // add MCS effect
734  AliMUONTrackExtrap::AddMCSEffect(&extrapTrackParamAtCh,AliMUONConstants::ChamberThicknessInX0(currentChamber),-1.);
735  }
736 
737  //Extrapolate trackCandidate to chamber "ch2"
739  GetRecoParam()->UseSmoother())) return kFALSE;
740 
741  // Printout for debuging
742  if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 2) || (AliLog::GetGlobalDebugLevel() >= 2)) {
743  cout<<endl<<"Track parameters and covariances at first cluster extrapolated to z = "<<AliMUONConstants::DefaultChamberZ(ch2)<<":"<<endl;
744  extrapTrackParamAtCh.GetParameters().Print();
745  extrapTrackParamAtCh.GetCovariances().Print();
746  }
747 
748  // Printout for debuging
749  if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
750  cout << "FollowTrackInStation: look for clusters in chamber(1..): " << ch2+1 << endl;
751  }
752 
753  // Ask the clustering to reconstruct new clusters around the track position in the current station
754  // except for station 4 and 5 that are already entirely clusterized
755  if (GetRecoParam()->CombineClusterTrackReco()) {
756  if (nextStation < 3) AskForNewClustersInStation(extrapTrackParamAtCh, clusterStore, nextStation);
757  }
758 
759  Int_t nClusters = clusterStore.GetSize();
760  Bool_t *clusterCh1Used = new Bool_t[nClusters];
761  for (Int_t i = 0; i < nClusters; i++) clusterCh1Used[i] = kFALSE;
762  Int_t iCluster1;
763 
764  // Create iterators to loop over clusters in both chambers
765  TIter nextInCh1(clusterStore.CreateChamberIterator(ch1,ch1));
766  TIter nextInCh2(clusterStore.CreateChamberIterator(ch2,ch2));
767 
768  // look for candidates in chamber 2
769  while ( ( clusterCh2 = static_cast<AliMUONVCluster*>(nextInCh2()) ) ) {
770 
771  // try to add the current cluster fast
772  if (!TryOneClusterFast(extrapTrackParamAtCh, clusterCh2)) continue;
773 
774  // try to add the current cluster accuratly
775  chi2OfCluster = TryOneCluster(extrapTrackParamAtCh, clusterCh2, extrapTrackParamAtCluster2,
776  GetRecoParam()->UseSmoother());
777 
778  // if good chi2 then try to attach a cluster in the other chamber too
779  if (chi2OfCluster < maxChi2OfCluster) {
780 
781  if (GetRecoParam()->UseSmoother()) {
782  // save extrapolated parameters for smoother
783  extrapTrackParamAtCluster2.SetExtrapParameters(extrapTrackParamAtCluster2.GetParameters());
784 
785  // save extrapolated covariance matrix for smoother
786  extrapTrackParamAtCluster2.SetExtrapCovariances(extrapTrackParamAtCluster2.GetCovariances());
787  }
788 
789  // Compute new track parameters including "clusterCh2" using kalman filter
790  addChi2TrackAtCluster2 = RunKalmanFilter(extrapTrackParamAtCluster2);
791 
792  // skip track out of limits
793  if (!IsAcceptable(extrapTrackParamAtCluster2)) continue;
794 
795  // Printout for debuging
796  if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
797  cout << "FollowTrackInStation: found one cluster in chamber(1..): " << ch2+1
798  << " (Chi2 = " << chi2OfCluster << ")" << endl;
799  clusterCh2->Print();
800  cout << " look for second clusters in chamber(1..): " << ch1+1 << " ..." << endl;
801  }
802 
803  // copy new track parameters for next step
804  extrapTrackParam = extrapTrackParamAtCluster2;
805 
806  // add MCS effect
808 
809  // reset propagator for smoother
810  if (GetRecoParam()->UseSmoother()) extrapTrackParam.ResetPropagator();
811 
812  //Extrapolate track parameters to chamber "ch1"
813  Bool_t normalExtrap = AliMUONTrackExtrap::ExtrapToZCov(&extrapTrackParam, AliMUONConstants::DefaultChamberZ(ch1),
814  GetRecoParam()->UseSmoother());
815 
816  // reset cluster iterator of chamber 1
817  nextInCh1.Reset();
818  iCluster1 = -1;
819 
820  // look for second candidates in chamber 1
821  Bool_t foundSecondCluster = kFALSE;
822  if (normalExtrap) while ( ( clusterCh1 = static_cast<AliMUONVCluster*>(nextInCh1()) ) ) {
823  iCluster1++;
824 
825  // try to add the current cluster fast
826  if (!TryOneClusterFast(extrapTrackParam, clusterCh1)) continue;
827 
828  // try to add the current cluster accuratly
829  chi2OfCluster = TryOneCluster(extrapTrackParam, clusterCh1, extrapTrackParamAtCluster1,
830  GetRecoParam()->UseSmoother());
831 
832  // if good chi2 then consider to add the 2 clusters to the "trackCandidate"
833  if (chi2OfCluster < maxChi2OfCluster) {
834 
835  if (GetRecoParam()->UseSmoother()) {
836  // save extrapolated parameters for smoother
837  extrapTrackParamAtCluster1.SetExtrapParameters(extrapTrackParamAtCluster1.GetParameters());
838 
839  // save extrapolated covariance matrix for smoother
840  extrapTrackParamAtCluster1.SetExtrapCovariances(extrapTrackParamAtCluster1.GetCovariances());
841  }
842 
843  // Compute new track parameters including "clusterCh1" using kalman filter
844  addChi2TrackAtCluster1 = RunKalmanFilter(extrapTrackParamAtCluster1);
845 
846  // skip track out of limits
847  if (!IsAcceptable(extrapTrackParamAtCluster1)) continue;
848 
849  // remember a second cluster was found
850  foundSecondCluster = kTRUE;
851  foundTwoClusters = kTRUE;
852 
853  // Printout for debuging
854  if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
855  cout << "FollowTrackInStation: found one cluster in chamber(1..): " << ch1+1
856  << " (Chi2 = " << chi2OfCluster << ")" << endl;
857  clusterCh1->Print();
858  }
859 
860  if (GetRecoParam()->TrackAllTracks()) {
861  // copy trackCandidate into a new track put at the end of fRecTracksPtr and add the new clusters
862  newTrack = new ((*fRecTracksPtr)[fRecTracksPtr->GetLast()+1]) AliMUONTrack(trackCandidate);
863  UpdateTrack(*newTrack,extrapTrackParamAtCluster1,extrapTrackParamAtCluster2,addChi2TrackAtCluster1,addChi2TrackAtCluster2);
864  fNRecTracks++;
865 
866  // Tag clusterCh1 as used
867  clusterCh1Used[iCluster1] = kTRUE;
868 
869  // Printout for debuging
870  if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
871  cout << "FollowTrackInStation: added two clusters in station(1..): " << nextStation+1 << endl;
872  if (AliLog::GetGlobalDebugLevel() >= 3) newTrack->RecursiveDump();
873  }
874 
875  } else if (addChi2TrackAtCluster1+addChi2TrackAtCluster2 < bestAddChi2TrackAtCluster1+bestAddChi2TrackAtCluster2) {
876  // keep track of the best couple of clusters
877  bestAddChi2TrackAtCluster1 = addChi2TrackAtCluster1;
878  bestAddChi2TrackAtCluster2 = addChi2TrackAtCluster2;
879  bestTrackParamAtCluster1 = extrapTrackParamAtCluster1;
880  bestTrackParamAtCluster2 = extrapTrackParamAtCluster2;
881  }
882 
883  }
884 
885  }
886 
887  // if no clusterCh1 found then consider to add clusterCh2 only
888  if (!foundSecondCluster) {
889 
890  // remember a cluster was found
891  foundOneCluster = kTRUE;
892 
893  if (GetRecoParam()->TrackAllTracks()) {
894  // copy trackCandidate into a new track put at the end of fRecTracksPtr and add the new cluster
895  newTrack = new ((*fRecTracksPtr)[fRecTracksPtr->GetLast()+1]) AliMUONTrack(trackCandidate);
896  UpdateTrack(*newTrack,extrapTrackParamAtCluster2,addChi2TrackAtCluster2);
897  fNRecTracks++;
898 
899  // Printout for debuging
900  if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
901  cout << "FollowTrackInStation: added one cluster in chamber(1..): " << ch2+1 << endl;
902  if (AliLog::GetGlobalDebugLevel() >= 3) newTrack->RecursiveDump();
903  }
904 
905  } else if (!foundTwoClusters && addChi2TrackAtCluster2 < bestAddChi2TrackAtCluster1) {
906  // keep track of the best single cluster except if a couple of clusters has already been found
907  bestAddChi2TrackAtCluster1 = addChi2TrackAtCluster2;
908  bestTrackParamAtCluster1 = extrapTrackParamAtCluster2;
909  }
910 
911  }
912 
913  }
914 
915  }
916 
917  // look for candidates in chamber 1 not already attached to a track
918  // if we want to keep all possible tracks or if no good couple of clusters has been found
919  if (GetRecoParam()->TrackAllTracks() || !foundTwoClusters) {
920 
921  // add MCS effect for next step
923 
924  //Extrapolate trackCandidate to chamber "ch1"
925  Bool_t normalExtrap = AliMUONTrackExtrap::ExtrapToZCov(&extrapTrackParamAtCh, AliMUONConstants::DefaultChamberZ(ch1),
926  GetRecoParam()->UseSmoother());
927 
928  // Printout for debuging
929  if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 2) || (AliLog::GetGlobalDebugLevel() >= 2)) {
930  cout<<endl<<"Track parameters and covariances at first cluster extrapolated to z = "<<AliMUONConstants::DefaultChamberZ(ch1)<<":"<<endl;
931  extrapTrackParamAtCh.GetParameters().Print();
932  extrapTrackParamAtCh.GetCovariances().Print();
933  }
934 
935  // Printout for debuging
936  if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
937  cout << "FollowTrackInStation: look for single clusters in chamber(1..): " << ch1+1 << endl;
938  }
939 
940  // reset cluster iterator of chamber 1
941  nextInCh1.Reset();
942  iCluster1 = -1;
943 
944  // look for second candidates in chamber 1
945  if (normalExtrap) while ( ( clusterCh1 = static_cast<AliMUONVCluster*>(nextInCh1()) ) ) {
946  iCluster1++;
947 
948  if (clusterCh1Used[iCluster1]) continue; // Skip clusters already used
949 
950  // try to add the current cluster fast
951  if (!TryOneClusterFast(extrapTrackParamAtCh, clusterCh1)) continue;
952 
953  // try to add the current cluster accuratly
954  chi2OfCluster = TryOneCluster(extrapTrackParamAtCh, clusterCh1, extrapTrackParamAtCluster1,
955  GetRecoParam()->UseSmoother());
956 
957  // if good chi2 then consider to add clusterCh1
958  // We do not try to attach a cluster in the other chamber too since it has already been done above
959  if (chi2OfCluster < maxChi2OfCluster) {
960 
961  if (GetRecoParam()->UseSmoother()) {
962  // save extrapolated parameters for smoother
963  extrapTrackParamAtCluster1.SetExtrapParameters(extrapTrackParamAtCluster1.GetParameters());
964 
965  // save extrapolated covariance matrix for smoother
966  extrapTrackParamAtCluster1.SetExtrapCovariances(extrapTrackParamAtCluster1.GetCovariances());
967  }
968 
969  // Compute new track parameters including "clusterCh1" using kalman filter
970  addChi2TrackAtCluster1 = RunKalmanFilter(extrapTrackParamAtCluster1);
971 
972  // skip track out of limits
973  if (!IsAcceptable(extrapTrackParamAtCluster1)) continue;
974 
975  // remember a cluster was found
976  foundOneCluster = kTRUE;
977 
978  // Printout for debuging
979  if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
980  cout << "FollowTrackInStation: found one cluster in chamber(1..): " << ch1+1
981  << " (Chi2 = " << chi2OfCluster << ")" << endl;
982  clusterCh1->Print();
983  }
984 
985  if (GetRecoParam()->TrackAllTracks()) {
986  // copy trackCandidate into a new track put at the end of fRecTracksPtr and add the new cluster
987  newTrack = new ((*fRecTracksPtr)[fRecTracksPtr->GetLast()+1]) AliMUONTrack(trackCandidate);
988  UpdateTrack(*newTrack,extrapTrackParamAtCluster1,addChi2TrackAtCluster1);
989  fNRecTracks++;
990 
991  // Printout for debuging
992  if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
993  cout << "FollowTrackInStation: added one cluster in chamber(1..): " << ch1+1 << endl;
994  if (AliLog::GetGlobalDebugLevel() >= 3) newTrack->RecursiveDump();
995  }
996 
997  } else if (addChi2TrackAtCluster1 < bestAddChi2TrackAtCluster1) {
998  // keep track of the best single cluster except if a couple of clusters has already been found
999  bestAddChi2TrackAtCluster1 = addChi2TrackAtCluster1;
1000  bestTrackParamAtCluster1 = extrapTrackParamAtCluster1;
1001  }
1002 
1003  }
1004 
1005  }
1006 
1007  }
1008 
1009  // fill out the best track if required else clean up the fRecTracksPtr array
1010  if (!GetRecoParam()->TrackAllTracks()) {
1011  if (foundTwoClusters) {
1012  UpdateTrack(trackCandidate,bestTrackParamAtCluster1,bestTrackParamAtCluster2,bestAddChi2TrackAtCluster1,bestAddChi2TrackAtCluster2);
1013 
1014  // Printout for debuging
1015  if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
1016  cout << "FollowTrackInStation: added the two best clusters in station(1..): " << nextStation+1 << endl;
1017  if (AliLog::GetGlobalDebugLevel() >= 3) trackCandidate.RecursiveDump();
1018  }
1019 
1020  } else if (foundOneCluster) {
1021  UpdateTrack(trackCandidate,bestTrackParamAtCluster1,bestAddChi2TrackAtCluster1);
1022 
1023  // Printout for debuging
1024  if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
1025  cout << "FollowTrackInStation: added the best cluster in chamber(1..): " << bestTrackParamAtCluster1.GetClusterPtr()->GetChamberId()+1 << endl;
1026  if (AliLog::GetGlobalDebugLevel() >= 3) trackCandidate.RecursiveDump();
1027  }
1028 
1029  } else {
1030  delete [] clusterCh1Used;
1031  return kFALSE;
1032  }
1033 
1034  } else if (foundOneCluster || foundTwoClusters) {
1035 
1036  // remove obsolete track
1037  fRecTracksPtr->Remove(&trackCandidate);
1038  fNRecTracks--;
1039 
1040  } else {
1041  delete [] clusterCh1Used;
1042  return kFALSE;
1043  }
1044 
1045  delete [] clusterCh1Used;
1046  return kTRUE;
1047 
1048 }
1049 
1050  //__________________________________________________________________________
1052 {
1055  AliDebug(1,"Enter RunKalmanFilter");
1056 
1057  // Get actual track parameters (p)
1058  TMatrixD param(trackParamAtCluster.GetParameters());
1059 
1060  // Get new cluster parameters (m)
1061  AliMUONVCluster *cluster = trackParamAtCluster.GetClusterPtr();
1062  TMatrixD clusterParam(5,1);
1063  clusterParam.Zero();
1064  clusterParam(0,0) = cluster->GetX();
1065  clusterParam(2,0) = cluster->GetY();
1066 
1067  // Compute the actual parameter weight (W)
1068  TMatrixD paramWeight(trackParamAtCluster.GetCovariances());
1069  if (paramWeight.Determinant() != 0) {
1070  paramWeight.Invert();
1071  } else {
1072  AliWarning(" Determinant = 0");
1073  return 2.*AliMUONTrack::MaxChi2();
1074  }
1075 
1076  // Compute the new cluster weight (U)
1077  TMatrixD clusterWeight(5,5);
1078  clusterWeight.Zero();
1079  clusterWeight(0,0) = 1. / cluster->GetErrX2();
1080  clusterWeight(2,2) = 1. / cluster->GetErrY2();
1081 
1082  // Compute the new parameters covariance matrix ( (W+U)^-1 )
1083  TMatrixD newParamCov(paramWeight,TMatrixD::kPlus,clusterWeight);
1084  if (newParamCov.Determinant() != 0) {
1085  newParamCov.Invert();
1086  } else {
1087  AliWarning(" Determinant = 0");
1088  return 2.*AliMUONTrack::MaxChi2();
1089  }
1090 
1091  // Save the new parameters covariance matrix
1092  trackParamAtCluster.SetCovariances(newParamCov);
1093 
1094  // Compute the new parameters (p' = ((W+U)^-1)U(m-p) + p)
1095  TMatrixD tmp(clusterParam,TMatrixD::kMinus,param);
1096  TMatrixD tmp2(clusterWeight,TMatrixD::kMult,tmp); // U(m-p)
1097  TMatrixD newParam(newParamCov,TMatrixD::kMult,tmp2); // ((W+U)^-1)U(m-p)
1098  newParam += param; // ((W+U)^-1)U(m-p) + p
1099 
1100  // Save the new parameters
1101  trackParamAtCluster.SetParameters(newParam);
1102 
1103  // Compute the additional chi2 (= ((p'-p)^-1)W(p'-p) + ((p'-m)^-1)U(p'-m))
1104  tmp = newParam; // p'
1105  tmp -= param; // (p'-p)
1106  TMatrixD tmp3(paramWeight,TMatrixD::kMult,tmp); // W(p'-p)
1107  TMatrixD addChi2Track(tmp,TMatrixD::kTransposeMult,tmp3); // ((p'-p)^-1)W(p'-p)
1108  tmp = newParam; // p'
1109  tmp -= clusterParam; // (p'-m)
1110  TMatrixD tmp4(clusterWeight,TMatrixD::kMult,tmp); // U(p'-m)
1111  addChi2Track += TMatrixD(tmp,TMatrixD::kTransposeMult,tmp4); // ((p'-p)^-1)W(p'-p) + ((p'-m)^-1)U(p'-m)
1112 
1113  return addChi2Track(0,0);
1114 
1115 }
1116 
1117  //__________________________________________________________________________
1118 void AliMUONTrackReconstructorK::UpdateTrack(AliMUONTrack &track, AliMUONTrackParam &trackParamAtCluster, Double_t addChi2)
1119 {
1122 
1123  // Flag cluster as being (not) removable
1124  if (GetRecoParam()->RequestStation(trackParamAtCluster.GetClusterPtr()->GetChamberId()/2))
1125  trackParamAtCluster.SetRemovable(kFALSE);
1126  else trackParamAtCluster.SetRemovable(kTRUE);
1127  trackParamAtCluster.SetLocalChi2(0.); // --> Local chi2 not used
1128 
1129  // Update the track chi2 into trackParamAtCluster
1130  trackParamAtCluster.SetTrackChi2(track.GetGlobalChi2() + addChi2);
1131 
1132  // Update the chi2 of the new track
1133  track.SetGlobalChi2(trackParamAtCluster.GetTrackChi2());
1134 
1135  // Update array of TrackParamAtCluster
1136  track.AddTrackParamAtCluster(trackParamAtCluster,*(trackParamAtCluster.GetClusterPtr()));
1137 
1138 }
1139 
1140  //__________________________________________________________________________
1142  Double_t addChi2AtCluster1, Double_t addChi2AtCluster2)
1143 {
1146 
1147  // Update local chi2 at first cluster
1148  AliMUONVCluster* cluster1 = trackParamAtCluster1.GetClusterPtr();
1149  Double_t deltaX = trackParamAtCluster1.GetNonBendingCoor() - cluster1->GetX();
1150  Double_t deltaY = trackParamAtCluster1.GetBendingCoor() - cluster1->GetY();
1151  Double_t localChi2AtCluster1 = deltaX*deltaX / cluster1->GetErrX2() +
1152  deltaY*deltaY / cluster1->GetErrY2();
1153  trackParamAtCluster1.SetLocalChi2(localChi2AtCluster1);
1154 
1155  // Flag first cluster as being removable
1156  trackParamAtCluster1.SetRemovable(kTRUE);
1157 
1158  // Update local chi2 at second cluster
1159  AliMUONVCluster* cluster2 = trackParamAtCluster2.GetClusterPtr();
1160  AliMUONTrackParam extrapTrackParamAtCluster2(trackParamAtCluster1);
1161  AliMUONTrackExtrap::ExtrapToZ(&extrapTrackParamAtCluster2, trackParamAtCluster2.GetZ());
1162  deltaX = extrapTrackParamAtCluster2.GetNonBendingCoor() - cluster2->GetX();
1163  deltaY = extrapTrackParamAtCluster2.GetBendingCoor() - cluster2->GetY();
1164  Double_t localChi2AtCluster2 = deltaX*deltaX / cluster2->GetErrX2() +
1165  deltaY*deltaY / cluster2->GetErrY2();
1166  trackParamAtCluster2.SetLocalChi2(localChi2AtCluster2);
1167 
1168  // Flag second cluster as being removable
1169  trackParamAtCluster2.SetRemovable(kTRUE);
1170 
1171  // Update the track chi2 into trackParamAtCluster2
1172  trackParamAtCluster2.SetTrackChi2(track.GetGlobalChi2() + addChi2AtCluster2);
1173 
1174  // Update the track chi2 into trackParamAtCluster1
1175  trackParamAtCluster1.SetTrackChi2(trackParamAtCluster2.GetTrackChi2() + addChi2AtCluster1);
1176 
1177  // Update the chi2 of the new track
1178  track.SetGlobalChi2(trackParamAtCluster1.GetTrackChi2());
1179 
1180  // Update array of trackParamAtCluster
1181  track.AddTrackParamAtCluster(trackParamAtCluster1,*cluster1);
1182  track.AddTrackParamAtCluster(trackParamAtCluster2,*cluster2);
1183 
1184 }
1185 
1186  //__________________________________________________________________________
1187 Bool_t AliMUONTrackReconstructorK::RecoverTrack(AliMUONTrack &trackCandidate, AliMUONVClusterStore& clusterStore, Int_t nextStation)
1188 {
1192  AliDebug(1,"Enter RecoverTrack");
1193 
1194  // Do not try to recover track until we have attached cluster(s) on station(1..) 3
1195  if (nextStation > 1) return kFALSE;
1196 
1197  Int_t worstClusterNumber = -1;
1198  Double_t localChi2, worstLocalChi2 = -1.;
1199 
1200  // Look for the cluster to remove
1201  for (Int_t clusterNumber = 0; clusterNumber < 2; clusterNumber++) {
1202  AliMUONTrackParam *trackParamAtCluster = (AliMUONTrackParam*)trackCandidate.GetTrackParamAtCluster()->UncheckedAt(clusterNumber);
1203 
1204  // check if current cluster is in the previous station
1205  if (trackParamAtCluster->GetClusterPtr()->GetChamberId()/2 != nextStation+1) break;
1206 
1207  // check if current cluster is removable
1208  if (!trackParamAtCluster->IsRemovable()) return kFALSE;
1209 
1210  // reset the current cluster as being not removable if it is on a required station
1211  if (GetRecoParam()->RequestStation(nextStation+1)) trackParamAtCluster->SetRemovable(kFALSE);
1212 
1213  // Pick up cluster with the worst chi2
1214  localChi2 = trackParamAtCluster->GetLocalChi2();
1215  if (localChi2 > worstLocalChi2) {
1216  worstLocalChi2 = localChi2;
1217  worstClusterNumber = clusterNumber;
1218  }
1219  }
1220 
1221  // check if worst cluster found
1222  if (worstClusterNumber < 0) return kFALSE;
1223 
1224  // Remove the worst cluster
1225  trackCandidate.RemoveTrackParamAtCluster((AliMUONTrackParam*)trackCandidate.GetTrackParamAtCluster()->UncheckedAt(worstClusterNumber));
1226 
1227  // Re-calculate track parameters at the (new) first cluster
1228  if (!RetracePartialTrack(trackCandidate,(AliMUONTrackParam*)trackCandidate.GetTrackParamAtCluster()->UncheckedAt(1))) return kFALSE;
1229 
1230  // skip track out of limits
1231  if (!IsAcceptable(*((AliMUONTrackParam*)trackCandidate.GetTrackParamAtCluster()->First()))) return kFALSE;
1232 
1233  // Look for new cluster(s) in next station
1234  return FollowTrackInStation(trackCandidate, clusterStore, nextStation);
1235 
1236 }
1237 
1238  //__________________________________________________________________________
1240 {
1242  AliDebug(1,"Enter UseSmoother");
1243 
1244  AliMUONTrackParam *previousTrackParam = (AliMUONTrackParam*) track.GetTrackParamAtCluster()->First();
1245 
1246  // Smoothed parameters and covariances at first cluster = filtered parameters and covariances
1247  previousTrackParam->SetSmoothParameters(previousTrackParam->GetParameters());
1248  previousTrackParam->SetSmoothCovariances(previousTrackParam->GetCovariances());
1249 
1250  AliMUONTrackParam *currentTrackParam = (AliMUONTrackParam*) track.GetTrackParamAtCluster()->After(previousTrackParam);
1251 
1252  // Save local chi2 at first cluster = last additional chi2 provided by Kalman
1253  previousTrackParam->SetLocalChi2(previousTrackParam->GetTrackChi2() - currentTrackParam->GetTrackChi2());
1254 
1255  // if the track contains only 2 clusters simply copy the filtered parameters
1256  if (track.GetNClusters() == 2) {
1257  currentTrackParam->SetSmoothParameters(currentTrackParam->GetParameters());
1258  currentTrackParam->SetSmoothCovariances(currentTrackParam->GetCovariances());
1259  currentTrackParam->SetLocalChi2(currentTrackParam->GetTrackChi2());
1260  return kTRUE;
1261  }
1262 
1263  while (currentTrackParam) {
1264 
1265  // Get variables
1266  const TMatrixD &extrapParameters = previousTrackParam->GetExtrapParameters(); // X(k+1 k)
1267  const TMatrixD &filteredParameters = currentTrackParam->GetParameters(); // X(k k)
1268  const TMatrixD &previousSmoothParameters = previousTrackParam->GetSmoothParameters(); // X(k+1 n)
1269  const TMatrixD &propagator = previousTrackParam->GetPropagator(); // F(k)
1270  const TMatrixD &extrapCovariances = previousTrackParam->GetExtrapCovariances(); // C(k+1 k)
1271  const TMatrixD &filteredCovariances = currentTrackParam->GetCovariances(); // C(k k)
1272  const TMatrixD &previousSmoothCovariances = previousTrackParam->GetSmoothCovariances(); // C(k+1 n)
1273 
1274  // Compute smoother gain: A(k) = C(kk) * F(k)^t * (C(k+1 k))^-1
1275  TMatrixD extrapWeight(extrapCovariances);
1276  if (extrapWeight.Determinant() != 0) {
1277  extrapWeight.Invert(); // (C(k+1 k))^-1
1278  } else {
1279  AliWarning(" Determinant = 0");
1280  return kFALSE;
1281  }
1282  TMatrixD smootherGain(filteredCovariances,TMatrixD::kMultTranspose,propagator); // C(kk) * F(k)^t
1283  smootherGain *= extrapWeight; // C(kk) * F(k)^t * (C(k+1 k))^-1
1284 
1285  // Compute smoothed parameters: X(k n) = X(k k) + A(k) * (X(k+1 n) - X(k+1 k))
1286  TMatrixD tmpParam(previousSmoothParameters,TMatrixD::kMinus,extrapParameters); // X(k+1 n) - X(k+1 k)
1287  TMatrixD smoothParameters(smootherGain,TMatrixD::kMult,tmpParam); // A(k) * (X(k+1 n) - X(k+1 k))
1288  smoothParameters += filteredParameters; // X(k k) + A(k) * (X(k+1 n) - X(k+1 k))
1289 
1290  // Save smoothed parameters
1291  currentTrackParam->SetSmoothParameters(smoothParameters);
1292 
1293  // Compute smoothed covariances: C(k n) = C(k k) + A(k) * (C(k+1 n) - C(k+1 k)) * (A(k))^t
1294  TMatrixD tmpCov(previousSmoothCovariances,TMatrixD::kMinus,extrapCovariances); // C(k+1 n) - C(k+1 k)
1295  TMatrixD tmpCov2(tmpCov,TMatrixD::kMultTranspose,smootherGain); // (C(k+1 n) - C(k+1 k)) * (A(k))^t
1296  TMatrixD smoothCovariances(smootherGain,TMatrixD::kMult,tmpCov2); // A(k) * (C(k+1 n) - C(k+1 k)) * (A(k))^t
1297  smoothCovariances += filteredCovariances; // C(k k) + A(k) * (C(k+1 n) - C(k+1 k)) * (A(k))^t
1298 
1299  // Save smoothed covariances
1300  currentTrackParam->SetSmoothCovariances(smoothCovariances);
1301 
1302  // Compute smoothed residual: r(k n) = cluster - X(k n)
1303  AliMUONVCluster* cluster = currentTrackParam->GetClusterPtr();
1304  TMatrixD smoothResidual(2,1);
1305  smoothResidual.Zero();
1306  smoothResidual(0,0) = cluster->GetX() - smoothParameters(0,0);
1307  smoothResidual(1,0) = cluster->GetY() - smoothParameters(2,0);
1308 
1309  // Compute weight of smoothed residual: W(k n) = (clusterCov - C(k n))^-1
1310  TMatrixD smoothResidualWeight(2,2);
1311  smoothResidualWeight(0,0) = cluster->GetErrX2() - smoothCovariances(0,0);
1312  smoothResidualWeight(0,1) = - smoothCovariances(0,2);
1313  smoothResidualWeight(1,0) = - smoothCovariances(2,0);
1314  smoothResidualWeight(1,1) = cluster->GetErrY2() - smoothCovariances(2,2);
1315  if (smoothResidualWeight.Determinant() != 0) {
1316  smoothResidualWeight.Invert();
1317  } else {
1318  AliWarning(" Determinant = 0");
1319  return kFALSE;
1320  }
1321 
1322  // Compute local chi2 = (r(k n))^t * W(k n) * r(k n)
1323  TMatrixD tmpChi2(smoothResidual,TMatrixD::kTransposeMult,smoothResidualWeight); // (r(k n))^t * W(k n)
1324  TMatrixD localChi2(tmpChi2,TMatrixD::kMult,smoothResidual); // (r(k n))^t * W(k n) * r(k n)
1325 
1326  // Save local chi2
1327  currentTrackParam->SetLocalChi2(localChi2(0,0));
1328 
1329  previousTrackParam = currentTrackParam;
1330  currentTrackParam = (AliMUONTrackParam*) track.GetTrackParamAtCluster()->After(previousTrackParam);
1331  }
1332 
1333  return kTRUE;
1334 
1335 }
1336 
1337  //__________________________________________________________________________
1339 {
1345  AliDebug(1,"Enter ComplementTracks");
1346 
1347  Int_t chamberId, detElemId;
1348  Double_t chi2OfCluster, addChi2TrackAtCluster, bestAddChi2TrackAtCluster;
1349  Double_t maxChi2OfCluster = 2. * GetRecoParam()->GetSigmaCutForTracking() *
1350  GetRecoParam()->GetSigmaCutForTracking(); // 2 because 2 quantities in chi2
1351  Bool_t foundOneCluster, trackModified, hasChanged = kFALSE;
1352  AliMUONVCluster *cluster;
1353  AliMUONTrackParam *trackParam, *previousTrackParam, *nextTrackParam, trackParamAtCluster, bestTrackParamAtCluster;
1354  AliMUONTrack *nextTrack;
1355 
1357  while (track) {
1358  trackModified = kFALSE;
1359 
1360  trackParam = (AliMUONTrackParam*)track->GetTrackParamAtCluster()->First();
1361  previousTrackParam = trackParam;
1362  while (trackParam) {
1363  foundOneCluster = kFALSE;
1364  bestAddChi2TrackAtCluster = AliMUONTrack::MaxChi2();
1365  chamberId = trackParam->GetClusterPtr()->GetChamberId();
1366  detElemId = trackParam->GetClusterPtr()->GetDetElemId();
1367 
1368  // prepare nextTrackParam before adding new cluster because of the sorting
1369  nextTrackParam = (AliMUONTrackParam*)track->GetTrackParamAtCluster()->After(trackParam);
1370 
1371  // Create iterators to loop over clusters in current chamber
1372  TIter nextInCh(clusterStore.CreateChamberIterator(chamberId,chamberId));
1373 
1374  // look for one second candidate in the same chamber
1375  while ( ( cluster = static_cast<AliMUONVCluster*>(nextInCh()) ) ) {
1376 
1377  // look for a cluster in another detection element
1378  if (cluster->GetDetElemId() == detElemId) continue;
1379 
1380  // try to add the current cluster fast
1381  if (!TryOneClusterFast(*trackParam, cluster)) continue;
1382 
1383  // try to add the current cluster accurately
1384  // never use track parameters at last cluster because the covariance matrix is meaningless
1385  if (nextTrackParam) chi2OfCluster = TryOneCluster(*trackParam, cluster, trackParamAtCluster);
1386  else chi2OfCluster = TryOneCluster(*previousTrackParam, cluster, trackParamAtCluster);
1387 
1388  // if good chi2 then consider to add this cluster to the track
1389  if (chi2OfCluster < maxChi2OfCluster) {
1390 
1391  // Compute local track parameters including current cluster using kalman filter
1392  addChi2TrackAtCluster = RunKalmanFilter(trackParamAtCluster);
1393 
1394  // keep track of the best cluster
1395  if (addChi2TrackAtCluster < bestAddChi2TrackAtCluster) {
1396  bestAddChi2TrackAtCluster = addChi2TrackAtCluster;
1397  bestTrackParamAtCluster = trackParamAtCluster;
1398  foundOneCluster = kTRUE;
1399  }
1400 
1401  }
1402 
1403  }
1404 
1405  // add new cluster if any
1406  if (foundOneCluster) {
1407 
1408  // Printout for debuging
1409  if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
1410  cout << "ComplementTracks: found one cluster in chamber(1..): " << chamberId+1 << endl;
1411  bestTrackParamAtCluster.GetClusterPtr()->Print();
1412  if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 2) || (AliLog::GetGlobalDebugLevel() >= 2)) {
1413  cout<<endl<<"Track parameters and covariances at cluster:"<<endl;
1414  bestTrackParamAtCluster.GetParameters().Print();
1415  bestTrackParamAtCluster.GetCovariances().Print();
1416  }
1417  }
1418 
1419  trackParam->SetRemovable(kTRUE);
1420  bestTrackParamAtCluster.SetRemovable(kTRUE);
1421  track->AddTrackParamAtCluster(bestTrackParamAtCluster,*(bestTrackParamAtCluster.GetClusterPtr()));
1422  trackModified = kTRUE;
1423  hasChanged = kTRUE;
1424  }
1425 
1426  previousTrackParam = trackParam;
1427  trackParam = nextTrackParam;
1428  }
1429 
1430  // prepare next track
1431  nextTrack = (AliMUONTrack*) fRecTracksPtr->After(track);
1432 
1433  // re-compute track parameters using kalman filter if needed
1434  if (trackModified && !RetraceTrack(*track,kTRUE)) {
1435  AliWarning("track modified but problem occur during refitting --> remove track");
1436  fRecTracksPtr->Remove(track);
1437  fNRecTracks--;
1438  }
1439 
1440  track = nextTrack;
1441  }
1442 
1443  return hasChanged;
1444 
1445 }
1446 
1447 //__________________________________________________________________________
1449 {
1454  AliDebug(1,"Enter ImproveTrack");
1455 
1456  Double_t localChi2, worstLocalChi2;
1457  AliMUONTrackParam *trackParamAtCluster, *worstTrackParamAtCluster, *nextTrackParam, *next2nextTrackParam;
1458  Int_t nextChamber, next2nextChamber;
1459  Bool_t smoothed;
1460  Double_t sigmaCut2 = GetRecoParam()->GetSigmaCutForImprovement() *
1462 
1463  while (!track.IsImproved()) {
1464 
1465  // identify removable clusters
1466  track.TagRemovableClusters(GetRecoParam()->RequestedStationMask());
1467 
1468  // Run smoother if required
1469  smoothed = kFALSE;
1470  if (GetRecoParam()->UseSmoother()) smoothed = RunSmoother(track);
1471 
1472  // Use standard procedure to compute local chi2 if smoother not required or not working
1473  if (!smoothed) {
1474 
1475  // Update track parameters and covariances
1476  if (!track.UpdateCovTrackParamAtCluster()) {
1477  AliWarning("unable to update track parameters and covariances --> stop improvement");
1478  // restore the kalman parameters
1479  RetraceTrack(track,kTRUE);
1480  break;
1481  }
1482 
1483  // Compute local chi2 of each clusters
1484  track.ComputeLocalChi2(kTRUE);
1485  }
1486 
1487  // Look for the cluster to remove
1488  worstTrackParamAtCluster = 0x0;
1489  worstLocalChi2 = -1.;
1490  trackParamAtCluster = (AliMUONTrackParam*)track.GetTrackParamAtCluster()->First();
1491  while (trackParamAtCluster) {
1492 
1493  // save parameters into smooth parameters in case of smoother did not work properly
1494  if (GetRecoParam()->UseSmoother() && !smoothed) {
1495  trackParamAtCluster->SetSmoothParameters(trackParamAtCluster->GetParameters());
1496  trackParamAtCluster->SetSmoothCovariances(trackParamAtCluster->GetCovariances());
1497  }
1498 
1499  // Pick up cluster with the worst chi2
1500  localChi2 = trackParamAtCluster->GetLocalChi2();
1501  if (localChi2 > worstLocalChi2) {
1502  worstLocalChi2 = localChi2;
1503  worstTrackParamAtCluster = trackParamAtCluster;
1504  }
1505 
1506  trackParamAtCluster = (AliMUONTrackParam*)track.GetTrackParamAtCluster()->After(trackParamAtCluster);
1507  }
1508 
1509  // Check whether the worst chi2 is under requirement or not
1510  if (worstLocalChi2 < 2. * sigmaCut2) { // 2 because 2 quantities in chi2
1511  track.SetImproved(kTRUE);
1512  break;
1513  }
1514 
1515  // if the worst cluster is not removable then stop improvement
1516  if (!worstTrackParamAtCluster->IsRemovable()) {
1517  // restore the kalman parameters in case they have been lost
1518  if (!smoothed) RetraceTrack(track,kTRUE);
1519  break;
1520  }
1521 
1522  // get track parameters at cluster next to the one to be removed
1523  nextTrackParam = (AliMUONTrackParam*) track.GetTrackParamAtCluster()->After(worstTrackParamAtCluster);
1524 
1525  // Remove the worst cluster
1526  track.RemoveTrackParamAtCluster(worstTrackParamAtCluster);
1527 
1528  // Re-calculate track parameters
1529  // - from the cluster immediately downstream the one suppressed
1530  // - or from the begining - if parameters have been re-computed using the standard method (kalman parameters have been lost)
1531  // - or if the removed cluster was used to compute the tracking seed
1532  Bool_t normalExtrap;
1533  if (smoothed && nextTrackParam) {
1534 
1535  nextChamber = nextTrackParam->GetClusterPtr()->GetChamberId();
1536  next2nextTrackParam = nextTrackParam;
1537  do {
1538 
1539  next2nextChamber = next2nextTrackParam->GetClusterPtr()->GetChamberId();
1540  next2nextTrackParam = (AliMUONTrackParam*) track.GetTrackParamAtCluster()->After(next2nextTrackParam);
1541 
1542  } while (next2nextTrackParam && (next2nextChamber == nextChamber));
1543 
1544  if (next2nextChamber == nextChamber) normalExtrap = RetraceTrack(track,kTRUE);
1545  else normalExtrap = RetracePartialTrack(track,nextTrackParam);
1546 
1547  } else normalExtrap = RetraceTrack(track,kTRUE);
1548 
1549  // stop in case of extrapolation problem
1550  if (!normalExtrap) {
1551  AliWarning("track partially improved but problem occur during refitting --> stop improvement");
1552  break;
1553  }
1554 
1555  // Printout for debuging
1556  if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
1557  cout << "ImproveTracks: track " << fRecTracksPtr->IndexOf(&track)+1 << " improved " << endl;
1558  }
1559 
1560  }
1561 
1562 }
1563 
1564 //__________________________________________________________________________
1566 {
1570 
1571  AliMUONTrackParam *trackParamAtCluster;
1572  Bool_t smoothed = kFALSE;
1573 
1574  // update track parameters (using smoother if required) if not already done
1575  if (track.IsImproved()) smoothed = GetRecoParam()->UseSmoother();
1576  else {
1577  if (GetRecoParam()->UseSmoother()) smoothed = RunSmoother(track);
1578  if (!smoothed) {
1579  if (track.UpdateCovTrackParamAtCluster()) track.ComputeLocalChi2(kTRUE);
1580  else {
1581  AliWarning("finalization failed due to extrapolation problem");
1582  return kFALSE;
1583  }
1584  }
1585  }
1586 
1587  // copy smoothed parameters and covariances if any
1588  if (smoothed) {
1589 
1590  trackParamAtCluster = (AliMUONTrackParam*) (track.GetTrackParamAtCluster()->First());
1591  while (trackParamAtCluster) {
1592 
1593  trackParamAtCluster->SetParameters(trackParamAtCluster->GetSmoothParameters());
1594  trackParamAtCluster->SetCovariances(trackParamAtCluster->GetSmoothCovariances());
1595 
1596  trackParamAtCluster = (AliMUONTrackParam*) (track.GetTrackParamAtCluster()->After(trackParamAtCluster));
1597  }
1598 
1599  }
1600 
1601  return kTRUE;
1602 
1603 }
1604 
1605  //__________________________________________________________________________
1607 {
1609  AliDebug(1,"Enter RefitTrack");
1610 
1611  // check validity of the track (i.e. at least 2 chambers hit on stations 4 and 5)
1612  if (!track.IsValid(0)) {
1613  AliWarning("the track is not valid --> unable to refit");
1614  return kFALSE;
1615  }
1616 
1617  // re-compute track parameters and covariances using Kalman filter
1618  if (!RetraceTrack(track,kTRUE)) {
1619  AliWarning("bad track refitting due to extrapolation failure");
1620  return kFALSE;
1621  }
1622 
1623  // Improve the reconstructed tracks if required
1624  track.SetImproved(kFALSE);
1625  if (enableImprovement && GetRecoParam()->ImproveTracks()) ImproveTrack(track);
1626 
1627  // Fill AliMUONTrack data members
1628  if (track.GetGlobalChi2() < AliMUONTrack::MaxChi2()) return FinalizeTrack(track);
1629  else {
1630  AliWarning("track not finalized due to extrapolation failure");
1631  return kFALSE;
1632  }
1633 
1634 }
1635 
void AskForNewClustersInStation(const AliMUONTrackParam &trackParam, AliMUONVClusterStore &clusterStore, Int_t station)
Bool_t FollowLinearTrackInStation(AliMUONTrack &trackCandidate, const AliMUONVClusterStore &clusterStore, Int_t nextStation)
void SetSmoothParameters(const TMatrixD &parameters)
Virtual class for the MUON track reconstruction.
void RemoveTrackParamAtCluster(AliMUONTrackParam *trackParam)
Int_t GetNClusters() const
return the number of clusters attached to the track
Definition: AliMUONTrack.h:46
virtual Int_t Clusterize(Int_t chamberId, AliMUONVClusterStore &clusterStore, const AliMpArea &area, const AliMUONRecoParam *recoParam=0x0)=0
Find and add clusters from a given region of a given chamber to the store.
Double_t GetLocalChi2() const
return the local chi2 of the associated cluster with respect to the track
Double_t GetSigmaCutForTracking() const
return the cut in sigma to apply on cluster (local chi2) and track (global chi2) during tracking ...
virtual Double_t GetZ() const =0
Return coordinate Z (cm)
const TMatrixD & GetSmoothCovariances() const
Double_t GetBendingCoor() const
return bending coordinate (cm)
Double_t TryOneCluster(const AliMUONTrackParam &trackParam, AliMUONVCluster *cluster, AliMUONTrackParam &trackParamAtCluster, Bool_t updatePropagator=kFALSE)
const TMatrixD & GetParameters() const
return track parameters
Top container class for geometry transformations.
void dZ()
Definition: CalibAlign.C:517
void RemoveUsedSegments(TClonesArray &segments)
virtual Bool_t FollowTracks(AliMUONVClusterStore &clusterStore)
Follow tracks in stations(1..) 3, 2 and 1.
Interface of a cluster finder for combined tracking.
Bool_t RecoverTrack(AliMUONTrack &track, AliMUONVClusterStore &clusterStore, Int_t nextStation)
virtual Int_t GetSize() const =0
The number of objects stored.
Double_t RunKalmanFilter(AliMUONTrackParam &trackParamAtCluster)
Double_t GetZ() const
return Z coordinate (cm)
const TMatrixD & GetExtrapCovariances() const
A rectangle area positioned in plane..
Definition: AliMpArea.h:20
Track parameters in ALICE dimuon spectrometer.
Bool_t FollowTrackInChamber(AliMUONTrack &trackCandidate, AliMUONVClusterStore &clusterStore, Int_t nextChamber)
virtual Bool_t RefitTrack(AliMUONTrack &track, Bool_t enableImprovement=kTRUE)
Re-fit the given track.
Class with MUON reconstruction parameters.
Bool_t IsAcceptable(AliMUONTrackParam &trackParam)
virtual Double_t GetErrX2() const =0
Return resolution**2 (cm**2) on coordinate X.
AliTPCfastTrack * track
void SetNonBendingCoor(Double_t nonBendingCoor)
set non bending coordinate (cm)
static Bool_t ExtrapToZ(AliMUONTrackParam *trackParam, Double_t zEnd)
void SetLocalChi2(Double_t chi2)
set the local chi2 of the associated cluster with respect to the track
Bool_t RetracePartialTrack(AliMUONTrack &trackCandidate, const AliMUONTrackParam *startingTrackParam)
Bool_t TryOneClusterFast(const AliMUONTrackParam &trackParam, const AliMUONVCluster *cluster)
Bool_t ComputeLocalChi2(Bool_t accountForMCS)
Class for the MUON track reconstruction using kalman filter.
void SetExtrapParameters(const TMatrixD &parameters)
void AskForNewClustersInChamber(const AliMUONTrackParam &trackParam, AliMUONVClusterStore &clusterStore, Int_t chamber)
Bool_t IsValid(UInt_t requestedStationMask, Bool_t request2ChInSameSt45=kFALSE)
Double_t GetBendingVertexDispersion() const
return the vertex dispersion (cm) in bending plane
#define AliWarning(message)
Definition: AliLog.h:541
Bool_t UpdateCovTrackParamAtCluster()
const AliMUONRecoParam * GetRecoParam() const
Return reco parameters.
Int_t GetMaxTrackCandidates() const
Get the maximum number of track candidates above which the tracking abort.
virtual void Print(Option_t *option="") const
void UseSmoother(Bool_t flag)
switch on/off the use of the smoother
Double_t GetBendingSlope() const
return bending slope (cm ** -1)
void SetSmoothCovariances(const TMatrixD &covariances)
void SetBendingSlope(Double_t bendingSlope)
set bending slope (cm ** -1)
virtual void ImproveTrack(AliMUONTrack &track)
Improve the given reconstructed track.
abstract base class for clusters
static Int_t GetGlobalDebugLevel()
Definition: AliLog.cxx:476
static Bool_t ExtrapToZCov(AliMUONTrackParam *trackParam, Double_t zEnd, Bool_t updatePropagator=kFALSE)
AliMUONVClusterServer * fClusterServer
reference to our cluster server
void SetImproved(Bool_t improved)
set the flag telling whether the track has been improved or not
Definition: AliMUONTrack.h:76
Double_t GetGlobalChi2() const
return the minimum value of the function minimized by the fit
Definition: AliMUONTrack.h:69
void SetExtrapCovariances(const TMatrixD &covariances)
Bool_t FollowLinearTrackInChamber(AliMUONTrack &trackCandidate, const AliMUONVClusterStore &clusterStore, Int_t nextChamber)
void AddTrackParamAtCluster(const AliMUONTrackParam &trackParam, AliMUONVCluster &cluster, Bool_t copy=kFALSE)
const TMatrixD & GetSmoothParameters() const
Bool_t IsRemovable() const
return kTRUE if the associated cluster can be removed from the track it belongs to ...
static void AddMCSEffect(AliMUONTrackParam *param, Double_t dZ, Double_t x0)
TClonesArray * MakeSegmentsBetweenChambers(const AliMUONVClusterStore &clusterStore, Int_t ch1, Int_t ch2)
Interface of a cluster container.
virtual TIterator * CreateChamberIterator(Int_t firstChamberId, Int_t lastChamberId) const =0
Return an iterator to loop over the store in the given chamber range.
void SetNonBendingSlope(Double_t nonBendingSlope)
set non bending slope (cm ** -1)
virtual Bool_t FinalizeTrack(AliMUONTrack &track)
Finalize the given track.
Double_t GetTrackChi2() const
return the chi2 of the track when the associated cluster was attached
virtual Bool_t MakeMoreTrackCandidates(AliMUONVClusterStore &clusterStore)
Make extra track candidates from clusters in stations(1..) 4 and 5.
const TMatrixD & GetExtrapParameters() const
virtual Double_t GetErrY2() const =0
Return resolution**2 (cm**2) on coordinate Y.
Bool_t RunSmoother(AliMUONTrack &track)
Bool_t RetraceTrack(AliMUONTrack &trackCandidate, Bool_t resetSeed)
void SetParameters(const TMatrixD &parameters)
set track parameters
static Int_t GetChamberId(UInt_t uniqueID)
Return chamber id (0..), part of the uniqueID.
void SetInverseBendingMomentum(Double_t inverseBendingMomentum)
set inverse bending momentum (GeV/c ** -1) times the charge (assumed forward motion) ...
virtual Double_t GetY() const =0
Return coordinate Y (cm)
void MakeTrackCandidatesFast(Bool_t flag)
switch on/off the fast building of track candidates (assuming linear propagation between stations 4 a...
#define AliDebug(logLevel, message)
Definition: AliLog.h:300
void SetBendingCoor(Double_t bendingCoor)
set bending coordinate (cm)
static Float_t * DefaultChamberZ()
Return pointer to array of positions.
void RequestStation(Int_t iSt, Bool_t flag)
request or not at least one cluster in the station to validate the track
Double_t GetNonBendingCoor() const
return non bending coordinate (cm)
void SetRemovable(Bool_t removable)
set the flag telling whether the associated cluster can be removed from the track it belongs to or no...
AliMUONVCluster * GetClusterPtr() const
get pointeur to associated cluster
Int_t fNRecTracks
number of reconstructed tracks
static Double_t ChamberThicknessInX0(Int_t chId)
Return chamber thickness in X0.
void SetTrackChi2(Double_t chi2)
set the chi2 of the track when the associated cluster was attached
static Int_t GetDetElemId(UInt_t uniqueID)
Return detection element id, part of the uniqueID.
virtual Double_t GetX() const =0
Return coordinate X (cm)
static Int_t GetDebugLevel(const char *module, const char *className)
Definition: AliLog.cxx:843
void RecursiveDump(void) const
Reconstructed track in ALICE dimuon spectrometer.
Definition: AliMUONTrack.h:24
#define AliError(message)
Definition: AliLog.h:591
Bool_t IsImproved() const
return kTRUE if the track has been improved
Definition: AliMUONTrack.h:74
static Bool_t IsFieldON()
return kTRUE if the field is switched ON
Double_t GetSigmaCutForImprovement() const
return the cut in sigma to apply on cluster (local chi2) during track improvement ...
virtual Bool_t MakeTrackCandidates(AliMUONVClusterStore &clusterStore)
Make track candidates from clusters in stations(1..) 4 and 5.
void SetCovariances(const TMatrixD &covariances)
Bool_t FollowTrackInStation(AliMUONTrack &trackCandidate, AliMUONVClusterStore &clusterStore, Int_t nextStation)
virtual Bool_t ComplementTracks(const AliMUONVClusterStore &clusterStore)
Complement the reconstructed tracks.
void SetZ(Double_t z)
set Z coordinate (cm)
void UpdateTrack(AliMUONTrack &track, AliMUONTrackParam &trackParamAtCluster, Double_t addChi2)
const TMatrixD & GetCovariances() const
static Double_t GetBendingMomentumFromImpactParam(Double_t impactParam)
TClonesArray * fRecTracksPtr
pointer to array of reconstructed tracks
The equivalent of a std::pair<TObject*,TObject*> ;-)
const TMatrixD & GetPropagator() const
void TagRemovableClusters(UInt_t requestedStationMask)
class TMatrixT< Double_t > TMatrixD
static Double_t MaxChi2()
return the maximum chi2 above which the track can be considered as abnormal (due to extrapolation fai...
Definition: AliMUONTrack.h:144
TObjArray * GetTrackParamAtCluster() const
void SetGlobalChi2(Double_t chi2)
set the minimum value of the function minimized by the fit
Definition: AliMUONTrack.h:71