]> git.uio.no Git - u/mrichter/AliRoot.git/blobdiff - MUON/AliMUONTrackReconstructor.cxx
Make this class non static, correct a bug (float instead of double) in ReadPCB, and...
[u/mrichter/AliRoot.git] / MUON / AliMUONTrackReconstructor.cxx
index 46ee6710926b075285c5408d3c266736987788b1..4d1ae1125fd6ab0172dac2dcd6661bc66be47e7e 100644 (file)
 
 /* $Id$ */
 
-////////////////////////////////////
-//
-// MUON track reconstructor in ALICE (class renamed from AliMUONEventReconstructor)
-//
-// This class contains as data:
-// * the parameters for the track reconstruction
-// * a pointer to the array of hits to be reconstructed (the event)
-// * a pointer to the array of segments made with these hits inside each station
-// * a pointer to the array of reconstructed tracks
-//
-// It contains as methods, among others:
-// * MakeEventToBeReconstructed to build the array of hits to be reconstructed
-// * MakeSegments to build the segments
-// * MakeTracks to build the tracks
-//
-////////////////////////////////////
+/// \class AliMUONTrackReconstructor
+/// MUON track reconstructor using the original method
+///
+/// This class contains as data:
+/// - the parameters for the track reconstruction
+///
+/// It contains as methods, among others:
+/// - MakeTracks to build the tracks
+///
 
 #include <stdlib.h>
 #include <Riostream.h>
-#include <TDirectory.h>
-#include <TFile.h>
 #include <TMatrixD.h>
 
+#include "AliMUONVTrackReconstructor.h"
 #include "AliMUONTrackReconstructor.h"
 #include "AliMUONData.h"
 #include "AliMUONConstants.h"
-#include "AliMUONHitForRec.h"
-#include "AliMUONTriggerTrack.h"
-#include "AliMUONTriggerCircuitNew.h"
 #include "AliMUONRawCluster.h"
-#include "AliMUONLocalTrigger.h"
-#include "AliMUONGlobalTrigger.h"
-#include "AliMUONSegment.h"
+#include "AliMUONHitForRec.h"
+#include "AliMUONObjectPair.h"
 #include "AliMUONTrack.h"
-#include "AliMUONTrackHit.h"
-#include "AliMagF.h"
-//#include "AliRunLoader.h"
-#include "AliLoader.h"
-#include "AliMUONTrackK.h" 
+#include "AliMUONTrackParam.h"
+#include "AliMUONTrackExtrap.h"
 #include "AliLog.h"
-#include "AliTracker.h"
+#include <TMinuit.h>
 
-//************* Defaults parameters for reconstruction
-const Double_t AliMUONTrackReconstructor::fgkDefaultMinBendingMomentum = 3.0;
-const Double_t AliMUONTrackReconstructor::fgkDefaultMaxBendingMomentum = 3000.0;
-const Double_t AliMUONTrackReconstructor::fgkDefaultMaxChi2 = 100.0;
-const Double_t AliMUONTrackReconstructor::fgkDefaultMaxSigma2Distance = 16.0;
-const Double_t AliMUONTrackReconstructor::fgkDefaultBendingResolution = 0.01;
-const Double_t AliMUONTrackReconstructor::fgkDefaultNonBendingResolution = 0.144;
-const Double_t AliMUONTrackReconstructor::fgkDefaultChamberThicknessInX0 = 0.03;
-// Simple magnetic field:
-// Value taken from macro MUONtracking.C: 0.7 T, hence 7 kG
-// Length and Position from reco_muon.F, with opposite sign:
-// Length = ZMAGEND-ZCOIL
-// Position = (ZMAGEND+ZCOIL)/2
-// to be ajusted differently from real magnetic field ????
-const Double_t AliMUONTrackReconstructor::fgkDefaultSimpleBValue = 7.0;
-const Double_t AliMUONTrackReconstructor::fgkDefaultSimpleBLength = 428.0;
-const Double_t AliMUONTrackReconstructor::fgkDefaultSimpleBPosition = 1019.0;
-const Double_t AliMUONTrackReconstructor::fgkDefaultEfficiency = 0.95;
+// Functions to be minimized with Minuit
+void TrackChi2(Int_t &NParam, Double_t *Gradient, Double_t &Chi2, Double_t *Param, Int_t Flag);
+void TrackChi2MCS(Int_t &NParam, Double_t *Gradient, Double_t &Chi2, Double_t *Param, Int_t Flag);
+
+Double_t MultipleScatteringAngle2(AliMUONTrackParam *param);
 
+/// \cond CLASSIMP
 ClassImp(AliMUONTrackReconstructor) // Class implementation in ROOT context
+/// \endcond
+
+//************* Defaults parameters for reconstruction
+const Double_t AliMUONTrackReconstructor::fgkMaxNormChi2 = 100.0;
+const Bool_t AliMUONTrackReconstructor::fgkTrackAllTracks = kFALSE;
 
 //__________________________________________________________________________
-AliMUONTrackReconstructor::AliMUONTrackReconstructor(AliLoader* loader, AliMUONData* data)
-  : TObject(),
-    fTrackMethod(1), //AZ - tracking method (1-default, 2-Kalman)
-    fMinBendingMomentum(fgkDefaultMinBendingMomentum),
-    fMaxBendingMomentum(fgkDefaultMaxBendingMomentum),
-    fMaxChi2(fgkDefaultMaxChi2),
-    fMaxSigma2Distance(fgkDefaultMaxSigma2Distance),
-    fBendingResolution(fgkDefaultBendingResolution),
-    fNonBendingResolution(fgkDefaultNonBendingResolution),
-    fChamberThicknessInX0(fgkDefaultChamberThicknessInX0),
-    fSimpleBValue(fgkDefaultSimpleBValue),
-    fSimpleBLength(fgkDefaultSimpleBLength),
-    fSimpleBPosition(fgkDefaultSimpleBPosition),
-    fEfficiency(fgkDefaultEfficiency),
-    fHitsForRecPtr(0x0),
-    fNHitsForRec(0),
-    fRecTracksPtr(0x0),
-    fNRecTracks(0),
-    fRecTrackHitsPtr(0x0),
-    fNRecTrackHits(0),
-    fMUONData(data),
-    fLoader(loader),
-    fMuons(0),
-    fTriggerTrack(new AliMUONTriggerTrack()),
-    fTriggerCircuit(0x0)
+AliMUONTrackReconstructor::AliMUONTrackReconstructor(AliMUONData* data)
+  : AliMUONVTrackReconstructor(data)
 {
-  // Constructor for class AliMUONTrackReconstructor
-  SetReconstructionParametersToDefaults();
-
-  // Memory allocation for the TClonesArray of hits for reconstruction
-  // Is 10000 the right size ????
-  fHitsForRecPtr = new TClonesArray("AliMUONHitForRec", 10000);
-
-  // Memory allocation for the TClonesArray's of segments in stations
-  // Is 2000 the right size ????
-  for (Int_t st = 0; st < AliMUONConstants::NTrackingCh()/2; st++) {
-    fSegmentsPtr[st] = new TClonesArray("AliMUONSegment", 2000);
-    fNSegments[st] = 0; // really needed or GetEntriesFast sufficient ????
-  }
+  /// Constructor for class AliMUONTrackReconstructor
+  
   // Memory allocation for the TClonesArray of reconstructed tracks
-  // Is 10 the right size ????
   fRecTracksPtr = new TClonesArray("AliMUONTrack", 10);
-
-  // Memory allocation for the TClonesArray of hits on reconstructed tracks
-  // Is 100 the right size ????
-  fRecTrackHitsPtr = new TClonesArray("AliMUONTrackHit", 100);
-
-  const AliMagF* kField = AliTracker::GetFieldMap();
-  if (!kField) AliFatal("No field available");
- // Sign of fSimpleBValue according to sign of Bx value at (50,50,-950).
-  Float_t b[3], x[3];
-  x[0] = 50.; x[1] = 50.; x[2] = -950.;
-  kField->Field(x,b);
-
-  fSimpleBValue    = TMath::Sign(fSimpleBValue,(Double_t) b[0]);
-  fSimpleBPosition = TMath::Sign(fSimpleBPosition,(Double_t) x[2]);
-  // See how to get fSimple(BValue, BLength, BPosition)
-  // automatically calculated from the actual magnetic field ????
-
-  return;
 }
 
   //__________________________________________________________________________
 AliMUONTrackReconstructor::~AliMUONTrackReconstructor(void)
 {
-  // Destructor for class AliMUONTrackReconstructor
-  delete fHitsForRecPtr; // Correct destruction of everything ???? or delete [] ????
-  for (Int_t st = 0; st < AliMUONConstants::NTrackingCh()/2; st++)
-    delete fSegmentsPtr[st]; // Correct destruction of everything ????
-
-  delete fTriggerTrack;
-}
-  //__________________________________________________________________________
-void AliMUONTrackReconstructor::SetReconstructionParametersToDefaults(void)
-{
-  // Set reconstruction parameters to default values
-  // Would be much more convenient with a structure (or class) ????
-
-  // ******** Parameters for making HitsForRec
-  // minimum radius,
-  // like in TRACKF_STAT:
-  // 2 degrees for stations 1 and 2, or ch(0...) from 0 to 3;
-  // 30 cm for stations 3 to 5, or ch(0...) from 4 to 9
-  for (Int_t ch = 0; ch < AliMUONConstants::NTrackingCh(); ch++) {
-    if (ch < 4) fRMin[ch] = TMath::Abs(AliMUONConstants::DefaultChamberZ(ch)) *
-                 2.0 * TMath::Pi() / 180.0;
-    else fRMin[ch] = 30.0;
-    // maximum radius at 10 degrees and Z of chamber
-    fRMax[ch] = TMath::Abs(AliMUONConstants::DefaultChamberZ(ch)) *
-                 10.0 * TMath::Pi() / 180.0;
-  }
-
-  // ******** Parameters for making segments
-  // should be parametrized ????
-  // according to interval between chambers in a station ????
-  // Maximum distance in non bending plane
-  // 5 * 0.22 just to remember the way it was made in TRACKF_STAT
-  // SIGCUT*DYMAX(IZ)
-  for (Int_t st = 0; st < AliMUONConstants::NTrackingCh()/2; st++)
-    fSegmentMaxDistNonBending[st] = 5. * 0.22;
-  // Maximum distance in bending plane:
-  // values from TRACKF_STAT, corresponding to (J psi 20cm),
-  // scaled to the real distance between chambers in a station
-  fSegmentMaxDistBending[0] = TMath::Abs( 1.5 *
-                                         (AliMUONConstants::DefaultChamberZ(1) - AliMUONConstants::DefaultChamberZ(0)) / 20.0);
-  fSegmentMaxDistBending[1] = TMath::Abs( 1.5 *
-                                         (AliMUONConstants::DefaultChamberZ(3) - AliMUONConstants::DefaultChamberZ(2)) / 20.0);
-  fSegmentMaxDistBending[2] = TMath::Abs( 3.0 *
-                                         (AliMUONConstants::DefaultChamberZ(5) - AliMUONConstants::DefaultChamberZ(4)) / 20.0);
-  fSegmentMaxDistBending[3] = TMath::Abs( 6.0 *
-                                         (AliMUONConstants::DefaultChamberZ(7) - AliMUONConstants::DefaultChamberZ(6)) / 20.0);
-  fSegmentMaxDistBending[4] = TMath::Abs( 6.0 *
-                                         (AliMUONConstants::DefaultChamberZ(9) - AliMUONConstants::DefaultChamberZ(8)) / 20.0);
-
-  return;
-}
-
-//__________________________________________________________________________
-Double_t AliMUONTrackReconstructor::GetImpactParamFromBendingMomentum(Double_t BendingMomentum) const
-{
-  // Returns impact parameter at vertex in bending plane (cm),
-  // from the signed bending momentum "BendingMomentum" in bending plane (GeV/c),
-  // using simple values for dipole magnetic field.
-  // The sign of "BendingMomentum" is the sign of the charge.
-  return (-0.0003 * fSimpleBValue * fSimpleBLength * fSimpleBPosition /
-         BendingMomentum);
-}
-
-//__________________________________________________________________________
-Double_t AliMUONTrackReconstructor::GetBendingMomentumFromImpactParam(Double_t ImpactParam) const
-{
-  // Returns signed bending momentum in bending plane (GeV/c),
-  // the sign being the sign of the charge for particles moving forward in Z,
-  // from the impact parameter "ImpactParam" at vertex in bending plane (cm),
-  // using simple values for dipole magnetic field.
-  return (-0.0003 * fSimpleBValue * fSimpleBLength * fSimpleBPosition /
-         ImpactParam);
-}
-
-//__________________________________________________________________________
-void AliMUONTrackReconstructor::EventReconstruct(void)
-{
-  // To reconstruct one event
-  AliDebug(1,"Enter EventReconstruct");
-  ResetTracks(); //AZ
-  ResetTrackHits(); //AZ 
-  ResetSegments(); //AZ
-  ResetHitsForRec(); //AZ
-  MakeEventToBeReconstructed();
-  MakeSegments();
-  MakeTracks();
-  if (fMUONData->IsTriggerTrackBranchesInTree()) 
-    ValidateTracksWithTrigger(); 
-
-  // Add tracks to MUON data container 
-  for(Int_t i=0; i<GetNRecTracks(); i++) {
-    AliMUONTrack * track = (AliMUONTrack*) GetRecTracksPtr()->At(i);
-    fMUONData->AddRecTrack(*track);
-  }
-
-  return;
-}
-
-//__________________________________________________________________________
-void AliMUONTrackReconstructor::EventReconstructTrigger(void)
-{
-  // To reconstruct one event
-  AliDebug(1,"Enter EventReconstructTrigger");
-  MakeTriggerTracks();  
-  return;
-}
-
-  //__________________________________________________________________________
-void AliMUONTrackReconstructor::ResetHitsForRec(void)
-{
-  // To reset the array and the number of HitsForRec,
-  // and also the number of HitsForRec
-  // and the index of the first HitForRec per chamber
-  if (fHitsForRecPtr) fHitsForRecPtr->Delete();
-  fNHitsForRec = 0;
-  for (Int_t ch = 0; ch < AliMUONConstants::NTrackingCh(); ch++)
-    fNHitsForRecPerChamber[ch] = fIndexOfFirstHitForRecPerChamber[ch] = 0;
-  return;
-}
-
-  //__________________________________________________________________________
-void AliMUONTrackReconstructor::ResetSegments(void)
-{
-  // To reset the TClonesArray of segments and the number of Segments
-  // for all stations
-  for (Int_t st = 0; st < AliMUONConstants::NTrackingCh()/2; st++) {
-    if (fSegmentsPtr[st]) fSegmentsPtr[st]->Clear();
-    fNSegments[st] = 0;
-  }
-  return;
-}
-
-  //__________________________________________________________________________
-void AliMUONTrackReconstructor::ResetTracks(void)
-{
-  // To reset the TClonesArray of reconstructed tracks
-  if (fRecTracksPtr) fRecTracksPtr->Delete();
-  // Delete in order that the Track destructors are called,
-  // hence the space for the TClonesArray of pointers to TrackHit's is freed
-  fNRecTracks = 0;
-  return;
-}
-
-
-  //__________________________________________________________________________
-void AliMUONTrackReconstructor::ResetTrackHits(void)
-{
-  // To reset the TClonesArray of hits on reconstructed tracks
-  if (fRecTrackHitsPtr) fRecTrackHitsPtr->Clear();
-  fNRecTrackHits = 0;
-  return;
-}
-
-  //__________________________________________________________________________
-void AliMUONTrackReconstructor::MakeEventToBeReconstructed(void)
-{
-  // To make the list of hits to be reconstructed,
-  // either from the track ref. hits or from the raw clusters
-  // according to the parameter set for the reconstructor
-
-  AliDebug(1,"Enter MakeEventToBeReconstructed");
-  //AZ ResetHitsForRec();
-  // Reconstruction from raw clusters
-  // AliMUON *MUON  = (AliMUON*) gAlice->GetModule("MUON"); // necessary ????
-  // Security on MUON ????
-  // TreeR assumed to be be "prepared" in calling function
-  // by "MUON->GetTreeR(nev)" ????
-  TTree *treeR = fLoader->TreeR();
-
-  //AZ? fMUONData->SetTreeAddress("RC");
-  AddHitsForRecFromRawClusters(treeR);
-  // No sorting: it is done automatically in the previous function
-  
-  AliDebug(1,"End of MakeEventToBeReconstructed");
-    if (AliLog::GetGlobalDebugLevel() > 0) {
-      AliDebug(1, Form("NHitsForRec: %d",fNHitsForRec));
-      for (Int_t ch = 0; ch < AliMUONConstants::NTrackingCh(); ch++) {
-       AliDebug(1, Form("Chamber(0...): %d",ch));
-       AliDebug(1, Form("NHitsForRec: %d", fNHitsForRecPerChamber[ch]));
-       AliDebug(1, Form("Index(first HitForRec): %d", fIndexOfFirstHitForRecPerChamber[ch]));
-       for (Int_t hit = fIndexOfFirstHitForRecPerChamber[ch];
-            hit < fIndexOfFirstHitForRecPerChamber[ch] + fNHitsForRecPerChamber[ch];
-            hit++) {
-         AliDebug(1, Form("HitForRec index(0...): %d",hit));
-         ((*fHitsForRecPtr)[hit])->Dump();
-      }
-    }
-  }
-  return;
-}
-
-  //__________________________________________________________________________
-void AliMUONTrackReconstructor::SortHitsForRecWithIncreasingChamber()
-{
-  // Sort HitsForRec's in increasing order with respect to chamber number.
-  // Uses the function "Compare".
-  // Update the information for HitsForRec per chamber too.
-  Int_t ch, nhits, prevch;
-  fHitsForRecPtr->Sort();
-  for (ch = 0; ch < AliMUONConstants::NTrackingCh(); ch++) {
-    fNHitsForRecPerChamber[ch] = 0;
-    fIndexOfFirstHitForRecPerChamber[ch] = 0;
-  }
-  prevch = 0; // previous chamber
-  nhits = 0; // number of hits in current chamber
-  // Loop over HitsForRec
-  for (Int_t hit = 0; hit < fNHitsForRec; hit++) {
-    // chamber number (0...)
-    ch = ((AliMUONHitForRec*)  ((*fHitsForRecPtr)[hit]))->GetChamberNumber();
-    // increment number of hits in current chamber
-    (fNHitsForRecPerChamber[ch])++;
-    // update index of first HitForRec in current chamber
-    // if chamber number different from previous one
-    if (ch != prevch) {
-      fIndexOfFirstHitForRecPerChamber[ch] = hit;
-      prevch = ch;
-    }
-  }
-  return;
+  /// Destructor for class AliMUONTrackReconstructor
+  delete fRecTracksPtr;
 }
 
   //__________________________________________________________________________
-void AliMUONTrackReconstructor::AddHitsForRecFromRawClusters(TTree* TR)
+void AliMUONTrackReconstructor::AddHitsForRecFromRawClusters()
 {
-  // To add to the list of hits for reconstruction all the raw clusters
-  // No condition added, like in Fortran TRACKF_STAT,
-  // on the radius between RMin and RMax.
+  /// To add to the list of hits for reconstruction all the raw clusters
+  TTree *treeR;
   AliMUONHitForRec *hitForRec;
   AliMUONRawCluster *clus;
-  Int_t iclus, nclus, nTRentries;
+  Int_t iclus, nclus;
   TClonesArray *rawclusters;
   AliDebug(1,"Enter AddHitsForRecFromRawClusters");
-
-  if (fTrackMethod != 3) { //AZ
-    fMUONData->SetTreeAddress("RC"); //AZ
-    nTRentries = Int_t(TR->GetEntries());
-    if (nTRentries != 1) {
-      AliError(Form("nTRentries = %d not equal to 1 ",nTRentries));
-      exit(0);
-    }
-    fLoader->TreeR()->GetEvent(0); // only one entry  
+  
+  treeR = fMUONData->TreeR();
+  if (!treeR) {
+    AliError("TreeR must be loaded");
+    exit(0);
   }
-
+  
+  fMUONData->SetTreeAddress("RC");
+  fMUONData->GetRawClusters(); // only one entry  
+  
   // Loop over tracking chambers
   for (Int_t ch = 0; ch < AliMUONConstants::NTrackingCh(); ch++) {
-    // number of HitsForRec to 0 for the chamber
-    fNHitsForRecPerChamber[ch] = 0;
-    // index of first HitForRec for the chamber
-    if (ch == 0) fIndexOfFirstHitForRecPerChamber[ch] = 0;
-    else fIndexOfFirstHitForRecPerChamber[ch] = fNHitsForRec;
     rawclusters =fMUONData->RawClusters(ch);
     nclus = (Int_t) (rawclusters->GetEntries());
     // Loop over (cathode correlated) raw clusters
@@ -405,11 +104,7 @@ void AliMUONTrackReconstructor::AddHitsForRecFromRawClusters(TTree* TR)
       // and increment number of AliMUONHitForRec's (total and in chamber)
       hitForRec = new ((*fHitsForRecPtr)[fNHitsForRec]) AliMUONHitForRec(clus);
       fNHitsForRec++;
-      (fNHitsForRecPerChamber[ch])++;
       // more information into HitForRec
-      //  resolution: info should be already in raw cluster and taken from it ????
-      //hitForRec->SetBendingReso2(fBendingResolution * fBendingResolution);
-      //hitForRec->SetNonBendingReso2(fNonBendingResolution * fNonBendingResolution);
       hitForRec->SetBendingReso2(clus->GetErrY() * clus->GetErrY());
       hitForRec->SetNonBendingReso2(clus->GetErrX() * clus->GetErrX());
       //  original raw cluster
@@ -417,765 +112,887 @@ void AliMUONTrackReconstructor::AddHitsForRecFromRawClusters(TTree* TR)
       hitForRec->SetHitNumber(iclus);
       // Z coordinate of the raw cluster (cm)
       hitForRec->SetZ(clus->GetZ(0));
-      if (AliLog::GetGlobalDebugLevel() > 1) {
-       cout << "chamber (0...): " << ch <<
-         " raw cluster (0...): " << iclus << endl;
-       clus->Dump();
-       cout << "AliMUONHitForRec number (1...): " << fNHitsForRec << endl;
-       hitForRec->Dump();}
+      StdoutToAliDebug(3,
+                       cout << "Chamber " << ch <<
+                       " raw cluster  " << iclus << " : " << endl;
+                       clus->Print("full");
+                       cout << "AliMUONHitForRec number (1...): " << fNHitsForRec << endl;
+                       hitForRec->Print("full");
+                       );
     } // end of cluster loop
   } // end of chamber loop
   SortHitsForRecWithIncreasingChamber(); 
+  
+  AliDebug(1,"End of AddHitsForRecFromRawClusters");
+    if (AliLog::GetGlobalDebugLevel() > 0) {
+      AliDebug(1, Form("NHitsForRec: %d",fNHitsForRec));
+      for (Int_t ch = 0; ch < AliMUONConstants::NTrackingCh(); ch++) {
+       AliDebug(1, Form("Chamber(0...): %d",ch));
+       AliDebug(1, Form("NHitsForRec: %d", fNHitsForRecPerChamber[ch]));
+       AliDebug(1, Form("Index(first HitForRec): %d", fIndexOfFirstHitForRecPerChamber[ch]));
+       for (Int_t hit = fIndexOfFirstHitForRecPerChamber[ch];
+            hit < fIndexOfFirstHitForRecPerChamber[ch] + fNHitsForRecPerChamber[ch];
+            hit++) {
+         AliDebug(1, Form("HitForRec index(0...): %d",hit));
+         ((*fHitsForRecPtr)[hit])->Dump();
+      }
+    }
+  }
+  
   return;
 }
 
   //__________________________________________________________________________
-void AliMUONTrackReconstructor::MakeSegments(void)
+void AliMUONTrackReconstructor::MakeTracks(void)
 {
-  // To make the list of segments in all stations,
-  // from the list of hits to be reconstructed
-  AliDebug(1,"Enter MakeSegments");
-  //AZ ResetSegments();
-  // Loop over stations
-  Int_t nb = (fTrackMethod != 1) ? 3 : 0; //AZ
-  for (Int_t st = nb; st < AliMUONConstants::NTrackingCh()/2; st++) 
-    MakeSegmentsPerStation(st); 
-  if (AliLog::GetGlobalDebugLevel() > 1) {
-    cout << "end of MakeSegments" << endl;
-    for (Int_t st = 0; st < AliMUONConstants::NTrackingCh()/2; st++) {
-      cout << "station(0...): " << st
-          << "  Segments: " << fNSegments[st]
-          << endl;
-      for (Int_t seg = 0;
-          seg < fNSegments[st];
-          seg++) {
-       cout << "Segment index(0...): " << seg << endl;
-       ((*fSegmentsPtr[st])[seg])->Dump();
+  /// To make the tracks from the list of segments and points in all stations
+  AliDebug(1,"Enter MakeTracks");
+  // Look for candidates from at least 3 aligned points in stations(1..) 4 and 5
+  MakeTrackCandidates();
+  // Follow tracks in stations(1..) 3, 2 and 1
+  FollowTracks();
+  // Remove double tracks
+  RemoveDoubleTracks();
+  // Propagate tracks to the vertex through absorber
+  ExtrapTracksToVertex();
+  // Fill out the AliMUONTrack's
+  FillMUONTrack();
+}
+
+  //__________________________________________________________________________
+void AliMUONTrackReconstructor::MakeTrackCandidates(void)
+{
+  /// To make track candidates:
+  /// Start with segments station(1..) 4 or 5 then follow track in station 5 or 4.
+  /// Good candidates are made of at least three hitForRec's.
+  /// Keep only best candidates or all of them according to the flag fgkTrackAllTracks.
+  TClonesArray *segments;
+  AliMUONObjectPair *segment;
+  AliMUONHitForRec *hitForRec1, *hitForRec2;
+  AliMUONTrack *track;
+  AliMUONTrackParam *trackParamAtFirstHit;
+  Int_t iCandidate = 0;
+
+  AliDebug(1,"Enter MakeTrackCandidates");
+
+  // Loop over stations(1..) 5 and 4 and make track candidates
+  for (Int_t istat=4; istat>=3; istat--) {
+    // Make segments in the station
+    segments = MakeSegmentsInStation(istat);
+    // Loop over segments
+    for (Int_t iseg=0; iseg<segments->GetEntriesFast(); iseg++) {
+      AliDebug(1,Form("Making primary candidate(1..) %d",++iCandidate));
+      // Transform segments to tracks and put them at the end of fRecTracksPtr
+      segment = (AliMUONObjectPair*) ((*segments)[iseg]);
+      hitForRec1 = (AliMUONHitForRec*) segment->First();
+      hitForRec2 = (AliMUONHitForRec*) segment->Second();
+      track = new ((*fRecTracksPtr)[fRecTracksPtr->GetLast()+1]) AliMUONTrack(hitForRec1, hitForRec2);
+      fNRecTracks++;
+      // Add MCS effects in parameter covariances
+      trackParamAtFirstHit = (AliMUONTrackParam*) (track->GetTrackParamAtHit()->First());
+      AliMUONTrackExtrap::AddMCSEffectInTrackParamCov(trackParamAtFirstHit,AliMUONConstants::ChamberThicknessInX0(),1.);
+      // Printout for debuging
+      if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructor") >= 2) || (AliLog::GetGlobalDebugLevel() >= 2)) {
+        cout<<endl<<"Track parameter covariances at first hit with multiple Coulomb scattering effects:"<<endl;
+        trackParamAtFirstHit->GetCovariances()->Print();
       }
+      // Look for compatible hitForRec(s) in the other station
+      FollowTrackInStation(track,7-istat);
     }
+    // delete the array of segments
+    delete segments;
   }
-  return;
+  fRecTracksPtr->Compress(); // this is essential before checking tracks
+  
+  // Keep all different tracks or only the best ones as required
+  if (fgkTrackAllTracks) RemoveIdenticalTracks();
+  else RemoveDoubleTracks();
+  
+  AliDebug(1,Form("Number of good candidates = %d",fNRecTracks));
+  
 }
 
   //__________________________________________________________________________
-void AliMUONTrackReconstructor::MakeSegmentsPerStation(Int_t Station)
+void AliMUONTrackReconstructor::RemoveIdenticalTracks(void)
 {
-  // To make the list of segments in station number "Station" (0...)
-  // from the list of hits to be reconstructed.
-  // Updates "fNSegments"[Station].
-  // Segments in stations 4 and 5 are sorted
-  // according to increasing absolute value of "impact parameter"
-  AliMUONHitForRec *hit1Ptr, *hit2Ptr;
-  AliMUONSegment *segment;
-  Bool_t last2st;
-  Double_t bendingSlope, distBend, distNonBend, extBendCoor, extNonBendCoor,
-      impactParam = 0., maxImpactParam = 0., minImpactParam = 0.; // =0 to avoid compilation warnings.
-  AliDebug(1,Form("Enter MakeSegmentsPerStation (0...) %d",Station));
-  // first and second chambers (0...) in the station
-  Int_t ch1 = 2 * Station;
-  Int_t ch2 = ch1 + 1;
-  // variable true for stations downstream of the dipole:
-  // Station(0..4) equal to 3 or 4
-  if ((Station == 3) || (Station == 4)) {
-    last2st = kTRUE;
-    // maximum impact parameter (cm) according to fMinBendingMomentum...
-    maxImpactParam =
-      TMath::Abs(GetImpactParamFromBendingMomentum(fMinBendingMomentum));
-    // minimum impact parameter (cm) according to fMaxBendingMomentum...
-    minImpactParam =
-      TMath::Abs(GetImpactParamFromBendingMomentum(fMaxBendingMomentum));
-  }
-  else last2st = kFALSE;
-  // extrapolation factor from Z of first chamber to Z of second chamber
-  // dZ to be changed to take into account fine structure of chambers ????
-  Double_t extrapFact;
-  // index for current segment
-  Int_t segmentIndex = 0;
-  // Loop over HitsForRec in the first chamber of the station
-  for (Int_t hit1 = fIndexOfFirstHitForRecPerChamber[ch1];
-       hit1 < fIndexOfFirstHitForRecPerChamber[ch1] + fNHitsForRecPerChamber[ch1];
-       hit1++) {
-    // pointer to the HitForRec
-    hit1Ptr = (AliMUONHitForRec*) ((*fHitsForRecPtr)[hit1]);
-    // extrapolation,
-    // on the straight line joining the HitForRec to the vertex (0,0,0),
-    // to the Z of the second chamber of the station
-    // Loop over HitsForRec in the second chamber of the station
-    for (Int_t hit2 = fIndexOfFirstHitForRecPerChamber[ch2];
-        hit2 < fIndexOfFirstHitForRecPerChamber[ch2] + fNHitsForRecPerChamber[ch2];
-        hit2++) {
-      // pointer to the HitForRec
-      hit2Ptr = (AliMUONHitForRec*) ((*fHitsForRecPtr)[hit2]);
-      // absolute values of distances, in bending and non bending planes,
-      // between the HitForRec in the second chamber
-      // and the previous extrapolation
-      extrapFact = hit2Ptr->GetZ()/ hit1Ptr->GetZ();
-      extBendCoor = extrapFact * hit1Ptr->GetBendingCoor();
-      extNonBendCoor = extrapFact * hit1Ptr->GetNonBendingCoor();
-      distBend = TMath::Abs(hit2Ptr->GetBendingCoor() - extBendCoor);
-      distNonBend = TMath::Abs(hit2Ptr->GetNonBendingCoor() - extNonBendCoor);
-      if (last2st) {
-       // bending slope
-       if ( hit1Ptr->GetZ() - hit2Ptr->GetZ() != 0.0 ) {
-         bendingSlope = (hit1Ptr->GetBendingCoor() - hit2Ptr->GetBendingCoor()) /
-           (hit1Ptr->GetZ() - hit2Ptr->GetZ());
-         // absolute value of impact parameter
-         impactParam =
-           TMath::Abs(hit1Ptr->GetBendingCoor() - hit1Ptr->GetZ() * bendingSlope);
-        } 
-        else {
-          AliWarning("hit1Ptr->GetZ() = hit2Ptr->GetZ(): impactParam set to maxImpactParam");
-          impactParam = maxImpactParam;   
-        }   
-      }
-      // check for distances not too large,
-      // and impact parameter not too big if stations downstream of the dipole.
-      // Conditions "distBend" and "impactParam" correlated for these stations ????
-      if ((distBend < fSegmentMaxDistBending[Station]) &&
-         (distNonBend < fSegmentMaxDistNonBending[Station]) &&
-         (!last2st || (impactParam < maxImpactParam)) &&
-         (!last2st || (impactParam > minImpactParam))) {
-       // make new segment
-       segment = new ((*fSegmentsPtr[Station])[segmentIndex])
-         AliMUONSegment(hit1Ptr, hit2Ptr);
-       // update "link" to this segment from the hit in the first chamber
-       if (hit1Ptr->GetNSegments() == 0)
-         hit1Ptr->SetIndexOfFirstSegment(segmentIndex);
-       hit1Ptr->SetNSegments(hit1Ptr->GetNSegments() + 1);
-       if (AliLog::GetGlobalDebugLevel() > 1) {
-         cout << "segmentIndex(0...): " << segmentIndex
-              << "  distBend: " << distBend
-              << "  distNonBend: " << distNonBend
-              << endl;
-         segment->Dump();
-         cout << "HitForRec in first chamber" << endl;
-         hit1Ptr->Dump();
-         cout << "HitForRec in second chamber" << endl;
-         hit2Ptr->Dump();
-       };
-       // increment index for current segment
-       segmentIndex++;
-      }
-    } //for (Int_t hit2
-  } // for (Int_t hit1...
-  fNSegments[Station] = segmentIndex;
-  // Sorting according to "impact parameter" if station(1..5) 4 or 5,
-  // i.e. Station(0..4) 3 or 4, using the function "Compare".
-  // After this sorting, it is impossible to use
-  // the "fNSegments" and "fIndexOfFirstSegment"
-  // of the HitForRec in the first chamber to explore all segments formed with it.
-  // Is this sorting really needed ????
-  if ((Station == 3) || (Station == 4)) (fSegmentsPtr[Station])->Sort();
-  AliDebug(1,Form("Station: %d  NSegments:  %d ", Station, fNSegments[Station]));
+  /// To remove identical tracks:
+  /// Tracks are considered identical if they have all their hits in common.
+  /// One keeps the track with the larger number of hits if need be
+  AliMUONTrack *track1, *track2, *trackToRemove;
+  Int_t hitsInCommon, nHits1, nHits2;
+  Bool_t removedTrack1;
+  // Loop over first track of the pair
+  track1 = (AliMUONTrack*) fRecTracksPtr->First();
+  while (track1) {
+    removedTrack1 = kFALSE;
+    nHits1 = track1->GetNTrackHits();
+    // Loop over second track of the pair
+    track2 = (AliMUONTrack*) fRecTracksPtr->After(track1);
+    while (track2) {
+      nHits2 = track2->GetNTrackHits();
+      // number of hits in common between two tracks
+      hitsInCommon = track1->HitsInCommon(track2);
+      // check for identical tracks
+      if ((hitsInCommon == nHits1) || (hitsInCommon == nHits2)) {
+        // decide which track to remove
+        if (nHits2 > nHits1) {
+         // remove track1 and continue the first loop with the track next to track1
+         trackToRemove = track1;
+         track1 = (AliMUONTrack*) fRecTracksPtr->After(track1);
+          fRecTracksPtr->Remove(trackToRemove);
+         fRecTracksPtr->Compress(); // this is essential to retrieve the TClonesArray afterwards
+         fNRecTracks--;
+         removedTrack1 = kTRUE;
+         break;
+       } else {
+         // remove track2 and continue the second loop with the track next to track2
+         trackToRemove = track2;
+         track2 = (AliMUONTrack*) fRecTracksPtr->After(track2);
+         fRecTracksPtr->Remove(trackToRemove);
+         fRecTracksPtr->Compress(); // this is essential to retrieve the TClonesArray afterwards
+         fNRecTracks--;
+        }
+      } else track2 = (AliMUONTrack*) fRecTracksPtr->After(track2);
+    } // track2
+    if (removedTrack1) continue;
+    track1 = (AliMUONTrack*) fRecTracksPtr->After(track1);
+  } // track1
   return;
 }
 
   //__________________________________________________________________________
-void AliMUONTrackReconstructor::MakeTracks(void)
+void AliMUONTrackReconstructor::RemoveDoubleTracks(void)
 {
-  // To make the tracks,
-  // from the list of segments and points in all stations
-  AliDebug(1,"Enter MakeTracks");
-  // The order may be important for the following Reset's
-  //AZ ResetTracks();
-  //AZ ResetTrackHits();
-  if (fTrackMethod != 1) { //AZ - Kalman filter
-    MakeTrackCandidatesK();
-    if (fRecTracksPtr->GetEntriesFast() == 0) return;
-    // Follow tracks in stations(1..) 3, 2 and 1
-    FollowTracksK();
-    // Remove double tracks
-    RemoveDoubleTracksK();
-    // Propagate tracks to the vertex thru absorber
-    GoToVertex();
-    // Fill AliMUONTrack data members
-    FillMUONTrack();
-  } else { 
-    // Look for candidates from at least 3 aligned points in stations(1..) 4 and 5
-    MakeTrackCandidates();
-    // Follow tracks in stations(1..) 3, 2 and 1
-    FollowTracks();
-    // Remove double tracks
-    RemoveDoubleTracks();
-    UpdateTrackParamAtHit();
-    UpdateHitForRecAtHit();
-  }
+  /// To remove double tracks:
+  /// Tracks are considered identical if more than half of the hits of the track
+  /// which has the smaller number of hits are in common with the other track.
+  /// Among two identical tracks, one keeps the track with the larger number of hits
+  /// or, if these numbers are equal, the track with the minimum chi2.
+  AliMUONTrack *track1, *track2, *trackToRemove;
+  Int_t hitsInCommon, nHits1, nHits2;
+  Bool_t removedTrack1;
+  // Loop over first track of the pair
+  track1 = (AliMUONTrack*) fRecTracksPtr->First();
+  while (track1) {
+    removedTrack1 = kFALSE;
+    nHits1 = track1->GetNTrackHits();
+    // Loop over second track of the pair
+    track2 = (AliMUONTrack*) fRecTracksPtr->After(track1);
+    while (track2) {
+      nHits2 = track2->GetNTrackHits();
+      // number of hits in common between two tracks
+      hitsInCommon = track1->HitsInCommon(track2);
+      // check for identical tracks
+      if (((nHits1 < nHits2) && (2 * hitsInCommon > nHits1)) || (2 * hitsInCommon > nHits2)) {
+        // decide which track to remove
+        if ((nHits1 > nHits2) || ((nHits1 == nHits2) && (track1->GetFitFMin() <= track2->GetFitFMin()))) {
+         // remove track2 and continue the second loop with the track next to track2
+         trackToRemove = track2;
+         track2 = (AliMUONTrack*) fRecTracksPtr->After(track2);
+         fRecTracksPtr->Remove(trackToRemove);
+         fRecTracksPtr->Compress(); // this is essential to retrieve the TClonesArray afterwards
+         fNRecTracks--;
+        } else {
+         // else remove track1 and continue the first loop with the track next to track1
+         trackToRemove = track1;
+         track1 = (AliMUONTrack*) fRecTracksPtr->After(track1);
+          fRecTracksPtr->Remove(trackToRemove);
+         fRecTracksPtr->Compress(); // this is essential to retrieve the TClonesArray afterwards
+         fNRecTracks--;
+         removedTrack1 = kTRUE;
+         break;
+        }
+      } else track2 = (AliMUONTrack*) fRecTracksPtr->After(track2);
+    } // track2
+    if (removedTrack1) continue;
+    track1 = (AliMUONTrack*) fRecTracksPtr->After(track1);
+  } // track1
   return;
 }
 
   //__________________________________________________________________________
-void AliMUONTrackReconstructor::ValidateTracksWithTrigger(void)
+void AliMUONTrackReconstructor::FollowTracks(void)
 {
-  // Try to match track from tracking system with trigger track
-  AliMUONTrack *track;
-  TClonesArray *recTriggerTracks;
+  /// Follow tracks in stations(1..) 3, 2 and 1
+  AliDebug(1,"Enter FollowTracks");
   
-  fMUONData->SetTreeAddress("RL");
-  fMUONData->GetRecTriggerTracks();
-  recTriggerTracks = fMUONData->RecTriggerTracks();
-
+  AliMUONTrack *track, *nextTrack;
+  AliMUONTrackParam *trackParamAtFirstHit;
+  Double_t numberOfDegFree, chi2Norm;
+  Int_t CurrentNRecTracks;
+  
+  for (Int_t station = 2; station >= 0; station--) {
+    // Save the actual number of reconstructed track in case of
+    // tracks are added or suppressed during the tracking procedure
+    // !! Do not compress fRecTracksPtr until the end of the loop over tracks !!
+    CurrentNRecTracks = fNRecTracks;
+    for (Int_t iRecTrack = 0; iRecTrack <CurrentNRecTracks; iRecTrack++) {
+      AliDebug(1,Form("FollowTracks: track candidate(1..) %d", iRecTrack+1));
+      track = (AliMUONTrack*) fRecTracksPtr->UncheckedAt(iRecTrack);
+      // Fit the track:
+      // Do not take into account the multiple scattering to speed up the fit
+      // Calculate the track parameter covariance matrix
+      // If "station" is station(1..) 3 then use the vertex to better constrain the fit
+      if (station==2) {
+        SetVertexForFit(track);
+        track->SetFitWithVertex(kTRUE);
+      } else track->SetFitWithVertex(kFALSE);
+      Fit(track,kFALSE, kTRUE);
+      // Remove the track if the normalized chi2 is too high
+      numberOfDegFree = (2. * track->GetNTrackHits() - 5.);
+      if (numberOfDegFree > 0) chi2Norm = track->GetFitFMin() / numberOfDegFree;
+      else chi2Norm = 1.e10;
+      if (chi2Norm > fgkMaxNormChi2) {
+       fRecTracksPtr->Remove(track);
+       fNRecTracks--;
+       continue;
+      }
+      // Add MCS effects in parameter covariances
+      trackParamAtFirstHit = (AliMUONTrackParam*) (track->GetTrackParamAtHit()->First());
+      AliMUONTrackExtrap::AddMCSEffectInTrackParamCov(trackParamAtFirstHit,AliMUONConstants::ChamberThicknessInX0(),1.);
+      // Printout for debuging
+      if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructor") >= 2) || (AliLog::GetGlobalDebugLevel() >= 2)) {
+        cout<<endl<<"Track parameter covariances at first hit with multiple Coulomb scattering effects:"<<endl;
+        trackParamAtFirstHit->GetCovariances()->Print();
+      }
+      // Look for compatible hitForRec in station(0..) "station"
+      FollowTrackInStation(track,station);
+    }
+    // Compress fRecTracksPtr for the next step
+    fRecTracksPtr->Compress();
+    // Keep only the best tracks if required
+    if (!fgkTrackAllTracks) RemoveDoubleTracks();
+  }
+  
+  // Last fit of track candidates with all station
+  // Take into account the multiple scattering and remove bad tracks
+  Int_t trackIndex = -1;
   track = (AliMUONTrack*) fRecTracksPtr->First();
   while (track) {
-    track->MatchTriggerTrack(recTriggerTracks);
-    track = (AliMUONTrack*) fRecTracksPtr->After(track);
+    trackIndex++;
+    nextTrack = (AliMUONTrack*) fRecTracksPtr->After(track); // prepare next track
+    track->SetFitWithVertex(kFALSE); // just to be sure
+    Fit(track,kTRUE, kFALSE);
+    // Printout for debuging
+    if (AliLog::GetGlobalDebugLevel() >= 3) {
+      cout << "FollowTracks: track candidate(0..) " << trackIndex << " after final fit" << endl;
+      track->RecursiveDump();
+    } 
+    // Remove the track if the normalized chi2 is too high
+    numberOfDegFree = (2.0 * track->GetNTrackHits() - 5);
+    if (numberOfDegFree > 0) chi2Norm = track->GetFitFMin() / numberOfDegFree;
+    else chi2Norm = 1.e10;
+    if (chi2Norm > fgkMaxNormChi2) {
+      fRecTracksPtr->Remove(track);
+      fNRecTracks--;
+    }
+    track = nextTrack;
   }
-
+  fRecTracksPtr->Compress();
+  
 }
 
   //__________________________________________________________________________
-Bool_t AliMUONTrackReconstructor::MakeTriggerTracks(void)
+void AliMUONTrackReconstructor::FollowTrackInStation(AliMUONTrack* trackCandidate, Int_t nextStation)
 {
-    // To make the trigger tracks from Local Trigger
-  AliDebug(1, "Enter MakeTriggerTracks");
-    
-    Int_t nTRentries;
-    Long_t gloTrigPat;
-    TClonesArray *localTrigger;
-    TClonesArray *globalTrigger;
-    AliMUONLocalTrigger *locTrg;
-    AliMUONGlobalTrigger *gloTrg;
-
-    TTree* treeR = fLoader->TreeR();
-   
-    nTRentries = Int_t(treeR->GetEntries());
-     
-    treeR->GetEvent(0); // only one entry  
-
-    if (!(fMUONData->IsTriggerBranchesInTree())) {
-      AliWarning(Form("Trigger information is not avalaible, nTRentries = %d not equal to 1",nTRentries));
-      return kFALSE;
+  /// Follow trackCandidate in station(0..) nextStation and search for compatible HitForRec(s)
+  /// Keep all possibilities or only the best one(s) according to the flag fgkTrackAllTracks:
+  /// kTRUE:  duplicate "trackCandidate" if there are several possibilities and add the new tracks at the end of
+  ///         fRecTracksPtr to avoid conficts with other track candidates at this current stage of the tracking procedure.
+  ///         Remove the obsolete "trackCandidate" at the end.
+  /// kFALSE: add only the best hit(s) to the "trackCandidate". Try to add a couple of hits in priority.
+  AliDebug(1,Form("Enter FollowTrackInStation(1..) %d", nextStation+1));
+  
+  Int_t ch1 = 2*nextStation;
+  Int_t ch2 = 2*nextStation+1;
+  Double_t zCh2 = AliMUONConstants::DefaultChamberZ(ch2);
+  Double_t chi2WithOneHitForRec = 1.e10;
+  Double_t chi2WithTwoHitForRec = 1.e10;
+  Double_t maxChi2WithOneHitForRec = 2.*fgkMaxNormChi2; // 2 because 2 quantities in chi2
+  Double_t maxChi2WithTwoHitForRec = 4.*fgkMaxNormChi2; // 4 because 4 quantities in chi2
+  Double_t bestChi2WithOneHitForRec = maxChi2WithOneHitForRec;
+  Double_t bestChi2WithTwoHitForRec = maxChi2WithTwoHitForRec;
+  AliMUONTrack *newTrack = 0x0;
+  AliMUONHitForRec *hitForRecCh1, *hitForRecCh2;
+  AliMUONHitForRec *bestHitForRec1 = 0x0, *bestHitForRec2 = 0x0;
+  Bool_t *hitForRecCh1Used = new Bool_t[fNHitsForRecPerChamber[ch1]];
+  for (Int_t hit1 = 0; hit1 < fNHitsForRecPerChamber[ch1]; hit1++) hitForRecCh1Used[hit1] = kFALSE;
+  //
+  //Extrapolate trackCandidate to chamber "ch2" to save computing time in the next steps
+  AliMUONTrackParam *extrapTrackParamPtr = trackCandidate->GetExtrapTrackParam();
+  *extrapTrackParamPtr = *((AliMUONTrackParam*)(trackCandidate->GetTrackParamAtHit()->First()));
+  AliMUONTrackExtrap::ExtrapToZCov(extrapTrackParamPtr, zCh2);
+  AliMUONTrackParam extrapTrackParamSave(*extrapTrackParamPtr);
+  //
+  // Printout for debuging
+  if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructor") >= 2) || (AliLog::GetGlobalDebugLevel() >= 2)) {
+    TMatrixD* paramCovForDebug = extrapTrackParamPtr->GetCovariances();
+    cout<<endl<<"Track parameter covariances at first hit extrapolated to z = "<<zCh2<<":"<<endl;
+    paramCovForDebug->Print();
+  }
+  //
+  // look for candidates in chamber 2 
+  // Printout for debuging
+  if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructor") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
+    cout << "FollowTrackInStation: look for hits in chamber(1..): " << ch2+1 << endl;
+  }
+  for (Int_t hit2 = 0; hit2 < fNHitsForRecPerChamber[ch2]; hit2++) {
+    hitForRecCh2 = (AliMUONHitForRec*) fHitsForRecPtr->UncheckedAt(fIndexOfFirstHitForRecPerChamber[ch2]+hit2);
+    // extrapolate track parameters and covariances only once for this hit
+    AliMUONTrackExtrap::ExtrapToZCov(extrapTrackParamPtr, hitForRecCh2->GetZ());
+    chi2WithOneHitForRec = trackCandidate->TryOneHitForRec(hitForRecCh2);
+    // if good chi2 then try to attach a hitForRec in the other chamber too
+    if (chi2WithOneHitForRec < maxChi2WithOneHitForRec) {
+      // Printout for debuging
+      if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructor") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
+        cout << "FollowTrackInStation: look for second hits in chamber(1..): " << ch1+1 << endl;
+      }
+      Bool_t foundSecondHit = kFALSE;
+      for (Int_t hit1 = 0; hit1 < fNHitsForRecPerChamber[ch1]; hit1++) {
+        hitForRecCh1 = (AliMUONHitForRec*) fHitsForRecPtr->UncheckedAt(fIndexOfFirstHitForRecPerChamber[ch1]+hit1);
+       chi2WithTwoHitForRec = trackCandidate->TryTwoHitForRec(hitForRecCh2, hitForRecCh1); // order hits like that to save computing time
+        // if good chi2 then create a new track by adding the 2 hitForRec to the "trackCandidate"
+       if (chi2WithTwoHitForRec < maxChi2WithTwoHitForRec) {
+         foundSecondHit = kTRUE;
+          if (fgkTrackAllTracks) {
+           // copy trackCandidate into a new track put at the end of fRecTracksPtr and add the new hitForRec's
+            newTrack = new ((*fRecTracksPtr)[fRecTracksPtr->GetLast()+1]) AliMUONTrack(*trackCandidate);
+           fNRecTracks++;
+            AliMUONTrackParam TrackParam1(extrapTrackParamSave);
+            AliMUONTrackExtrap::ExtrapToZ(&TrackParam1, hitForRecCh1->GetZ());
+           newTrack->AddTrackParamAtHit(&TrackParam1,hitForRecCh1);
+            AliMUONTrackParam TrackParam2(extrapTrackParamSave);
+            AliMUONTrackExtrap::ExtrapToZ(&TrackParam2, hitForRecCh2->GetZ());
+           newTrack->AddTrackParamAtHit(&TrackParam2,hitForRecCh2);
+            // Sort TrackParamAtHit according to increasing Z
+            newTrack->GetTrackParamAtHit()->Sort();
+           // Update the chi2 of the new track
+           if (newTrack->GetFitFMin()<0) newTrack->SetFitFMin(chi2WithTwoHitForRec);
+           else newTrack->SetFitFMin(newTrack->GetFitFMin() + chi2WithTwoHitForRec);
+           // Tag hitForRecCh1 as used
+           hitForRecCh1Used[hit1] = kTRUE;
+           // Printout for debuging
+           if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructor") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
+             cout << "FollowTrackInStation: added two hits in station(1..): " << nextStation+1
+                  << " (Chi2 = " << chi2WithTwoHitForRec << ")" << endl;
+             if (AliLog::GetGlobalDebugLevel() >= 3) newTrack->RecursiveDump();
+           }
+          } else if (chi2WithTwoHitForRec < bestChi2WithTwoHitForRec) {
+           // keep track of the best couple of hits
+           bestChi2WithTwoHitForRec = chi2WithTwoHitForRec;
+           bestHitForRec1 = hitForRecCh1;
+           bestHitForRec2 = hitForRecCh2;
+          }
+       }
+      }
+      // if no hitForRecCh1 found then consider to add hitForRecCh2 only
+      if (!foundSecondHit) {
+        if (fgkTrackAllTracks) {
+         // copy trackCandidate into a new track put at the end of fRecTracksPtr and add the new hitForRec's
+          newTrack = new ((*fRecTracksPtr)[fRecTracksPtr->GetLast()+1]) AliMUONTrack(*trackCandidate);
+         fNRecTracks++;
+          AliMUONTrackParam TrackParam1(extrapTrackParamSave);
+          AliMUONTrackExtrap::ExtrapToZ(&TrackParam1, hitForRecCh2->GetZ());
+          newTrack->AddTrackParamAtHit(&TrackParam1,hitForRecCh2);
+          // Sort TrackParamAtHit according to increasing Z
+          newTrack->GetTrackParamAtHit()->Sort();
+         // Update the chi2 of the new track
+         if (newTrack->GetFitFMin()<0) newTrack->SetFitFMin(chi2WithOneHitForRec);
+         else newTrack->SetFitFMin(newTrack->GetFitFMin() + chi2WithOneHitForRec);
+         // Printout for debuging
+         if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructor") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
+           cout << "FollowTrackInStation: added one hit in chamber(1..): " << ch2+1
+                << " (Chi2 = " << chi2WithOneHitForRec << ")" << endl;
+           if (AliLog::GetGlobalDebugLevel() >= 3) newTrack->RecursiveDump();
+         }
+       } if (!bestHitForRec2 && chi2WithOneHitForRec < bestChi2WithOneHitForRec) {
+         // keep track of the best single hitForRec except if a couple
+          // of hits has already been found (i.e. bestHitForRec2!=0x0)
+         bestChi2WithOneHitForRec = chi2WithOneHitForRec;
+         bestHitForRec1 = hitForRecCh2;
+        }
+      }
     }
-
-    fMUONData->SetTreeAddress("TC");
-    fMUONData->GetTrigger();
-
-    // global trigger for trigger pattern
-    gloTrigPat = 0;
-    globalTrigger = fMUONData->GlobalTrigger(); 
-    gloTrg = (AliMUONGlobalTrigger*)globalTrigger->UncheckedAt(0);
-    if (gloTrg)
-      gloTrigPat = gloTrg->GetGlobalPattern();
+    // reset the extrapolated track parameter for next step
+    trackCandidate->SetExtrapTrackParam(&extrapTrackParamSave);
+  }
+  //
+  // 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 hitForRec has been found
+  if (fgkTrackAllTracks || !bestHitForRec2) {
+    if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructor") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
+      cout << "FollowTrackInStation: look for single hits in chamber(1..): " << ch1+1 << endl;
+    }
+    for (Int_t hit1 = 0; hit1 < fNHitsForRecPerChamber[ch1]; hit1++) {
+      hitForRecCh1 = (AliMUONHitForRec*) fHitsForRecPtr->UncheckedAt(fIndexOfFirstHitForRecPerChamber[ch1]+hit1);
+      if (hitForRecCh1Used[hit1]) continue; // Skip hitForRec already used
+      chi2WithOneHitForRec = trackCandidate->TryOneHitForRec(hitForRecCh1);
+      // if good chi2 then create a new track by adding the good hitForRec in "ch1" to the "trackCandidate"
+      // We do not try to attach a hitForRec in the other chamber too since it has already been done above
+      if (chi2WithOneHitForRec < maxChi2WithOneHitForRec) {
+       if (fgkTrackAllTracks) {
+         // copy trackCandidate into a new track put at the end of fRecTracksPtr and add the new hitForRec's
+         newTrack = new ((*fRecTracksPtr)[fRecTracksPtr->GetLast()+1]) AliMUONTrack(*trackCandidate);
+         fNRecTracks++;
+         AliMUONTrackParam TrackParam1(extrapTrackParamSave);
+         AliMUONTrackExtrap::ExtrapToZ(&TrackParam1, hitForRecCh1->GetZ());
+         newTrack->AddTrackParamAtHit(&TrackParam1,hitForRecCh1);
+         // Sort TrackParamAtHit according to increasing Z
+         newTrack->GetTrackParamAtHit()->Sort();
+         // Update the chi2 of the new track
+         if (newTrack->GetFitFMin()<0) newTrack->SetFitFMin(chi2WithOneHitForRec);
+         else newTrack->SetFitFMin(newTrack->GetFitFMin() + chi2WithOneHitForRec);
+         // Printout for debuging
+         if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructor") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
+           cout << "FollowTrackInStation: added one hit in chamber(1..): " << ch1+1
+                << " (Chi2 = " << chi2WithOneHitForRec << ")" << endl;
+           if (AliLog::GetGlobalDebugLevel() >= 3) newTrack->RecursiveDump();
+         }
+       } if (!bestHitForRec2 && chi2WithOneHitForRec < bestChi2WithOneHitForRec) {
+         // keep track of the best single hitForRec except if a couple
+         // of hits has already been found (i.e. bestHitForRec1!=0x0)
+         bestChi2WithOneHitForRec = chi2WithOneHitForRec;
+         bestHitForRec1 = hitForRecCh1;
+       }
+      }
+    }
+  }
+  //
+  // fill out the best track if required else clean up the fRecTracksPtr array
+  if (!fgkTrackAllTracks && bestHitForRec1) {
+    AliMUONTrackParam TrackParam1(extrapTrackParamSave);
+    AliMUONTrackExtrap::ExtrapToZ(&TrackParam1, bestHitForRec1->GetZ());
+    trackCandidate->AddTrackParamAtHit(&TrackParam1,bestHitForRec1);
+    if (bestHitForRec2) {
+      AliMUONTrackParam TrackParam2(extrapTrackParamSave);
+      AliMUONTrackExtrap::ExtrapToZ(&TrackParam2, bestHitForRec2->GetZ());
+      trackCandidate->AddTrackParamAtHit(&TrackParam2,bestHitForRec2);
+      // Sort TrackParamAtHit according to increasing Z
+      trackCandidate->GetTrackParamAtHit()->Sort();
+      // Update the chi2 of the new track
+      if (trackCandidate->GetFitFMin()<0) trackCandidate->SetFitFMin(bestChi2WithTwoHitForRec);
+      else trackCandidate->SetFitFMin(trackCandidate->GetFitFMin() + bestChi2WithTwoHitForRec);
+      // Printout for debuging
+      if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructor") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
+        cout << "FollowTrackInStation: added the two best hits in station(1..): " << nextStation+1
+             << " (Chi2 = " << bestChi2WithTwoHitForRec << ")" << endl;
+        if (AliLog::GetGlobalDebugLevel() >= 3) newTrack->RecursiveDump();
+      }
+    } else {
+      // Sort TrackParamAtHit according to increasing Z
+      trackCandidate->GetTrackParamAtHit()->Sort();
+      // Update the chi2 of the new track
+      if (trackCandidate->GetFitFMin()<0) trackCandidate->SetFitFMin(bestChi2WithOneHitForRec);
+      else trackCandidate->SetFitFMin(trackCandidate->GetFitFMin() + bestChi2WithOneHitForRec);
+      // Printout for debuging
+      if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructor") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
+        cout << "FollowTrackInStation: added the best hit in station(1..): " << nextStation+1
+             << " (Chi2 = " << bestChi2WithOneHitForRec << ")" << endl;
+        if (AliLog::GetGlobalDebugLevel() >= 3) newTrack->RecursiveDump();
+      }
+    }
+  } else {
+    fRecTracksPtr->Remove(trackCandidate); // obsolete track
+    fNRecTracks--;
+  }
   
-
-    // local trigger for tracking 
-    localTrigger = fMUONData->LocalTrigger();    
-    Int_t nlocals = (Int_t) (localTrigger->GetEntries());
-
-    Float_t z11 = AliMUONConstants::DefaultChamberZ(10);
-    Float_t z21 = AliMUONConstants::DefaultChamberZ(12);
-
-    Float_t y11 = 0.;
-    Int_t stripX21 = 0;
-    Float_t y21 = 0.;
-    Float_t x11 = 0.;
-
-    for (Int_t i=0; i<nlocals; i++) { // loop on Local Trigger
-      locTrg = (AliMUONLocalTrigger*)localTrigger->UncheckedAt(i);     
-
-      AliDebug(1, "AliMUONTrackReconstructor::MakeTriggerTrack using NEW trigger \n");
-      AliMUONTriggerCircuitNew* circuit = 
-       (AliMUONTriggerCircuitNew*)fTriggerCircuit->At(locTrg->LoCircuit()-1); // -1 !!!
-
-      y11 = circuit->GetY11Pos(locTrg->LoStripX()); 
-      stripX21 = locTrg->LoStripX()+locTrg->LoDev()+1;
-      y21 = circuit->GetY21Pos(stripX21);      
-      x11 = circuit->GetX11Pos(locTrg->LoStripY());
-      
-      AliDebug(1, Form(" MakeTriggerTrack %d %d %d %d %d %f %f %f \n",i,locTrg->LoCircuit(),
-                      locTrg->LoStripX(),locTrg->LoStripX()+locTrg->LoDev()+1,locTrg->LoStripY(),y11, y21, x11));
-      
-      Float_t thetax = TMath::ATan2( x11 , z11 );
-      Float_t thetay = TMath::ATan2( (y21-y11) , (z21-z11) );
-      
-      fTriggerTrack->SetX11(x11);
-      fTriggerTrack->SetY11(y11);
-      fTriggerTrack->SetThetax(thetax);
-      fTriggerTrack->SetThetay(thetay);
-      fTriggerTrack->SetGTPattern(gloTrigPat);
-            
-      fMUONData->AddRecTriggerTrack(*fTriggerTrack);
-    } // end of loop on Local Trigger
-    return kTRUE;    
 }
 
   //__________________________________________________________________________
-Int_t AliMUONTrackReconstructor::MakeTrackCandidatesWithTwoSegments(AliMUONSegment *BegSegment)
+void AliMUONTrackReconstructor::SetVertexForFit(AliMUONTrack* trackCandidate)
 {
-  // To make track candidates with two segments in stations(1..) 4 and 5,
-  // the first segment being pointed to by "BegSegment".
-  // Returns the number of such track candidates.
-  Int_t endStation, iEndSegment, nbCan2Seg;
-  AliMUONSegment *endSegment;
-  AliMUONSegment *extrapSegment = NULL;
-  AliMUONTrack *recTrack;
-  Double_t mcsFactor;
-  AliDebug(1,"Enter MakeTrackCandidatesWithTwoSegments");
-  // Station for the end segment
-  endStation = 7 - (BegSegment->GetHitForRec1())->GetChamberNumber() / 2;
-  // multiple scattering factor corresponding to one chamber
-  mcsFactor = 0.0136 /
-    GetBendingMomentumFromImpactParam(BegSegment->GetBendingImpact());
-  mcsFactor    = fChamberThicknessInX0 * mcsFactor * mcsFactor;
-  // linear extrapolation to end station
-  // number of candidates with 2 segments to 0
-  nbCan2Seg = 0;
-  // Loop over segments in the end station
-  for (iEndSegment = 0; iEndSegment < fNSegments[endStation]; iEndSegment++) {
-    // pointer to segment
-    endSegment = (AliMUONSegment*) ((*fSegmentsPtr[endStation])[iEndSegment]);
-    // test compatibility between current segment and "extrapSegment"
-    // 4 because 4 quantities in chi2
-    extrapSegment =
-      BegSegment->CreateSegmentFromLinearExtrapToStation(endSegment->GetZ(), mcsFactor);
-    if ((endSegment->
-        NormalizedChi2WithSegment(extrapSegment,
-                                  fMaxSigma2Distance)) <= 4.0) {
-      // both segments compatible:
-      // make track candidate from "begSegment" and "endSegment"
-      AliDebug(2,Form("TrackCandidate with Segment %d in Station(0..) %d", iEndSegment, endStation));
-      // flag for both segments in one track:
-      // to be done in track constructor ????
-      BegSegment->SetInTrack(kTRUE);
-      endSegment->SetInTrack(kTRUE);
-      recTrack = new ((*fRecTracksPtr)[fNRecTracks])
-       AliMUONTrack(BegSegment, endSegment, this);
-      fNRecTracks++;
-      if (AliLog::GetGlobalDebugLevel() > 1) recTrack->RecursiveDump();
-      // increment number of track candidates with 2 segments
-      nbCan2Seg++;
-    }
-    delete extrapSegment; // should not delete HitForRec's it points to !!!!
-  } // for (iEndSegment = 0;...
-  return nbCan2Seg;
+  /// Add the vertex as a measured hit to constrain the fit of the "trackCandidate"
+  /// Compute the vertex resolution from natural vertex dispersion and
+  /// multiple scattering effets according to trackCandidate path in absorber
+  /// It is necessary to account for multiple scattering effects here instead of during the fit of
+  /// the "trackCandidate" to do not influence the result by changing track resolution at vertex
+  AliDebug(1,"Enter SetVertexForFit");
+  
+  Double_t nonBendingReso2 = fNonBendingVertexDispersion * fNonBendingVertexDispersion;
+  Double_t bendingReso2 = fBendingVertexDispersion * fBendingVertexDispersion;
+  // add multiple scattering effets
+  AliMUONTrackParam paramAtVertex(*((AliMUONTrackParam*)(trackCandidate->GetTrackParamAtHit()->First())));
+  paramAtVertex.DeleteCovariances(); // to be sure to account only for multiple scattering
+  AliMUONTrackExtrap::ExtrapToVertexUncorrected(&paramAtVertex,0.);
+  TMatrixD* paramCov = paramAtVertex.GetCovariances();
+  nonBendingReso2 += (*paramCov)(0,0);
+  bendingReso2 += (*paramCov)(2,2);
+  // Set the vertex
+  AliMUONHitForRec vertex; // Coordinates set to (0.,0.,0.) by default
+  vertex.SetNonBendingReso2(nonBendingReso2);
+  vertex.SetBendingReso2(bendingReso2);
+  trackCandidate->SetVertex(&vertex);
 }
 
   //__________________________________________________________________________
-Int_t AliMUONTrackReconstructor::MakeTrackCandidatesWithOneSegmentAndOnePoint(AliMUONSegment *BegSegment)
+void AliMUONTrackReconstructor::Fit(AliMUONTrack *track, Bool_t includeMCS, Bool_t calcCov)
 {
-  // To make track candidates with one segment and one point
-  // in stations(1..) 4 and 5,
-  // the segment being pointed to by "BegSegment".
-  Int_t ch, ch1, ch2, endStation, iHit, iHitMax, iHitMin, nbCan1Seg1Hit;
-  AliMUONHitForRec *extrapHitForRec= NULL;
-  AliMUONHitForRec *hit;
-  AliMUONTrack *recTrack;
-  Double_t mcsFactor;
-  AliDebug(1,"Enter MakeTrackCandidatesWithOneSegmentAndOnePoint");
-  // station for the end point
-  endStation = 7 - (BegSegment->GetHitForRec1())->GetChamberNumber() / 2;
-  // multiple scattering factor corresponding to one chamber
-  mcsFactor = 0.0136 /
-    GetBendingMomentumFromImpactParam(BegSegment->GetBendingImpact());
-  mcsFactor    = fChamberThicknessInX0 * mcsFactor * mcsFactor;
-  // first and second chambers(0..) in the end station
-  ch1 = 2 * endStation;
-  ch2 = ch1 + 1;
-  // number of candidates to 0
-  nbCan1Seg1Hit = 0;
-  // Loop over chambers of the end station
-  for (ch = ch2; ch >= ch1; ch--) {
-    // limits for the hit index in the loop
-    iHitMin = fIndexOfFirstHitForRecPerChamber[ch];
-    iHitMax = iHitMin + fNHitsForRecPerChamber[ch];
-    // Loop over HitForRec's in the chamber
-    for (iHit = iHitMin; iHit < iHitMax; iHit++) {
-      // pointer to HitForRec
-      hit = (AliMUONHitForRec*) ((*fHitsForRecPtr)[iHit]);
-      // test compatibility between current HitForRec and "extrapHitForRec"
-      // 2 because 2 quantities in chi2
-      // linear extrapolation to chamber
-      extrapHitForRec =
-       BegSegment->CreateHitForRecFromLinearExtrapToChamber( hit->GetZ(), mcsFactor);
-      if ((hit->
-          NormalizedChi2WithHitForRec(extrapHitForRec,
-                                      fMaxSigma2Distance)) <= 2.0) {
-       // both HitForRec's compatible:
-       // make track candidate from begSegment and current HitForRec
-       AliDebug(2, Form("TrackCandidate with HitForRec  %d in Chamber(0..) %d", iHit, ch));
-       // flag for beginning segments in one track:
-       // to be done in track constructor ????
-       BegSegment->SetInTrack(kTRUE);
-       recTrack = new ((*fRecTracksPtr)[fNRecTracks])
-         AliMUONTrack(BegSegment, hit, this);
-       // the right place to eliminate "double counting" ???? how ????
-       fNRecTracks++;
-       if (AliLog::GetGlobalDebugLevel() > 1) recTrack->RecursiveDump();
-       // increment number of track candidates
-       nbCan1Seg1Hit++;
-      }
-      delete extrapHitForRec;
-    } // for (iHit = iHitMin;...
-  } // for (ch = ch2;...
-  return nbCan1Seg1Hit;
+  /// Fit the track "track" with or without multiple Coulomb scattering according to "includeMCS".
+  
+  Double_t benC, errorParam, invBenP, nonBenC, x, y;
+  AliMUONTrackParam *trackParam;
+  Double_t arg[1], fedm, errdef, fitFMin;
+  Int_t npari, nparx;
+  Int_t status, covStatus;
+  
+  // Clear MINUIT parameters
+  gMinuit->mncler();
+  // Give the fitted track to MINUIT
+  gMinuit->SetObjectFit(track);
+  if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructor") >= 2) || (AliLog::GetGlobalDebugLevel() >= 2)) {
+    // Define print level
+    arg[0] = 1;
+    gMinuit->mnexcm("SET PRI", arg, 1, status);
+    // Print covariance matrix
+    gMinuit->mnexcm("SHO COV", arg, 0, status);
+  } else {
+    arg[0] = -1;
+    gMinuit->mnexcm("SET PRI", arg, 1, status);
+  }
+  // No warnings
+  gMinuit->mnexcm("SET NOW", arg, 0, status);
+  // Define strategy
+  //arg[0] = 2;
+  //gMinuit->mnexcm("SET STR", arg, 1, status);
+  
+  // Switch between available FCN according to "includeMCS"
+  if (includeMCS) gMinuit->SetFCN(TrackChi2MCS);
+  else gMinuit->SetFCN(TrackChi2);
+  
+  // Set fitted parameters (!! The order is very important for the covariance matrix !!)
+  trackParam = (AliMUONTrackParam*) (track->GetTrackParamAtHit()->First());
+  // could be tried with no limits for the search (min=max=0) ????
+  // mandatory limits in non Bending to avoid NaN values of parameters
+  gMinuit->mnparm(0, "X", trackParam->GetNonBendingCoor(), 0.03, -500.0, 500.0, status);
+  gMinuit->mnparm(1, "NonBenS", trackParam->GetNonBendingSlope(), 0.001, -0.5, 0.5, status);
+  // mandatory limits in Bending to avoid NaN values of parameters
+  gMinuit->mnparm(2, "Y", trackParam->GetBendingCoor(), 0.10, -500.0, 500.0, status);
+  gMinuit->mnparm(3, "BenS", trackParam->GetBendingSlope(), 0.001, -0.5, 0.5, status);
+  gMinuit->mnparm(4, "InvBenP", trackParam->GetInverseBendingMomentum(), 0.003, -0.4, 0.4, status);
+  
+  // minimization
+  gMinuit->mnexcm("MIGRAD", arg, 0, status);
+  
+  // Calculate the covariance matrix more accurately if required
+  if (calcCov) gMinuit->mnexcm("HESSE", arg, 0, status);
+  
+  // get results into "invBenP", "benC", "nonBenC" ("x", "y")
+  gMinuit->GetParameter(0, x, errorParam);
+  trackParam->SetNonBendingCoor(x);
+  gMinuit->GetParameter(1, nonBenC, errorParam);
+  trackParam->SetNonBendingSlope(nonBenC);
+  gMinuit->GetParameter(2, y, errorParam);
+  trackParam->SetBendingCoor(y);
+  gMinuit->GetParameter(3, benC, errorParam);
+  trackParam->SetBendingSlope(benC);
+  gMinuit->GetParameter(4, invBenP, errorParam);
+  trackParam->SetInverseBendingMomentum(invBenP);
+  
+  // global result of the fit
+  gMinuit->mnstat(fitFMin, fedm, errdef, npari, nparx, covStatus);
+  track->SetFitFMin(fitFMin);
+  
+  // Get the covariance matrix if required
+  if (calcCov) {
+    // Covariance matrix according to HESSE status
+    // If problem then keep only the diagonal terms (variances)
+    Double_t matrix[5][5];
+    gMinuit->mnemat(&matrix[0][0],5);
+    if (covStatus == 3) trackParam->SetCovariances(matrix);
+    else trackParam->SetVariances(matrix);
+  } else *(trackParam->GetCovariances()) = 0;
+  
 }
 
   //__________________________________________________________________________
-void AliMUONTrackReconstructor::MakeTrackCandidates(void)
+void TrackChi2(Int_t & /*NParam*/, Double_t * /*Gradient*/, Double_t &Chi2, Double_t *Param, Int_t /*Flag*/)
 {
-  // To make track candidates
-  // with at least 3 aligned points in stations(1..) 4 and 5
-  // (two Segment's or one Segment and one HitForRec)
-  Int_t begStation, iBegSegment, nbCan1Seg1Hit, nbCan2Seg;
-  AliMUONSegment *begSegment;
-  AliDebug(1,"Enter MakeTrackCandidates");
-  // Loop over stations(1..) 5 and 4 for the beginning segment
-  for (begStation = 4; begStation > 2; begStation--) {
-    // Loop over segments in the beginning station
-    for (iBegSegment = 0; iBegSegment < fNSegments[begStation]; iBegSegment++) {
-      // pointer to segment
-      begSegment = (AliMUONSegment*) ((*fSegmentsPtr[begStation])[iBegSegment]);
-      AliDebug(2,Form("Look for TrackCandidate's with Segment %d  in Station(0..) %d", iBegSegment, begStation));
-      // Look for track candidates with two segments,
-      // "begSegment" and all compatible segments in other station.
-      // Only for beginning station(1..) 5
-      // because candidates with 2 segments have to looked for only once.
-      if (begStation == 4)
-       nbCan2Seg = MakeTrackCandidatesWithTwoSegments(begSegment);
-      // Look for track candidates with one segment and one point,
-      // "begSegment" and all compatible HitForRec's in other station.
-      // Only if "begSegment" does not belong already to a track candidate.
-      // Is that a too strong condition ????
-      if (!(begSegment->GetInTrack()))
-       nbCan1Seg1Hit = MakeTrackCandidatesWithOneSegmentAndOnePoint(begSegment);
-    } // for (iBegSegment = 0;...
-  } // for (begStation = 4;...
-  return;
+  /// Return the "Chi2" to be minimized with Minuit for track fitting,
+  /// with "NParam" parameters
+  /// and their current values in array pointed to by "Param".
+  /// Assumes that the track hits are sorted according to increasing Z.
+  /// Track parameters at each TrackHit are updated accordingly.
+  /// Multiple Coulomb scattering is not taken into account
+  
+  AliMUONTrack *trackBeingFitted = (AliMUONTrack*) gMinuit->GetObjectFit();
+//  AliMUONTrack *trackBeingFitted = (AliMUONTrack*) AliMUONTrackReconstructor::Fitter()->GetObjectFit();
+  AliMUONTrackParam param1;
+  AliMUONTrackParam* trackParamAtHit;
+  AliMUONHitForRec* hitForRec;
+  Chi2 = 0.0; // initialize Chi2
+  Double_t dX, dY;
+  
+  // copy of track parameters to be fitted
+  param1 = *((AliMUONTrackParam*) (trackBeingFitted->GetTrackParamAtHit()->First()));
+  param1.SetNonBendingCoor(Param[0]);
+  param1.SetNonBendingSlope(Param[1]);
+  param1.SetBendingCoor(Param[2]);
+  param1.SetBendingSlope(Param[3]);
+  param1.SetInverseBendingMomentum(Param[4]);
+  
+  // Take the vertex into account in the fit if required
+  if (trackBeingFitted->GetFitWithVertex()) {
+    AliMUONTrackParam paramAtVertex(param1);
+    AliMUONTrackExtrap::ExtrapToZ(&paramAtVertex, 0.);
+    AliMUONHitForRec *vertex = trackBeingFitted->GetVertex();
+    if (!vertex) {
+      cout<<"Error in TrackChi2: Want to use the vertex in tracking but it has not been created!!"<<endl;
+      exit(-1);
+    }
+    dX = vertex->GetNonBendingCoor() - paramAtVertex.GetNonBendingCoor();
+    dY = vertex->GetBendingCoor() - paramAtVertex.GetBendingCoor();
+    Chi2 += dX * dX / vertex->GetNonBendingReso2() + dY * dY / vertex->GetBendingReso2();
+  }
+  
+  // Follow track through all planes of track hits
+  trackParamAtHit = (AliMUONTrackParam*) (trackBeingFitted->GetTrackParamAtHit()->First());
+  while (trackParamAtHit) {
+    hitForRec = trackParamAtHit->GetHitForRecPtr();
+    // extrapolation to the plane of the hitForRec attached to the current trackParamAtHit
+    AliMUONTrackExtrap::ExtrapToZ(&param1, hitForRec->GetZ());
+    // update track parameters of the current hit
+    trackParamAtHit->SetTrackParam(param1);
+    // Increment Chi2
+    // done hit per hit, with hit resolution,
+    // and not with point and angle like in "reco_muon.F" !!!!
+    dX = hitForRec->GetNonBendingCoor() - param1.GetNonBendingCoor();
+    dY = hitForRec->GetBendingCoor() - param1.GetBendingCoor();
+    Chi2 = Chi2 + dX * dX / hitForRec->GetNonBendingReso2() + dY * dY / hitForRec->GetBendingReso2();
+    trackParamAtHit = (AliMUONTrackParam*) (trackBeingFitted->GetTrackParamAtHit()->After(trackParamAtHit));
+  }
 }
 
   //__________________________________________________________________________
-void AliMUONTrackReconstructor::FollowTracks(void)
+void TrackChi2MCS(Int_t & /*NParam*/, Double_t * /*Gradient*/, Double_t &Chi2, Double_t *Param, Int_t /*Flag*/)
 {
-  // Follow tracks in stations(1..) 3, 2 and 1
-  // too long: should be made more modular !!!!
-  AliMUONHitForRec *bestHit, *extrapHit, *hit;
-  AliMUONSegment *bestSegment, *extrapSegment, *segment;
-  AliMUONTrack *track, *nextTrack;
-  AliMUONTrackParam *trackParam1, trackParam[2], trackParamVertex;
-  // -1 to avoid compilation warnings
-  Int_t ch = -1, chInStation, chBestHit = -1, iHit, iSegment, station, trackIndex; 
-  Double_t bestChi2, chi2, dZ1, dZ2, dZ3, maxSigma2Distance, mcsFactor;
-  Double_t bendingMomentum, chi2Norm = 0.;
-
-
-  // local maxSigma2Distance, for easy increase in testing
-  maxSigma2Distance = fMaxSigma2Distance;
-  AliDebug(2,"Enter FollowTracks");
-  // Loop over track candidates
-  track = (AliMUONTrack*) fRecTracksPtr->First();
-  trackIndex = -1;
-  while (track) {
-    // Follow function for each track candidate ????
-    trackIndex++;
-    nextTrack = (AliMUONTrack*) fRecTracksPtr->After(track); // prepare next track
-    AliDebug(2,Form("FollowTracks: track candidate(0..): %d", trackIndex));
-    // Fit track candidate
-    track->SetFitMCS(0); // without multiple Coulomb scattering
-    track->SetFitNParam(3); // with 3 parameters (X = Y = 0)
-    track->SetFitStart(0); // from parameters at vertex
-    track->Fit();
-    if (AliLog::GetGlobalDebugLevel()> 2) {
-      cout << "FollowTracks: track candidate(0..): " << trackIndex
-          << " after fit in stations(0..) 3 and 4" << endl;
-      track->RecursiveDump();
+  /// Return the "Chi2" to be minimized with Minuit for track fitting,
+  /// with "NParam" parameters
+  /// and their current values in array pointed to by "Param".
+  /// Assumes that the track hits are sorted according to increasing Z.
+  /// Track parameters at each TrackHit are updated accordingly.
+  /// Multiple Coulomb scattering is taken into account with covariance matrix.
+  
+  AliMUONTrack *trackBeingFitted = (AliMUONTrack*) gMinuit->GetObjectFit();
+//  AliMUONTrack *trackBeingFitted = (AliMUONTrack*) AliMUONTrackReconstructor::Fitter()->GetObjectFit();
+  AliMUONTrackParam param1;
+  AliMUONTrackParam* trackParamAtHit;
+  AliMUONHitForRec* hitForRec;
+  Chi2 = 0.0; // initialize Chi2
+  Int_t chCurrent, chPrev = 0, hitNumber, hitNumber1, hitNumber2, hitNumber3;
+  Double_t z1, z2, z3;
+  AliMUONTrackParam *trackParamAtHit1, *trackParamAtHit2, *trackParamAtHit3;
+  AliMUONHitForRec *hitForRec1, *hitForRec2;
+  Double_t hbc1, hbc2, pbc1, pbc2;
+  Double_t hnbc1, hnbc2, pnbc1, pnbc2;
+  Int_t numberOfHit = trackBeingFitted->GetNTrackHits();
+  TMatrixD *covBending = new TMatrixD(numberOfHit, numberOfHit);
+  TMatrixD *covNonBending = new TMatrixD(numberOfHit, numberOfHit);
+  Double_t *msa2 = new Double_t[numberOfHit];
+  
+  // copy of track parameters to be fitted
+  param1 = *((AliMUONTrackParam*) (trackBeingFitted->GetTrackParamAtHit()->First()));
+  param1.SetNonBendingCoor(Param[0]);
+  param1.SetNonBendingSlope(Param[1]);
+  param1.SetBendingCoor(Param[2]);
+  param1.SetBendingSlope(Param[3]);
+  param1.SetInverseBendingMomentum(Param[4]);
+
+  // Take the vertex into account in the fit if required
+  if (trackBeingFitted->GetFitWithVertex()) {
+    AliMUONTrackParam paramAtVertex(param1);
+    AliMUONTrackExtrap::ExtrapToZ(&paramAtVertex, 0.);
+    AliMUONHitForRec *vertex = trackBeingFitted->GetVertex();
+    if (!vertex) {
+      cout<<"Error in TrackChi2MCS: Want to use the vertex in tracking but it has not been created!!"<<endl;
+      exit(-1);
     }
-    // Loop over stations(1..) 3, 2 and 1
-    // something SPECIAL for stations 2 and 1 for majority 3 coincidence ????
-    // otherwise: majority coincidence 2 !!!!
-    for (station = 2; station >= 0; station--) {
-      // Track parameters at first track hit (smallest Z)
-      trackParam1 = ((AliMUONTrackHit*)
-                    (track->GetTrackHitsPtr()->First()))->GetTrackParam();
-      // extrapolation to station
-      trackParam1->ExtrapToStation(station, trackParam);
-      extrapSegment = new AliMUONSegment(); //  empty segment
-      // multiple scattering factor corresponding to one chamber
-      // and momentum in bending plane (not total)
-      mcsFactor = 0.0136 * trackParam1->GetInverseBendingMomentum();
-      mcsFactor        = fChamberThicknessInX0 * mcsFactor * mcsFactor;
-      // Z difference from previous station
-      dZ1 = AliMUONConstants::DefaultChamberZ(2 * station) -
-           AliMUONConstants::DefaultChamberZ(2 * station + 2);
-      // Z difference between the two previous stations
-      dZ2 = AliMUONConstants::DefaultChamberZ(2 * station + 2) -
-           AliMUONConstants::DefaultChamberZ(2 * station + 4);
-      // Z difference between the two chambers in the previous station
-      dZ3 = AliMUONConstants::DefaultChamberZ(2 * station) -
-           AliMUONConstants::DefaultChamberZ(2 * station + 1);
-      extrapSegment->SetBendingCoorReso2(fBendingResolution * fBendingResolution);
-      extrapSegment->
-       SetNonBendingCoorReso2(fNonBendingResolution * fNonBendingResolution);
-      extrapSegment->UpdateFromStationTrackParam
-       (trackParam, mcsFactor, dZ1, dZ2, dZ3, station,
-        trackParam1->GetInverseBendingMomentum());
-      bestChi2 = 5.0;
-      bestSegment = NULL;
-      if (AliLog::GetGlobalDebugLevel() > 2) {
-       cout << "FollowTracks: track candidate(0..): " << trackIndex
-            << " Look for segment in station(0..): " << station << endl;
-      }
+    Double_t dX = vertex->GetNonBendingCoor() - paramAtVertex.GetNonBendingCoor();
+    Double_t dY = vertex->GetBendingCoor() - paramAtVertex.GetBendingCoor();
+    Chi2 += dX * dX / vertex->GetNonBendingReso2() + dY * dY / vertex->GetBendingReso2();
+  }
+  
+  // Predicted coordinates and multiple scattering angles are first calculated
+  for (hitNumber = 0; hitNumber < numberOfHit; hitNumber++) {
+    trackParamAtHit = (AliMUONTrackParam*) (trackBeingFitted->GetTrackParamAtHit()->UncheckedAt(hitNumber));
+    hitForRec = trackParamAtHit->GetHitForRecPtr();
+    // extrapolation to the plane of the hitForRec attached to the current trackParamAtHit
+    AliMUONTrackExtrap::ExtrapToZ(&param1, hitForRec->GetZ());
+    // update track parameters of the current hit
+    trackParamAtHit->SetTrackParam(param1);
+    // square of multiple scattering angle at current hit, with one chamber
+    msa2[hitNumber] = MultipleScatteringAngle2(&param1);
+    // correction for eventual missing hits or multiple hits in a chamber,
+    // according to the number of chambers
+    // between the current hit and the previous one
+    chCurrent = hitForRec->GetChamberNumber();
+    if (hitNumber > 0) msa2[hitNumber] = msa2[hitNumber] * (chCurrent - chPrev);
+    chPrev = chCurrent;
+  }
 
-      // Loop over segments in station
-      for (iSegment = 0; iSegment < fNSegments[station]; iSegment++) {
-       // Look for best compatible Segment in station
-       // should consider all possibilities ????
-       // multiple scattering ????
-       // separation in 2 functions: Segment and HitForRec ????
-       segment = (AliMUONSegment*) ((*fSegmentsPtr[station])[iSegment]);
-       // correction of corrected segment (fBendingCoor and fNonBendingCoor)
-       // according to real Z value of "segment" and slopes of "extrapSegment"
-       (&(trackParam[0]))->ExtrapToZ(segment->GetZ());
-       (&(trackParam[1]))->ExtrapToZ(segment->GetZ());
-       extrapSegment->SetBendingCoor((&(trackParam[0]))->GetBendingCoor());
-       extrapSegment->SetNonBendingCoor((&(trackParam[0]))->GetNonBendingCoor());
-       extrapSegment->SetBendingSlope((&(trackParam[0]))->GetBendingSlope());
-       extrapSegment->SetNonBendingSlope((&(trackParam[0]))->GetNonBendingSlope());
-       chi2 = segment->
-         NormalizedChi2WithSegment(extrapSegment, maxSigma2Distance);
-       if (chi2 < bestChi2) {
-         // update best Chi2 and Segment if better found
-         bestSegment = segment;
-         bestChi2 = chi2;
-       }
+  // Calculates the covariance matrix
+  for (hitNumber1 = 0; hitNumber1 < numberOfHit; hitNumber1++) { 
+    trackParamAtHit1 = (AliMUONTrackParam*) (trackBeingFitted->GetTrackParamAtHit()->UncheckedAt(hitNumber1));
+    hitForRec1 = trackParamAtHit1->GetHitForRecPtr();
+    z1 = hitForRec1->GetZ();
+    for (hitNumber2 = hitNumber1; hitNumber2 < numberOfHit; hitNumber2++) {
+      trackParamAtHit2 = (AliMUONTrackParam*) (trackBeingFitted->GetTrackParamAtHit()->UncheckedAt(hitNumber2));
+      z2 = trackParamAtHit2->GetHitForRecPtr()->GetZ();
+      // initialization to 0 (diagonal plus upper triangular part)
+      (*covBending)(hitNumber2, hitNumber1) = 0.0;
+      // contribution from multiple scattering in bending plane:
+      // loop over upstream hits
+      for (hitNumber3 = 0; hitNumber3 < hitNumber1; hitNumber3++) {    
+        trackParamAtHit3 = (AliMUONTrackParam*) (trackBeingFitted->GetTrackParamAtHit()->UncheckedAt(hitNumber3));
+       z3 = trackParamAtHit3->GetHitForRecPtr()->GetZ();
+       (*covBending)(hitNumber2, hitNumber1) = (*covBending)(hitNumber2, hitNumber1) + ((z1 - z3) * (z2 - z3) * msa2[hitNumber3]); 
       }
-      if (bestSegment) {
-       // best segment found: add it to track candidate
-       (&(trackParam[0]))->ExtrapToZ(bestSegment->GetZ());
-       (&(trackParam[1]))->ExtrapToZ(bestSegment->GetZ());
-       track->AddSegment(bestSegment);
-       // set track parameters at these two TrakHit's
-       track->SetTrackParamAtHit(track->GetNTrackHits() - 2, &(trackParam[0]));
-       track->SetTrackParamAtHit(track->GetNTrackHits() - 1, &(trackParam[1]));
-       AliDebug(3, Form("FollowTracks: track candidate(0..): %d  Added segment in station(0..): %d", trackIndex, station));
-       if (AliLog::GetGlobalDebugLevel()>2) track->RecursiveDump();
-      }
-      else {
-       // No best segment found:
-       // Look for best compatible HitForRec in station:
-       // should consider all possibilities ????
-       // multiple scattering ???? do about like for extrapSegment !!!!
-       extrapHit = new AliMUONHitForRec(); //  empty hit
-       bestChi2 = 3.0;
-       bestHit = NULL;
-       AliDebug(3, Form("FollowTracks: track candidate(0..): %d Segment not found, look for hit in station(0..): %d ", 
-                        trackIndex, station));
-       
-       // Loop over chambers of the station
-       for (chInStation = 0; chInStation < 2; chInStation++) {
-         ch = 2 * station + chInStation;
-         for (iHit = fIndexOfFirstHitForRecPerChamber[ch];
-              iHit < fIndexOfFirstHitForRecPerChamber[ch] +
-                fNHitsForRecPerChamber[ch];
-              iHit++) {
-           hit = (AliMUONHitForRec*) ((*fHitsForRecPtr)[iHit]);
-           // coordinates of extrapolated hit
-           (&(trackParam[chInStation]))->ExtrapToZ(hit->GetZ());
-           extrapHit->
-             SetBendingCoor((&(trackParam[chInStation]))->GetBendingCoor());
-           extrapHit->
-             SetNonBendingCoor((&(trackParam[chInStation]))->GetNonBendingCoor());
-           // resolutions from "extrapSegment"
-           extrapHit->SetBendingReso2(extrapSegment->GetBendingCoorReso2());
-           extrapHit->SetNonBendingReso2(extrapSegment->GetNonBendingCoorReso2());
-           // Loop over hits in the chamber
-           // condition for hit not already in segment ????
-           chi2 = hit->NormalizedChi2WithHitForRec(extrapHit, maxSigma2Distance);
-           if (chi2 < bestChi2) {
-             // update best Chi2 and HitForRec if better found
-             bestHit = hit;
-             bestChi2 = chi2;
-             chBestHit = chInStation;
-           }
-         }
-       }
-       if (bestHit) {
-         // best hit found: add it to track candidate
-         (&(trackParam[chBestHit]))->ExtrapToZ(bestHit->GetZ());
-         track->AddHitForRec(bestHit);
-         // set track parameters at this TrackHit
-         track->SetTrackParamAtHit(track->GetNTrackHits() - 1,
-                                   &(trackParam[chBestHit]));
-         if (AliLog::GetGlobalDebugLevel() > 2) {
-           cout << "FollowTracks: track candidate(0..): " << trackIndex
-                << " Added hit in station(0..): " << station << endl;
-           track->RecursiveDump();
-         }
-       }
-       else {
-         // Remove current track candidate
-         // and corresponding TrackHit's, ...
-         track->Remove();
-         delete extrapSegment;
-         delete extrapHit;
-         break; // stop the search for this candidate:
-         // exit from the loop over station
-       }
-       delete extrapHit;
-      }
-      delete extrapSegment;
-      // Sort track hits according to increasing Z
-      track->GetTrackHitsPtr()->Sort();
-      // Update track parameters at first track hit (smallest Z)
-      trackParam1 = ((AliMUONTrackHit*)
-                    (track->GetTrackHitsPtr()->First()))->GetTrackParam();
-      bendingMomentum = 0.;
-      if (TMath::Abs(trackParam1->GetInverseBendingMomentum()) > 0.)
-       bendingMomentum = TMath::Abs(1/(trackParam1->GetInverseBendingMomentum()));
-      // Track removed if bendingMomentum not in window [min, max]
-      if ((bendingMomentum < fMinBendingMomentum) || (bendingMomentum > fMaxBendingMomentum)) {
-       track->Remove();
-       break; // stop the search for this candidate:
-       // exit from the loop over station 
-      }
-      // Track fit
-      // with multiple Coulomb scattering if all stations
-      if (station == 0) track->SetFitMCS(1);
-      // without multiple Coulomb scattering if not all stations
-      else track->SetFitMCS(0);
-      track->SetFitNParam(5);  // with 5 parameters (momentum and position)
-      track->SetFitStart(1);  // from parameters at first hit
-      track->Fit();
-      Double_t numberOfDegFree = (2.0 * track->GetNTrackHits() - 5);
-      if (numberOfDegFree > 0) {
-        chi2Norm =  track->GetFitFMin() / numberOfDegFree;
+      // equal contribution from multiple scattering in non bending plane
+      (*covNonBending)(hitNumber2, hitNumber1) = (*covBending)(hitNumber2, hitNumber1);
+      if (hitNumber1 == hitNumber2) {
+       // Diagonal elements: add contribution from position measurements
+       // in bending plane
+       (*covBending)(hitNumber2, hitNumber1) = (*covBending)(hitNumber2, hitNumber1) + hitForRec1->GetBendingReso2();
+       // and in non bending plane
+       (*covNonBending)(hitNumber2, hitNumber1) = (*covNonBending)(hitNumber2, hitNumber1) + hitForRec1->GetNonBendingReso2();
       } else {
-       chi2Norm = 1.e10;
+       // Non diagonal elements: symmetrization
+       // for bending plane
+       (*covBending)(hitNumber1, hitNumber2) = (*covBending)(hitNumber2, hitNumber1);
+       // and non bending plane
+       (*covNonBending)(hitNumber1, hitNumber2) = (*covNonBending)(hitNumber2, hitNumber1);
       }
-      // Track removed if normalized chi2 too high
-      if (chi2Norm > fMaxChi2) {
-       track->Remove();
-       break; // stop the search for this candidate:
-       // exit from the loop over station 
-      }
-      if (AliLog::GetGlobalDebugLevel() > 2) {
-       cout << "FollowTracks: track candidate(0..): " << trackIndex
-            << " after fit from station(0..): " << station << " to 4" << endl;
-       track->RecursiveDump();
-      }
-      // Track extrapolation to the vertex through the absorber (Branson)
-      // after going through the first station
-      if (station == 0) {
-       trackParamVertex = *trackParam1;
-       (&trackParamVertex)->ExtrapToVertex(0.,0.,0.);
-       track->SetTrackParamAtVertex(&trackParamVertex);
-       if (AliLog::GetGlobalDebugLevel() > 0) {
-         cout << "FollowTracks: track candidate(0..): " << trackIndex
-              << " after extrapolation to vertex" << endl;
-         track->RecursiveDump();
-       }
+    } // for (hitNumber2 = hitNumber1;...
+  } // for (hitNumber1 = 0;...
+    
+  // Inversion of covariance matrices
+  Int_t ifailBending;
+  gMinuit->mnvert(&((*covBending)(0,0)), numberOfHit, numberOfHit, numberOfHit, ifailBending);
+  Int_t ifailNonBending;
+  gMinuit->mnvert(&((*covNonBending)(0,0)), numberOfHit, numberOfHit, numberOfHit, ifailNonBending);
+
+  // It would be worth trying to calculate the inverse of the covariance matrix
+  // only once per fit, since it cannot change much in principle,
+  // and it would save a lot of computing time !!!!
+  
+  // Calculates Chi2
+  if ((ifailBending == 0) && (ifailNonBending == 0)) {
+    // with Multiple Scattering if inversion correct
+    for (hitNumber1 = 0; hitNumber1 < numberOfHit ; hitNumber1++) { 
+      trackParamAtHit1 = (AliMUONTrackParam*) (trackBeingFitted->GetTrackParamAtHit()->UncheckedAt(hitNumber1));
+      hitForRec1 = trackParamAtHit1->GetHitForRecPtr();
+      hbc1 = hitForRec1->GetBendingCoor();
+      pbc1 = trackParamAtHit1->GetBendingCoor();
+      hnbc1 = hitForRec1->GetNonBendingCoor();
+      pnbc1 = trackParamAtHit1->GetNonBendingCoor();
+      for (hitNumber2 = 0; hitNumber2 < numberOfHit; hitNumber2++) {
+       trackParamAtHit2 = (AliMUONTrackParam*) (trackBeingFitted->GetTrackParamAtHit()->UncheckedAt(hitNumber2));
+        hitForRec2 = trackParamAtHit2->GetHitForRecPtr();
+       hbc2 = hitForRec2->GetBendingCoor();
+       pbc2 = trackParamAtHit2->GetBendingCoor();
+       hnbc2 = hitForRec2->GetNonBendingCoor();
+       pnbc2 = trackParamAtHit2->GetNonBendingCoor();
+       Chi2 += ((*covBending)(hitNumber2, hitNumber1) * (hbc1 - pbc1) * (hbc2 - pbc2)) +
+               ((*covNonBending)(hitNumber2, hitNumber1) * (hnbc1 - pnbc1) * (hnbc2 - pnbc2));
       }
-    } // for (station = 2;...
-    // go really to next track
-    track = nextTrack;
-  } // while (track)
-  // Compression of track array (necessary after Remove ????)
-  fRecTracksPtr->Compress();
-  return;
+    }
+  } else {
+    // without Multiple Scattering if inversion impossible
+    for (hitNumber1 = 0; hitNumber1 < numberOfHit ; hitNumber1++) { 
+      trackParamAtHit1 = (AliMUONTrackParam*) (trackBeingFitted->GetTrackParamAtHit()->UncheckedAt(hitNumber1));
+      hitForRec1 = trackParamAtHit1->GetHitForRecPtr();
+      hbc1 = hitForRec1->GetBendingCoor();
+      pbc1 = trackParamAtHit1->GetBendingCoor();
+      hnbc1 = hitForRec1->GetNonBendingCoor();
+      pnbc1 = trackParamAtHit1->GetNonBendingCoor();
+      Chi2 += ((hbc1 - pbc1) * (hbc1 - pbc1) / hitForRec1->GetBendingReso2()) +
+             ((hnbc1 - pnbc1) * (hnbc1 - pnbc1) / hitForRec1->GetNonBendingReso2());
+    }
+  }
+  
+  delete covBending;
+  delete covNonBending;
+  delete [] msa2;
 }
 
   //__________________________________________________________________________
-void AliMUONTrackReconstructor::RemoveDoubleTracks(void)
+Double_t MultipleScatteringAngle2(AliMUONTrackParam *param)
 {
-  // To remove double tracks.
-  // Tracks are considered identical
-  // if they have at least half of their hits in common.
-  // Among two identical tracks, one keeps the track with the larger number of hits
-  // or, if these numbers are equal, the track with the minimum Chi2.
-  AliMUONTrack *track1, *track2, *trackToRemove;
-  Bool_t identicalTracks;
-  Int_t hitsInCommon, nHits1, nHits2;
-  identicalTracks = kTRUE;
-  while (identicalTracks) {
-    identicalTracks = kFALSE;
-    // Loop over first track of the pair
-    track1 = (AliMUONTrack*) fRecTracksPtr->First();
-    while (track1 && (!identicalTracks)) {
-      nHits1 = track1->GetNTrackHits();
-      // Loop over second track of the pair
-      track2 = (AliMUONTrack*) fRecTracksPtr->After(track1);
-      while (track2 && (!identicalTracks)) {
-       nHits2 = track2->GetNTrackHits();
-       // number of hits in common between two tracks
-       hitsInCommon = track1->HitsInCommon(track2);
-       // check for identical tracks
-       if ((4 * hitsInCommon) >= (nHits1 + nHits2)) {
-         identicalTracks = kTRUE;
-         // decide which track to remove
-         if (nHits1 > nHits2) trackToRemove = track2;
-         else if (nHits1 < nHits2) trackToRemove = track1;
-         else if ((track1->GetFitFMin()) < (track2->GetFitFMin()))
-           trackToRemove = track2;
-         else trackToRemove = track1;
-         // remove it
-         trackToRemove->Remove();
-       }
-       track2 = (AliMUONTrack*) fRecTracksPtr->After(track2);
-      } // track2
-      track1 = (AliMUONTrack*) fRecTracksPtr->After(track1);
-    } // track1
-  }
-  return;
+  /// Returns square of multiple Coulomb scattering angle
+  /// from TrackParamAtHit pointed to by "param"
+  Double_t slopeBending, slopeNonBending, radiationLength, inverseBendingMomentum2, inverseTotalMomentum2;
+  Double_t varMultipleScatteringAngle;
+  slopeBending = param->GetBendingSlope();
+  slopeNonBending = param->GetNonBendingSlope();
+  // thickness in radiation length for the current track,
+  // taking local angle into account
+  radiationLength = AliMUONConstants::ChamberThicknessInX0() *
+                   TMath::Sqrt(1.0 + slopeBending*slopeBending + slopeNonBending*slopeNonBending);
+  inverseBendingMomentum2 =  param->GetInverseBendingMomentum() * param->GetInverseBendingMomentum();
+  inverseTotalMomentum2 = inverseBendingMomentum2 * (1.0 + slopeBending * slopeBending) /
+                         (1.0 + slopeBending *slopeBending + slopeNonBending * slopeNonBending); 
+  varMultipleScatteringAngle = 0.0136 * (1.0 + 0.038 * TMath::Log(radiationLength));
+  // The velocity is assumed to be 1 !!!!
+  varMultipleScatteringAngle = inverseTotalMomentum2 * radiationLength * varMultipleScatteringAngle * varMultipleScatteringAngle;
+  return varMultipleScatteringAngle;
 }
 
   //__________________________________________________________________________
-void AliMUONTrackReconstructor::UpdateTrackParamAtHit()
+void AliMUONTrackReconstructor::ExtrapTracksToVertex()
 {
-  // Set track parameters after track fitting. Fill fTrackParamAtHit of AliMUONTrack's
+  /// propagate tracks to the vertex through the absorber (Branson)
   AliMUONTrack *track;
-  AliMUONTrackHit *trackHit;
-  AliMUONTrackParam *trackParam;
-  track = (AliMUONTrack*) fRecTracksPtr->First();
-  while (track) {
-    trackHit = (AliMUONTrackHit*) (track->GetTrackHitsPtr())->First();
-    while (trackHit) {
-      trackParam = trackHit->GetTrackParam();
-      track->AddTrackParamAtHit(trackParam);
-      trackHit = (AliMUONTrackHit*) (track->GetTrackHitsPtr())->After(trackHit); 
-    } // trackHit    
-    track = (AliMUONTrack*) fRecTracksPtr->After(track);
-  } // track
-  return;
+  AliMUONTrackParam trackParamVertex;
+  AliMUONHitForRec *vertex;
+  Double_t vX, vY, vZ;
+  
+  for (Int_t iRecTrack = 0; iRecTrack <fNRecTracks; iRecTrack++) {
+    track = (AliMUONTrack*) fRecTracksPtr->UncheckedAt(iRecTrack);
+    trackParamVertex = *((AliMUONTrackParam*)(track->GetTrackParamAtHit()->First()));
+    vertex = track->GetVertex();
+    if (vertex) { // if track as a vertex defined, use it
+      vX = vertex->GetNonBendingCoor();
+      vY = vertex->GetBendingCoor();
+      vZ = vertex->GetZ();
+    } else { // else vertex = (0.,0.,0.)
+      vX = 0.;
+      vY = 0.;
+      vZ = 0.;
+    }
+    AliMUONTrackExtrap::ExtrapToVertex(&trackParamVertex, vX, vY, vZ);
+    track->SetTrackParamAtVertex(&trackParamVertex);
+    
+    if (AliLog::GetGlobalDebugLevel() > 0) {
+      cout << "FollowTracks: track candidate(0..): " << iRecTrack
+          << " after extrapolation to vertex" << endl;
+      track->RecursiveDump();
+    }
+  }
+  
 }
 
   //__________________________________________________________________________
-void AliMUONTrackReconstructor::UpdateHitForRecAtHit()
+void AliMUONTrackReconstructor::FillMUONTrack()
 {
-  // Set cluster parameterss after track fitting. Fill fHitForRecAtHit of AliMUONTrack's
+  /// Fill fHitForRecAtHit of AliMUONTrack's
   AliMUONTrack *track;
-  AliMUONTrackHit *trackHit;
-  AliMUONHitForRec *hitForRec;
+  AliMUONTrackParam *trackParamAtHit;
   track = (AliMUONTrack*) fRecTracksPtr->First();
   while (track) {
-    trackHit = (AliMUONTrackHit*) (track->GetTrackHitsPtr())->First();
-    while (trackHit) {
-      hitForRec = trackHit->GetHitForRecPtr();
-      track->AddHitForRecAtHit(hitForRec);
-      trackHit = (AliMUONTrackHit*) (track->GetTrackHitsPtr())->After(trackHit); 
-    } // trackHit    
+    trackParamAtHit = (AliMUONTrackParam*) (track->GetTrackParamAtHit()->First());
+    while (trackParamAtHit) {
+      track->AddHitForRecAtHit(trackParamAtHit->GetHitForRecPtr());
+      trackParamAtHit = (AliMUONTrackParam*) (track->GetTrackParamAtHit()->After(trackParamAtHit)); 
+    }
     track = (AliMUONTrack*) fRecTracksPtr->After(track);
-  } // track
-  return;
-}
-
-  //__________________________________________________________________________
-void AliMUONTrackReconstructor::FillMUONTrack()
-{
-  // Set track parameters at hits for Kalman track. Fill fTrackParamAtHit of AliMUONTrack's
-  AliMUONTrackK *track;
-  track = (AliMUONTrackK*) fRecTracksPtr->First();
-  while (track) {
-    track->FillMUONTrack();
-    track = (AliMUONTrackK*) fRecTracksPtr->After(track);
-  } 
+  }
   return;
 }
 
   //__________________________________________________________________________
 void AliMUONTrackReconstructor::EventDump(void)
 {
-  // Dump reconstructed event (track parameters at vertex and at first hit),
-  // and the particle parameters
-
+  /// Dump reconstructed event (track parameters at vertex and at first hit),
+  /// and the particle parameters
   AliMUONTrack *track;
   AliMUONTrackParam *trackParam, *trackParam1;
   Double_t bendingSlope, nonBendingSlope, pYZ;
@@ -1188,7 +1005,6 @@ void AliMUONTrackReconstructor::EventDump(void)
   fRecTracksPtr->Compress(); // for simple loop without "Next" since no hole
   // Loop over reconstructed tracks
   for (trackIndex = 0; trackIndex < fNRecTracks; trackIndex++) {
-    if (fTrackMethod != 1) continue; //AZ - skip the rest for now
     AliDebug(1, Form("track number: %d", trackIndex));
     // function for each track for modularity ????
     track = (AliMUONTrack*) ((*fRecTracksPtr)[trackIndex]);
@@ -1210,8 +1026,7 @@ void AliMUONTrackReconstructor::EventDump(void)
                     z, x, y, pX, pY, pZ, c));
 
     // track parameters at first hit
-    trackParam1 = ((AliMUONTrackHit*)
-                  (track->GetTrackHitsPtr()->First()))->GetTrackParam();
+    trackParam1 = (AliMUONTrackParam*) track->GetTrackParamAtHit()->First();
     x = trackParam1->GetNonBendingCoor();
     y = trackParam1->GetBendingCoor();
     z = trackParam1->GetZ();
@@ -1236,280 +1051,3 @@ void AliMUONTrackReconstructor::EventDump(void)
 }
 
 
-//__________________________________________________________________________
-void AliMUONTrackReconstructor::EventDumpTrigger(void)
-{
-  // Dump reconstructed trigger event 
-  // and the particle parameters
-    
-  AliMUONTriggerTrack *triggertrack ;
-  Int_t nTriggerTracks = fMUONData->RecTriggerTracks()->GetEntriesFast();
-  AliDebug(1, "****** enter EventDumpTrigger ******");
-  AliDebug(1, Form("Number of Reconstructed tracks : %d ",  nTriggerTracks));
-  
-  // Loop over reconstructed tracks
-  for (Int_t trackIndex = 0; trackIndex < nTriggerTracks; trackIndex++) {
-    triggertrack = (AliMUONTriggerTrack*)fMUONData->RecTriggerTracks()->At(trackIndex);
-      printf(" trigger track number %i x11=%f y11=%f thetax=%f thetay=%f \n",
-            trackIndex,
-            triggertrack->GetX11(),triggertrack->GetY11(),
-            triggertrack->GetThetax(),triggertrack->GetThetay());      
-  } 
-}
-
-//__________________________________________________________________________
-void AliMUONTrackReconstructor::MakeTrackCandidatesK(void)
-{
-  // To make initial tracks for Kalman filter from the list of segments
-  Int_t istat, iseg;
-  AliMUONSegment *segment;
-  AliMUONTrackK *trackK;
-
-  AliDebug(1,"Enter MakeTrackCandidatesK");
-
-  AliMUONTrackK a(this, fHitsForRecPtr);
-  // Loop over stations(1...) 5 and 4
-  for (istat=4; istat>=3; istat--) {
-    // Loop over segments in the station
-    for (iseg=0; iseg<fNSegments[istat]; iseg++) {
-      // Transform segments to tracks and evaluate covariance matrix
-      segment = (AliMUONSegment*) ((*fSegmentsPtr[istat])[iseg]);
-      trackK = new ((*fRecTracksPtr)[fNRecTracks++]) AliMUONTrackK(segment);
-    } // for (iseg=0;...)
-  } // for (istat=4;...)
-  return;
-}
-
-//__________________________________________________________________________
-void AliMUONTrackReconstructor::FollowTracksK(void)
-{
-  // Follow tracks using Kalman filter
-  Bool_t ok;
-  Int_t icand, ichamBeg = 0, ichamEnd, chamBits;
-  Double_t zDipole1, zDipole2;
-  AliMUONTrackK *trackK;
-  AliMUONHitForRec *hit;
-  AliMUONRawCluster *clus;
-  TClonesArray *rawclusters;
-  clus = 0; rawclusters = 0;
-
-  zDipole1 = GetSimpleBPosition() + GetSimpleBLength()/2;
-  zDipole2 = zDipole1 - GetSimpleBLength();
-
-  // Print hits
-  trackK = (AliMUONTrackK*) ((*fRecTracksPtr)[0]);
-
-  if (trackK->DebugLevel() > 0) {
-    for (Int_t i1=0; i1<fNHitsForRec; i1++) {
-      hit = (AliMUONHitForRec*) ((*fHitsForRecPtr)[i1]);
-      printf(" Hit # %d %10.4f %10.4f %10.4f",
-             hit->GetChamberNumber(), hit->GetBendingCoor(),
-             hit->GetNonBendingCoor(), hit->GetZ());
-      // from raw clusters
-      rawclusters = fMUONData->RawClusters(hit->GetChamberNumber());
-      clus = (AliMUONRawCluster*) rawclusters->UncheckedAt(hit->
-                                                          GetHitNumber());
-      printf(" %d", clus->GetTrack(1));
-      if (clus->GetTrack(2) != -1) printf(" %d \n", clus->GetTrack(2));
-      else printf("\n");
-     
-    }
-  } // if (trackK->DebugLevel() > 0)
-
-  icand = -1;
-  Int_t nSeeds;
-  nSeeds = fNRecTracks; // starting number of seeds
-  // Loop over track candidates
-  while (icand < fNRecTracks-1) {
-    icand ++;
-    if (trackK->DebugLevel()>0) cout << " *** Kalman track candidate No. " << icand << endl;
-    trackK = (AliMUONTrackK*) ((*fRecTracksPtr)[icand]);
-    if (trackK->GetRecover() < 0) continue; // failed track
-
-    // Discard candidate which will produce the double track
-    /*
-    if (icand > 0) {
-      ok = CheckCandidateK(icand,nSeeds);
-      if (!ok) {
-        trackK->SetRecover(-1); // mark candidate to be removed
-        continue;
-      }
-    }
-    */
-
-    ok = kTRUE;
-    if (trackK->GetRecover() == 0) 
-      hit = (AliMUONHitForRec*) trackK->GetTrackHits()->Last(); // last hit
-    else 
-      hit = trackK->GetHitLastOk(); // hit where track stopped
-
-    if (hit) ichamBeg = hit->GetChamberNumber();
-    ichamEnd = 0;
-    // Check propagation direction
-    if (!hit) { ichamBeg = ichamEnd; AliFatal(" ??? "); }
-    else if (trackK->GetTrackDir() < 0) {
-      ichamEnd = 9; // forward propagation
-      ok = trackK->KalmanFilter(ichamBeg,ichamEnd,kFALSE,zDipole1,zDipole2);
-      if (ok) {
-        ichamBeg = ichamEnd;
-        ichamEnd = 6; // backward propagation
-       // Change weight matrix and zero fChi2 for backpropagation
-        trackK->StartBack();
-       trackK->SetTrackDir(1);
-        ok = trackK->KalmanFilter(ichamBeg,ichamEnd,kTRUE,zDipole1,zDipole2);
-        ichamBeg = ichamEnd;
-        ichamEnd = 0;
-      }
-    } else {
-      if (trackK->GetBPFlag()) {
-       // backpropagation
-        ichamEnd = 6; // backward propagation
-       // Change weight matrix and zero fChi2 for backpropagation
-        trackK->StartBack();
-        ok = trackK->KalmanFilter(ichamBeg,ichamEnd,kTRUE,zDipole1,zDipole2);
-        ichamBeg = ichamEnd;
-        ichamEnd = 0;
-      }
-    }
-
-    if (ok) {
-      trackK->SetTrackDir(1);
-      trackK->SetBPFlag(kFALSE);
-      ok = trackK->KalmanFilter(ichamBeg,ichamEnd,kFALSE,zDipole1,zDipole2);
-    }
-    if (!ok) { trackK->SetRecover(-1); continue; } // mark candidate to be removed
-
-    // Apply smoother
-    if (trackK->GetRecover() >= 0) {
-      ok = trackK->Smooth();
-      if (!ok) trackK->SetRecover(-1); // mark candidate to be removed
-    }
-
-    // Majority 3 of 4 in first 2 stations
-    if (!ok) continue;
-    chamBits = 0;
-    Double_t chi2max = 0;
-    for (Int_t i=0; i<trackK->GetNTrackHits(); i++) {
-      hit = (AliMUONHitForRec*) (*trackK->GetTrackHits())[i];
-      chamBits |= BIT(hit->GetChamberNumber());
-      if (trackK->GetChi2PerPoint(i) > chi2max) chi2max = trackK->GetChi2PerPoint(i);
-    }
-    if (!((chamBits&3)==3 || (chamBits>>2&3)==3) && chi2max > 25) {
-      //trackK->Recover();
-      trackK->SetRecover(-1); //mark candidate to be removed
-      continue;
-    }
-    if (ok) trackK->SetTrackQuality(0); // compute "track quality"
-  } // while
-
-  for (Int_t i=0; i<fNRecTracks; i++) {
-    trackK = (AliMUONTrackK*) ((*fRecTracksPtr)[i]);
-    if (trackK->GetRecover() < 0) fRecTracksPtr->RemoveAt(i);
-  }
-
-  // Compress TClonesArray
-  fRecTracksPtr->Compress();
-  fNRecTracks = fRecTracksPtr->GetEntriesFast();
-  return;
-}
-
-//__________________________________________________________________________
-Bool_t AliMUONTrackReconstructor::CheckCandidateK(Int_t icand, Int_t nSeeds) const
-{
-  // Discards track candidate if it will produce the double track (having
-  // the same seed segment hits as hits of a good track found before)
-  AliMUONTrackK *track1, *track2;
-  AliMUONHitForRec *hit1, *hit2, *hit;
-
-  track1 = (AliMUONTrackK*) ((*fRecTracksPtr)[icand]);
-  hit1 = (AliMUONHitForRec*) (*track1->GetTrackHits())[0]; // 1'st hit
-  hit2 = (AliMUONHitForRec*) (*track1->GetTrackHits())[1]; // 2'nd hit
-
-  for (Int_t i=0; i<icand; i++) {
-    track2 = (AliMUONTrackK*) ((*fRecTracksPtr)[i]);
-    //if (track2->GetRecover() < 0) continue;
-    if (track2->GetRecover() < 0 && icand >= nSeeds) continue;
-
-    if (track1->GetStartSegment() == track2->GetStartSegment()) {
-      return kFALSE;
-    } else {
-      Int_t nSame = 0;
-      for (Int_t j=0; j<track2->GetNTrackHits(); j++) {
-        hit = (AliMUONHitForRec*) (*track2->GetTrackHits())[j];
-        if (hit == hit1 || hit == hit2) {
-          nSame++;
-          if (nSame == 2) return kFALSE;
-        }
-      } // for (Int_t j=0;
-    }
-  } // for (Int_t i=0;
-  return kTRUE;
-}
-
-//__________________________________________________________________________
-void AliMUONTrackReconstructor::RemoveDoubleTracksK(void)
-{
-  // Removes double tracks (sharing more than half of their hits). Keeps
-  // the track with higher quality
-  AliMUONTrackK *track1, *track2, *trackToKill;
-
-  // Sort tracks according to their quality
-  fRecTracksPtr->Sort();
-
-  // Loop over first track of the pair
-  track1 = (AliMUONTrackK*) fRecTracksPtr->First();
-  Int_t debug = track1->DebugLevel();
-  while (track1) {
-    // Loop over second track of the pair
-    track2 = (AliMUONTrackK*) fRecTracksPtr->After(track1);
-    while (track2) {
-      // Check whether or not to keep track2
-      if (!track2->KeepTrack(track1)) {
-        if (debug >= 0) cout << " Killed track: " << 1/(*track2->GetTrackParameters())(4,0) <<
-         " " << track2->GetTrackQuality() << endl;
-        trackToKill = track2;
-        track2 = (AliMUONTrackK*) fRecTracksPtr->After(track2);
-        trackToKill->Kill();
-        fRecTracksPtr->Compress();
-      } else track2 = (AliMUONTrackK*) fRecTracksPtr->After(track2);
-    } // track2
-    track1 = (AliMUONTrackK*) fRecTracksPtr->After(track1);
-  } // track1
-
-  fNRecTracks = fRecTracksPtr->GetEntriesFast();
-  if (debug >= 0) cout << " Number of Kalman tracks: " << fNRecTracks << endl;
-}
-
-//__________________________________________________________________________
-void AliMUONTrackReconstructor::GoToVertex(void)
-{
-  // Propagates track to the vertex thru absorber
-  // (using Branson correction for now)
-
-  Double_t zVertex;
-  zVertex = 0;
-  for (Int_t i=0; i<fNRecTracks; i++) {
-    //((AliMUONTrackK*)(*fRecTracksPtr)[i])->Branson();
-    ((AliMUONTrackK*)(*fRecTracksPtr)[i])->SetTrackQuality(1); // compute Chi2
-    //((AliMUONTrackK*)(*fRecTracksPtr)[i])->GoToZ(zVertex); // w/out absorber
-    ((AliMUONTrackK*)(*fRecTracksPtr)[i])->GoToVertex(1); // with absorber
-  }
-}
-
-//__________________________________________________________________________
-void AliMUONTrackReconstructor::SetTrackMethod(Int_t iTrackMethod)
-{
-  // Set track method and recreate track container if necessary
-  
-  fTrackMethod = TMath::Min (iTrackMethod, 3);
-  fTrackMethod = TMath::Max (fTrackMethod, 1);
-  if (fTrackMethod != 1) {
-    if (fRecTracksPtr) delete fRecTracksPtr;
-    fRecTracksPtr = new TClonesArray("AliMUONTrackK", 10);
-    if (fTrackMethod == 2) cout << " *** Tracking with the Kalman filter *** " << endl;
-    else cout << " *** Combined cluster / track finder ***" << endl;
-  } else cout << " *** Original tracking *** " << endl;
-
-}