]> git.uio.no Git - u/mrichter/AliRoot.git/blobdiff - MUON/AliMUONTrackReconstructor.cxx
Fixing Doxygen warnings
[u/mrichter/AliRoot.git] / MUON / AliMUONTrackReconstructor.cxx
index 5b340b2d1b706b808798eb58d8acf84b5ff1d25b..1c3936f5f855c65a7a6c9ca7aaa841c267569ec1 100644 (file)
@@ -35,6 +35,7 @@
 #include "AliMUONTrack.h"
 #include "AliMUONTrackParam.h"
 #include "AliMUONTrackExtrap.h"
+#include "AliMUONRecoParam.h"
 
 #include "AliMpArea.h"
 
@@ -53,8 +54,8 @@ ClassImp(AliMUONTrackReconstructor) // Class implementation in ROOT context
 /// \endcond
 
   //__________________________________________________________________________
-AliMUONTrackReconstructor::AliMUONTrackReconstructor(AliMUONVClusterServer* clusterServer)
-  : AliMUONVTrackReconstructor(clusterServer)
+AliMUONTrackReconstructor::AliMUONTrackReconstructor(const AliMUONRecoParam* recoParam, AliMUONVClusterServer* clusterServer)
+  : AliMUONVTrackReconstructor(recoParam,clusterServer)
 {
   /// Constructor
 }
@@ -66,7 +67,7 @@ AliMUONTrackReconstructor::~AliMUONTrackReconstructor()
 } 
 
   //__________________________________________________________________________
-void AliMUONTrackReconstructor::MakeTrackCandidates(AliMUONVClusterStore& clusterStore)
+Bool_t AliMUONTrackReconstructor::MakeTrackCandidates(AliMUONVClusterStore& clusterStore)
 {
   /// To make track candidates (assuming linear propagation if the flag fgkMakeTrackCandidatesFast is set to kTRUE):
   /// Start with segments station(1..) 4 or 5 then follow track in station 5 or 4.
@@ -84,7 +85,7 @@ void AliMUONTrackReconstructor::MakeTrackCandidates(AliMUONVClusterStore& cluste
   Int_t firstChamber(0);
   Int_t lastChamber(9);
   
-  if (AliMUONReconstructor::GetRecoParam()->CombineClusterTrackReco()) {
+  if (GetRecoParam()->CombineClusterTrackReco()) {
     // ... Here's the exception : ask the clustering to reconstruct
     // clusters *only* in station 4 and 5 for combined tracking
     firstChamber = 6;
@@ -92,7 +93,7 @@ void AliMUONTrackReconstructor::MakeTrackCandidates(AliMUONVClusterStore& cluste
 
   for (Int_t i = firstChamber; i <= lastChamber; ++i ) 
   {
-    if (fClusterServer && AliMUONReconstructor::GetRecoParam()->UseChamber(i)) fClusterServer->Clusterize(i, clusterStore, AliMpArea());
+    if (fClusterServer && GetRecoParam()->UseChamber(i)) fClusterServer->Clusterize(i, clusterStore, AliMpArea(), GetRecoParam());
   }
   
   // Loop over stations(1..) 5 and 4 and make track candidates
@@ -107,18 +108,31 @@ void AliMUONTrackReconstructor::MakeTrackCandidates(AliMUONVClusterStore& cluste
       AliDebug(1,Form("Making primary candidate(1..) %d",++iCandidate));
       
       // Transform segments to tracks and put them at the end of fRecTracksPtr
-      track = new ((*fRecTracksPtr)[fRecTracksPtr->GetLast()+1]) AliMUONTrack((AliMUONObjectPair*)((*segments)[iseg]));
+      track = new ((*fRecTracksPtr)[fRecTracksPtr->GetLast()+1]) AliMUONTrack((AliMUONObjectPair*)((*segments)[iseg]),GetRecoParam()->GetBendingVertexDispersion());
       fNRecTracks++;
       
       // Look for compatible cluster(s) in the other station
-      if (AliMUONReconstructor::GetRecoParam()->MakeTrackCandidatesFast())
+      if (GetRecoParam()->MakeTrackCandidatesFast())
        clusterFound = FollowLinearTrackInStation(*track, clusterStore, 7-istat);
       else clusterFound = FollowTrackInStation(*track, clusterStore, 7-istat);
       
-      // Remove track if no cluster found
-      if (!clusterFound && AliMUONReconstructor::GetRecoParam()->RequestStation(7-istat)) {
-        fRecTracksPtr->Remove(track);
-       fNRecTracks--;
+      // Remove track if no cluster found on a requested station
+      // or abort tracking if there are too many candidates
+      if (GetRecoParam()->RequestStation(7-istat)) {
+       if (!clusterFound) {
+         fRecTracksPtr->Remove(track);
+         fNRecTracks--;
+       } else if (fNRecTracks > GetRecoParam()->GetMaxTrackCandidates()) {
+         AliError(Form("Too many track candidates (%d tracks). Abort tracking.", fNRecTracks));
+         delete segments;
+         return kFALSE;
+       }
+      } else {
+       if ((fNRecTracks + segments->GetEntriesFast() - iseg - 1) > GetRecoParam()->GetMaxTrackCandidates()) {
+         AliError(Form("Too many track candidates (%d tracks). Abort tracking.", fNRecTracks + segments->GetEntriesFast() - iseg - 1));
+         delete segments;
+         return kFALSE;
+       }
       }
       
     }
@@ -127,18 +141,18 @@ void AliMUONTrackReconstructor::MakeTrackCandidates(AliMUONVClusterStore& cluste
     delete segments;
   }
   
-  fRecTracksPtr->Compress(); // this is essential before checking tracks
-  
   // Keep all different tracks or only the best ones as required
-  if (AliMUONReconstructor::GetRecoParam()->TrackAllTracks()) RemoveIdenticalTracks();
+  if (GetRecoParam()->TrackAllTracks()) RemoveIdenticalTracks();
   else RemoveDoubleTracks();
   
   AliDebug(1,Form("Number of good candidates = %d",fNRecTracks));
   
+  return kTRUE;
+  
 }
 
   //__________________________________________________________________________
-void AliMUONTrackReconstructor::MakeMoreTrackCandidates(AliMUONVClusterStore& clusterStore)
+Bool_t AliMUONTrackReconstructor::MakeMoreTrackCandidates(AliMUONVClusterStore& clusterStore)
 {
   /// To make extra track candidates (assuming linear propagation if the flag fgkMakeTrackCandidatesFast is set to kTRUE):
   /// clustering is supposed to be already done
@@ -147,6 +161,7 @@ void AliMUONTrackReconstructor::MakeMoreTrackCandidates(AliMUONVClusterStore& cl
   /// Keep only best candidates or all of them according to the flag fgkTrackAllTracks.
   
   TClonesArray *segments;
+  AliMUONObjectPair *segment;
   AliMUONTrack *track;
   Int_t iCandidate = 0, iCurrentTrack, nCurrentTracks;
   Bool_t clusterFound;
@@ -160,23 +175,25 @@ void AliMUONTrackReconstructor::MakeMoreTrackCandidates(AliMUONVClusterStore& cl
       // Make segments in the station
       segments = MakeSegmentsBetweenChambers(clusterStore, ich1, ich2);
       
+      /// Remove segments already attached to a track
+      RemoveUsedSegments(*segments);
+      
       // Loop over segments
-      for (Int_t iseg=0; iseg<segments->GetEntriesFast(); iseg++) 
+      for (Int_t iSegment=0; iSegment<segments->GetEntriesFast(); iSegment++)
       {
        AliDebug(1,Form("Making primary candidate(1..) %d",++iCandidate));
+       segment = (AliMUONObjectPair*) segments->UncheckedAt(iSegment);
        
        // Transform segments to tracks and put them at the end of fRecTracksPtr
        iCurrentTrack = fRecTracksPtr->GetLast()+1;
-       track = new ((*fRecTracksPtr)[iCurrentTrack]) AliMUONTrack((AliMUONObjectPair*)((*segments)[iseg]));
+       track = new ((*fRecTracksPtr)[iCurrentTrack]) AliMUONTrack(segment,GetRecoParam()->GetBendingVertexDispersion());
        fNRecTracks++;
        
        // Look for compatible cluster(s) in the second chamber of station 5
-       if (AliMUONReconstructor::GetRecoParam()->MakeTrackCandidatesFast())
-         clusterFound = FollowLinearTrackInChamber(*track, clusterStore, 17-ich2);
-       else clusterFound = FollowTrackInChamber(*track, clusterStore, 17-ich2);
+       clusterFound = FollowLinearTrackInChamber(*track, clusterStore, 17-ich2);
        
        // skip the original track in case it has been removed
-       if (AliMUONReconstructor::GetRecoParam()->TrackAllTracks() && clusterFound) iCurrentTrack++;
+       if (GetRecoParam()->TrackAllTracks() && clusterFound) iCurrentTrack++;
        
        // loop over every new tracks
        nCurrentTracks = fRecTracksPtr->GetLast()+1;
@@ -184,13 +201,18 @@ void AliMUONTrackReconstructor::MakeMoreTrackCandidates(AliMUONVClusterStore& cl
          track = (AliMUONTrack*) fRecTracksPtr->UncheckedAt(iCurrentTrack);
          
          // Look for compatible cluster(s) in the second chamber of station 4
-         if (AliMUONReconstructor::GetRecoParam()->MakeTrackCandidatesFast())
-           FollowLinearTrackInChamber(*track, clusterStore, 13-ich1);
-         else FollowTrackInChamber(*track, clusterStore, 13-ich1);
+         FollowLinearTrackInChamber(*track, clusterStore, 13-ich1);
          
          iCurrentTrack++;
        }
        
+       // abort tracking if there are too many candidates
+       if ((fNRecTracks + segments->GetEntriesFast() - iSegment - 1) > GetRecoParam()->GetMaxTrackCandidates()) {
+         AliError(Form("Too many track candidates (%d tracks). Abort tracking.", fNRecTracks + segments->GetEntriesFast() - iSegment - 1));
+         delete segments;
+         return kFALSE;
+       }
+       
       }
       
       // delete the array of segments
@@ -198,18 +220,18 @@ void AliMUONTrackReconstructor::MakeMoreTrackCandidates(AliMUONVClusterStore& cl
     }
   }
   
-  fRecTracksPtr->Compress(); // this is essential before checking tracks
-  
-  // Keep all different tracks or only the best ones as required
-  if (AliMUONReconstructor::GetRecoParam()->TrackAllTracks()) RemoveIdenticalTracks();
-  else RemoveDoubleTracks();
+  // Keep only the best tracks if required
+  if (!GetRecoParam()->TrackAllTracks()) RemoveDoubleTracks();
+  else fRecTracksPtr->Compress();
   
   AliDebug(1,Form("Number of good candidates = %d",fNRecTracks));
   
+  return kTRUE;
+  
 }
 
   //__________________________________________________________________________
-void AliMUONTrackReconstructor::FollowTracks(AliMUONVClusterStore& clusterStore)
+Bool_t AliMUONTrackReconstructor::FollowTracks(AliMUONVClusterStore& clusterStore)
 {
   /// Follow tracks in stations(1..) 3, 2 and 1
   AliDebug(1,"Enter FollowTracks");
@@ -218,8 +240,8 @@ void AliMUONTrackReconstructor::FollowTracks(AliMUONVClusterStore& clusterStore)
   AliMUONTrackParam *trackParam, *nextTrackParam;
   Int_t currentNRecTracks;
   
-  Double_t sigmaCut2 = AliMUONReconstructor::GetRecoParam()->GetSigmaCutForTracking() *
-                       AliMUONReconstructor::GetRecoParam()->GetSigmaCutForTracking();
+  Double_t sigmaCut2 = GetRecoParam()->GetSigmaCutForTracking() *
+                       GetRecoParam()->GetSigmaCutForTracking();
   
   for (Int_t station = 2; station >= 0; station--) {
     
@@ -241,19 +263,22 @@ void AliMUONTrackReconstructor::FollowTracks(AliMUONVClusterStore& clusterStore)
        Fit(*track, kFALSE, kTRUE, kTRUE);
       else Fit(*track, kFALSE, kFALSE, kTRUE);
       
-      // remove track with absolute bending momentum out of limits
-      // or if the normalized chi2 is too high
-      Double_t bendingMomentum = TMath::Abs(1. / ((AliMUONTrackParam*)track->GetTrackParamAtCluster()->First())->GetInverseBendingMomentum());
-      if (bendingMomentum < AliMUONReconstructor::GetRecoParam()->GetMinBendingMomentum() ||
-         bendingMomentum > AliMUONReconstructor::GetRecoParam()->GetMaxBendingMomentum() ||
-         track->GetNormalizedChi2() > sigmaCut2) {
+      // remove tracks out of limits
+      if (!IsAcceptable(*((AliMUONTrackParam*)track->GetTrackParamAtCluster()->First()))) {
+       fRecTracksPtr->Remove(track);
+       fNRecTracks--;
+       continue;
+      }
+      
+      // remove track if the normalized chi2 is too high
+      if (track->GetNormalizedChi2() > sigmaCut2) {
        fRecTracksPtr->Remove(track);
-       fNRecTracks--;
-       continue;
+       fNRecTracks--;
+       continue;
       }
       
       // save parameters from fit into smoothed parameters to complete track afterward
-      if (AliMUONReconstructor::GetRecoParam()->ComplementTracks()) {
+      if (GetRecoParam()->ComplementTracks()) {
        
        if (station==2) { // save track parameters on stations 4 and 5
          
@@ -305,11 +330,11 @@ void AliMUONTrackReconstructor::FollowTracks(AliMUONVClusterStore& clusterStore)
       if (!FollowTrackInStation(*track, clusterStore, station)) {
        
        // Try to recover track if required
-       if (AliMUONReconstructor::GetRecoParam()->RecoverTracks()) {
+       if (GetRecoParam()->RecoverTracks()) {
          
          // work on a copy of the track if this station is not required
          // to keep the case where no cluster is reconstructed as a possible candidate
-         if (!AliMUONReconstructor::GetRecoParam()->RequestStation(station)) {
+         if (!GetRecoParam()->RequestStation(station)) {
            track = new ((*fRecTracksPtr)[fRecTracksPtr->GetLast()+1]) AliMUONTrack(*track);
            fNRecTracks++;
          }
@@ -321,7 +346,7 @@ void AliMUONTrackReconstructor::FollowTracks(AliMUONVClusterStore& clusterStore)
            fNRecTracks--;
          }
          
-       } else if (AliMUONReconstructor::GetRecoParam()->RequestStation(station)) {
+       } else if (GetRecoParam()->RequestStation(station)) {
          // remove track if no cluster found
          fRecTracksPtr->Remove(track);
          fNRecTracks--;
@@ -329,13 +354,19 @@ void AliMUONTrackReconstructor::FollowTracks(AliMUONVClusterStore& clusterStore)
        
       }
       
+      // abort tracking if there are too many candidates
+      if (fNRecTracks > GetRecoParam()->GetMaxTrackCandidates()) {
+       AliError(Form("Too many track candidates (%d tracks). Abort tracking.", fNRecTracks));
+       return kFALSE;
+      }
+      
     }
     
     // Compress fRecTracksPtr for the next step
     fRecTracksPtr->Compress();
     
     // Keep only the best tracks if required
-    if (!AliMUONReconstructor::GetRecoParam()->TrackAllTracks()) RemoveDoubleTracks();
+    if (!GetRecoParam()->TrackAllTracks()) RemoveDoubleTracks();
     
   }
   
@@ -365,7 +396,7 @@ void AliMUONTrackReconstructor::FollowTracks(AliMUONVClusterStore& clusterStore)
     }
     
     // save parameters from fit into smoothed parameters to complete track afterward
-    if (AliMUONReconstructor::GetRecoParam()->ComplementTracks()) {
+    if (GetRecoParam()->ComplementTracks()) {
       
       trackParam = (AliMUONTrackParam*) track->GetTrackParamAtCluster()->First();
       if (trackParam->GetClusterPtr()->GetChamberId() < 2) {
@@ -402,6 +433,8 @@ void AliMUONTrackReconstructor::FollowTracks(AliMUONVClusterStore& clusterStore)
   
   fRecTracksPtr->Compress();
   
+  return kTRUE;
+  
 }
 
   //__________________________________________________________________________
@@ -416,8 +449,8 @@ Bool_t AliMUONTrackReconstructor::FollowTrackInChamber(AliMUONTrack &trackCandid
   AliDebug(1,Form("Enter FollowTrackInChamber(1..) %d", nextChamber+1));
   
   Double_t chi2WithOneCluster = 1.e10;
-  Double_t maxChi2WithOneCluster = 2. * AliMUONReconstructor::GetRecoParam()->GetSigmaCutForTracking() *
-                                       AliMUONReconstructor::GetRecoParam()->GetSigmaCutForTracking(); // 2 because 2 quantities in chi2
+  Double_t maxChi2WithOneCluster = 2. * GetRecoParam()->GetSigmaCutForTracking() *
+                                       GetRecoParam()->GetSigmaCutForTracking(); // 2 because 2 quantities in chi2
   Double_t bestChi2WithOneCluster = maxChi2WithOneCluster;
   Bool_t foundOneCluster = kFALSE;
   AliMUONTrack *newTrack = 0x0;
@@ -468,7 +501,7 @@ Bool_t AliMUONTrackReconstructor::FollowTrackInChamber(AliMUONTrack &trackCandid
   
   // Ask the clustering to reconstruct new clusters around the track position in the current chamber
   // except for station 4 and 5 that are already entirely clusterized
-  if (AliMUONReconstructor::GetRecoParam()->CombineClusterTrackReco()) {
+  if (GetRecoParam()->CombineClusterTrackReco()) {
     if (nextChamber < 6) AskForNewClustersInChamber(extrapTrackParamAtCh, clusterStore, nextChamber);
   }
   
@@ -495,7 +528,7 @@ Bool_t AliMUONTrackReconstructor::FollowTrackInChamber(AliMUONTrack &trackCandid
        cluster->Print();
       }
       
-      if (AliMUONReconstructor::GetRecoParam()->TrackAllTracks()) {
+      if (GetRecoParam()->TrackAllTracks()) {
        // copy trackCandidate into a new track put at the end of fRecTracksPtr and add the new cluster
        newTrack = new ((*fRecTracksPtr)[fRecTracksPtr->GetLast()+1]) AliMUONTrack(trackCandidate);
        UpdateTrack(*newTrack,extrapTrackParamAtCluster);
@@ -518,7 +551,7 @@ Bool_t AliMUONTrackReconstructor::FollowTrackInChamber(AliMUONTrack &trackCandid
   }
   
   // fill out the best track if required else clean up the fRecTracksPtr array
-  if (!AliMUONReconstructor::GetRecoParam()->TrackAllTracks()) {
+  if (!GetRecoParam()->TrackAllTracks()) {
     if (foundOneCluster) {
       UpdateTrack(trackCandidate,bestTrackParamAtCluster);
       
@@ -567,10 +600,10 @@ Bool_t AliMUONTrackReconstructor::FollowTrackInStation(AliMUONTrack &trackCandid
   
   Double_t chi2WithOneCluster = 1.e10;
   Double_t chi2WithTwoClusters = 1.e10;
-  Double_t maxChi2WithOneCluster = 2. * AliMUONReconstructor::GetRecoParam()->GetSigmaCutForTracking() *
-                                       AliMUONReconstructor::GetRecoParam()->GetSigmaCutForTracking(); // 2 because 2 quantities in chi2
-  Double_t maxChi2WithTwoClusters = 4. * AliMUONReconstructor::GetRecoParam()->GetSigmaCutForTracking() *
-                                        AliMUONReconstructor::GetRecoParam()->GetSigmaCutForTracking(); // 4 because 4 quantities in chi2
+  Double_t maxChi2WithOneCluster = 2. * GetRecoParam()->GetSigmaCutForTracking() *
+                                       GetRecoParam()->GetSigmaCutForTracking(); // 2 because 2 quantities in chi2
+  Double_t maxChi2WithTwoClusters = 4. * GetRecoParam()->GetSigmaCutForTracking() *
+                                        GetRecoParam()->GetSigmaCutForTracking(); // 4 because 4 quantities in chi2
   Double_t bestChi2WithOneCluster = maxChi2WithOneCluster;
   Double_t bestChi2WithTwoClusters = maxChi2WithTwoClusters;
   Bool_t foundOneCluster = kFALSE;
@@ -630,7 +663,7 @@ Bool_t AliMUONTrackReconstructor::FollowTrackInStation(AliMUONTrack &trackCandid
   
   // Ask the clustering to reconstruct new clusters around the track position in the current station
   // except for station 4 and 5 that are already entirely clusterized
-  if (AliMUONReconstructor::GetRecoParam()->CombineClusterTrackReco()) {
+  if (GetRecoParam()->CombineClusterTrackReco()) {
     if (nextStation < 3) AskForNewClustersInStation(extrapTrackParamAtCh, clusterStore, nextStation);
   }
   
@@ -694,7 +727,7 @@ Bool_t AliMUONTrackReconstructor::FollowTrackInStation(AliMUONTrack &trackCandid
            clusterCh1->Print();
          }
          
-         if (AliMUONReconstructor::GetRecoParam()->TrackAllTracks()) {
+         if (GetRecoParam()->TrackAllTracks()) {
            // copy trackCandidate into a new track put at the end of fRecTracksPtr and add the new clusters
             newTrack = new ((*fRecTracksPtr)[fRecTracksPtr->GetLast()+1]) AliMUONTrack(trackCandidate);
            UpdateTrack(*newTrack,extrapTrackParamAtCluster1,extrapTrackParamAtCluster2);
@@ -724,7 +757,7 @@ Bool_t AliMUONTrackReconstructor::FollowTrackInStation(AliMUONTrack &trackCandid
       if (!foundSecondCluster) {
         foundOneCluster = kTRUE;
         
-       if (AliMUONReconstructor::GetRecoParam()->TrackAllTracks()) {
+       if (GetRecoParam()->TrackAllTracks()) {
          // copy trackCandidate into a new track put at the end of fRecTracksPtr and add the new cluster
           newTrack = new ((*fRecTracksPtr)[fRecTracksPtr->GetLast()+1]) AliMUONTrack(trackCandidate);
          UpdateTrack(*newTrack,extrapTrackParamAtCluster2);
@@ -750,7 +783,7 @@ Bool_t AliMUONTrackReconstructor::FollowTrackInStation(AliMUONTrack &trackCandid
   
   // look for candidates in chamber 1 not already attached to a track
   // if we want to keep all possible tracks or if no good couple of clusters has been found
-  if (AliMUONReconstructor::GetRecoParam()->TrackAllTracks() || !foundTwoClusters) {
+  if (GetRecoParam()->TrackAllTracks() || !foundTwoClusters) {
     
     // add MCS effect for next step
     AliMUONTrackExtrap::AddMCSEffect(&extrapTrackParamAtCh,AliMUONConstants::ChamberThicknessInX0(),1.);
@@ -798,7 +831,7 @@ Bool_t AliMUONTrackReconstructor::FollowTrackInStation(AliMUONTrack &trackCandid
          clusterCh1->Print();
        }
        
-       if (AliMUONReconstructor::GetRecoParam()->TrackAllTracks()) {
+       if (GetRecoParam()->TrackAllTracks()) {
          // copy trackCandidate into a new track put at the end of fRecTracksPtr and add the new cluster
          newTrack = new ((*fRecTracksPtr)[fRecTracksPtr->GetLast()+1]) AliMUONTrack(trackCandidate);
          UpdateTrack(*newTrack,extrapTrackParamAtCluster1);
@@ -823,7 +856,7 @@ Bool_t AliMUONTrackReconstructor::FollowTrackInStation(AliMUONTrack &trackCandid
   }
   
   // fill out the best track if required else clean up the fRecTracksPtr array
-  if (!AliMUONReconstructor::GetRecoParam()->TrackAllTracks()) {
+  if (!GetRecoParam()->TrackAllTracks()) {
     if (foundTwoClusters) {
       UpdateTrack(trackCandidate,bestTrackParamAtCluster1,bestTrackParamAtCluster2);
       
@@ -916,6 +949,7 @@ Double_t AliMUONTrackReconstructor::TryTwoClusters(const AliMUONTrackParam &trac
     jacob(1,2) = 1.; // dy1/dy
     // first derivative at the second cluster:
     TMatrixD dParam(5,1);
+    Double_t direction[5] = {-1.,-1.,1.,1.,-1.};
     for (Int_t i=0; i<5; i++) {
       // Skip jacobian calculation for parameters with no associated error
       if (kParamCov(i,i) == 0.) continue;
@@ -923,7 +957,7 @@ Double_t AliMUONTrackReconstructor::TryTwoClusters(const AliMUONTrackParam &trac
       for (Int_t j=0; j<5; j++) {
         if (j==i) {
           dParam(j,0) = TMath::Sqrt(kParamCov(i,i));
-         if (j == 4) dParam(j,0) *= TMath::Sign(1.,-paramAtCluster1Save(4,0)); // variation always in the same direction
+         dParam(j,0) *= TMath::Sign(1.,direction[j]*paramAtCluster1Save(j,0)); // variation always in the same direction
         } else dParam(j,0) = 0.;
       }
       
@@ -981,7 +1015,7 @@ void AliMUONTrackReconstructor::UpdateTrack(AliMUONTrack &track, AliMUONTrackPar
                       deltaY*deltaY / cluster->GetErrY2();
   
   // Flag cluster as being not removable
-  if (AliMUONReconstructor::GetRecoParam()->RequestStation(cluster->GetChamberId()/2))
+  if (GetRecoParam()->RequestStation(cluster->GetChamberId()/2))
     trackParamAtCluster.SetRemovable(kFALSE);
   else trackParamAtCluster.SetRemovable(kTRUE);
   trackParamAtCluster.SetLocalChi2(0.); // --> Local chi2 not used
@@ -1056,7 +1090,7 @@ Bool_t AliMUONTrackReconstructor::RecoverTrack(AliMUONTrack &trackCandidate, Ali
     if (!trackParamAtCluster->IsRemovable()) return kFALSE;
     
     // reset the current cluster as beig not removable if it is on a required station
-    if (AliMUONReconstructor::GetRecoParam()->RequestStation(nextStation+1)) trackParamAtCluster->SetRemovable(kFALSE);
+    if (GetRecoParam()->RequestStation(nextStation+1)) trackParamAtCluster->SetRemovable(kFALSE);
     
     // Pick up cluster with the worst chi2
     localChi2 = trackParamAtCluster->GetLocalChi2();
@@ -1078,6 +1112,9 @@ Bool_t AliMUONTrackReconstructor::RecoverTrack(AliMUONTrack &trackCandidate, Ali
   // Calculate the track parameter covariance matrix
   Fit(trackCandidate, kFALSE, kFALSE, kTRUE);
   
+  // skip track out of limits
+  if (!IsAcceptable(*((AliMUONTrackParam*)trackCandidate.GetTrackParamAtCluster()->First()))) return kFALSE;
+  
   // Look for new cluster(s) in next station
   return FollowTrackInStation(trackCandidate,clusterStore,nextStation);
   
@@ -1092,10 +1129,10 @@ void AliMUONTrackReconstructor::SetVertexErrXY2ForFit(AliMUONTrack &trackCandida
   /// the "trackCandidate" to do not influence the result by changing track resolution at vertex
   AliDebug(1,"Enter SetVertexForFit");
   
-  Double_t nonBendingReso2 = AliMUONReconstructor::GetRecoParam()->GetNonBendingVertexDispersion() *
-                             AliMUONReconstructor::GetRecoParam()->GetNonBendingVertexDispersion();
-  Double_t bendingReso2 = AliMUONReconstructor::GetRecoParam()->GetBendingVertexDispersion() *
-                         AliMUONReconstructor::GetRecoParam()->GetBendingVertexDispersion();
+  Double_t nonBendingReso2 = GetRecoParam()->GetNonBendingVertexDispersion() *
+                             GetRecoParam()->GetNonBendingVertexDispersion();
+  Double_t bendingReso2 = GetRecoParam()->GetBendingVertexDispersion() *
+                         GetRecoParam()->GetBendingVertexDispersion();
   
   // add multiple scattering effets
   AliMUONTrackParam paramAtVertex(*((AliMUONTrackParam*)(trackCandidate.GetTrackParamAtCluster()->First())));
@@ -1165,7 +1202,7 @@ void AliMUONTrackReconstructor::Fit(AliMUONTrack &track, Bool_t includeMCS, Bool
   // Set fitted parameters (!! The order is very important for the covariance matrix !!)
   // Mandatory limits to avoid NaN values of parameters
   trackParam = (AliMUONTrackParam*) (track.GetTrackParamAtCluster()->First());
-  Double_t maxIBM = 1. / AliMUONReconstructor::GetRecoParam()->GetMinBendingMomentum();
+  Double_t maxIBM = 1. / GetRecoParam()->GetMinBendingMomentum();
   gMinuit->mnparm(0, "X", trackParam->GetNonBendingCoor(), 0.03, -500.0, 500.0, status);
   gMinuit->mnparm(1, "NonBenS", trackParam->GetNonBendingSlope(), 0.001, -1., 1., status);
   gMinuit->mnparm(2, "Y", trackParam->GetBendingCoor(), 0.10, -500.0, 500.0, status);
@@ -1248,18 +1285,19 @@ void TrackChi2(Int_t & /*nParam*/, Double_t * /*gradient*/, Double_t &chi2, Doub
 }
 
   //__________________________________________________________________________
-void AliMUONTrackReconstructor::ComplementTracks(const AliMUONVClusterStore& clusterStore)
+Bool_t AliMUONTrackReconstructor::ComplementTracks(const AliMUONVClusterStore& clusterStore)
 {
   /// Complete tracks by adding missing clusters (if there is an overlap between
-  /// two detection elements, the track may have two clusters in the same chamber)
-  /// Re-fit track parameters and covariances
+  /// two detection elements, the track may have two clusters in the same chamber).
+  /// Re-fit track parameters and covariances.
+  /// Return kTRUE if one or more tracks have been complemented.
   AliDebug(1,"Enter ComplementTracks");
   
   Int_t chamberId, detElemId;
   Double_t chi2OfCluster, bestChi2OfCluster;
-  Double_t sigmaCut2 = AliMUONReconstructor::GetRecoParam()->GetSigmaCutForTracking() *
-                       AliMUONReconstructor::GetRecoParam()->GetSigmaCutForTracking();
-  Bool_t foundOneCluster, trackModified;
+  Double_t sigmaCut2 = GetRecoParam()->GetSigmaCutForTracking() *
+                       GetRecoParam()->GetSigmaCutForTracking();
+  Bool_t foundOneCluster, trackModified, hasChanged = kFALSE;
   AliMUONVCluster* cluster;
   AliMUONTrackParam *trackParam, *nextTrackParam, copyOfTrackParam, trackParamAtCluster, bestTrackParamAtCluster;
   
@@ -1322,6 +1360,7 @@ void AliMUONTrackReconstructor::ComplementTracks(const AliMUONVClusterStore& clu
        bestTrackParamAtCluster.SetRemovable(kTRUE);
        track->AddTrackParamAtCluster(bestTrackParamAtCluster,*(bestTrackParamAtCluster.GetClusterPtr()));
        trackModified = kTRUE;
+       hasChanged = kTRUE;
       }
       
       trackParam = nextTrackParam;
@@ -1333,6 +1372,8 @@ void AliMUONTrackReconstructor::ComplementTracks(const AliMUONVClusterStore& clu
     track = (AliMUONTrack*) fRecTracksPtr->After(track);
   }
   
+  return hasChanged;
+  
 }
 
   //__________________________________________________________________________
@@ -1344,13 +1385,13 @@ void AliMUONTrackReconstructor::ImproveTrack(AliMUONTrack &track)
   
   Double_t localChi2, worstLocalChi2;
   AliMUONTrackParam *trackParamAtCluster, *worstTrackParamAtCluster;
-  Double_t sigmaCut2 = AliMUONReconstructor::GetRecoParam()->GetSigmaCutForImprovement() *
-                      AliMUONReconstructor::GetRecoParam()->GetSigmaCutForImprovement();
+  Double_t sigmaCut2 = GetRecoParam()->GetSigmaCutForImprovement() *
+                      GetRecoParam()->GetSigmaCutForImprovement();
   
   while (!track.IsImproved()) {
     
     // identify removable clusters
-    track.TagRemovableClusters();
+    track.TagRemovableClusters(GetRecoParam()->RequestedStationMask());
     
     // Update track parameters and covariances
     track.UpdateCovTrackParamAtCluster();
@@ -1421,7 +1462,7 @@ Bool_t AliMUONTrackReconstructor::RefitTrack(AliMUONTrack &track, Bool_t enableI
   /// re-fit the given track
   
   // check validity of the track
-  if (!track.IsValid()) {
+  if (track.GetNClusters() < 3) {
     AliWarning("the track does not contain enough clusters --> unable to refit");
     return kFALSE;
   }
@@ -1444,7 +1485,7 @@ Bool_t AliMUONTrackReconstructor::RefitTrack(AliMUONTrack &track, Bool_t enableI
   
   // Improve the reconstructed tracks if required
   track.SetImproved(kFALSE);
-  if (enableImprovement && AliMUONReconstructor::GetRecoParam()->ImproveTracks()) ImproveTrack(track);
+  if (enableImprovement && GetRecoParam()->ImproveTracks()) ImproveTrack(track);
   
   // Fill AliMUONTrack data members
   FinalizeTrack(track);