Re-establishing creation of RecPoints in TreeR (Laurent)
authorlaphecet <laphecet@f7af4fe6-9843-0410-8265-dc069ae4e863>
Sun, 30 Mar 2008 22:06:05 +0000 (22:06 +0000)
committerlaphecet <laphecet@f7af4fe6-9843-0410-8265-dc069ae4e863>
Sun, 30 Mar 2008 22:06:05 +0000 (22:06 +0000)
Introducing tracking mode starting from trigger tracks (Laurent)
New options for tracking and some bugs fixed (Philippe P.)

========================================================

New classes :

- AliMUONLegacyClusterServer (Laurent)

A cluster server which is doing no more than serving clusters from an existing cluster store. Used to re-establish clustering in local reconstruction (see AliMUONReconstructor's changes)

- AliMUONTriggerTrackToTrackerClusters (Laurent)

A class to replace clusters in stations 4 and 5 (that are discarded (if they exist)) by "fake" ones, created from the extrapolation of trigger tracks to st45.
Created to allow reconstruction of data taken during Feb. 08 cosmic run where st45 were not ready yet.

========================================================

 AliMUONReconstructor.cxx (Laurent)

        Re-establishing, in the case of non-combined tracking, the filling of the TreeR with        the clusters, i.e. clustering is done in local reconstruction in that case, and
        not in tracking phase.

 AliMUONClusterFinderMLEM.cxx (Laurent)

        Fixing a small memory leak

libMUONrec.pkg (Laurent)
MUONrecLinkDef.h

        Adding new classes

AliMUONClusterStoreV2.cxx (Laurent)

        Fixing a memory leak in ReMap

AliMUONRawClusterV2.cxx (Laurent)
AliMUONCluster.cxx

        Fixing errors found by valgrind

AliMUONSimpleClusterServer (Laurent)

        Changing ctor parameter from ref to pointer, as we're taking ownership of that
        object, and adding a method to find out in which DE a global (x,y) position is.

AliMUONVClusterServer.h (Laurent)

        Changing comment which did not follow interface change...

AliMUONTracker (Laurent)

        If no cluster server given, use legacy one (see also changes in AliMUONReconstructor)

 AliMUONRecoParam (Laurent & Philippe P.)

        New options

AliMUONRefitter (Laurent)

        Avoids code duplication and use new SimpleClusterServer interface.

AliMUON*Tracker* (Philippe P.)

        - solved the problem of divergence in the tracking of low momentum muons
        - added a reconstruction parameter defining the maximum non bending slope of the primary track candidates
        - added the possibility to disable one or more chambers in the reconstruction (new option)
        - added the possibility to reconstruct a track even if it has no cluster in one or more stations (new option)
        - added the possibility to make a primary track candidate starting from one cluster on station 4 and one on station 5 (new option)

32 files changed:
MUON/AliMUONCluster.cxx
MUON/AliMUONClusterFinderMLEM.cxx
MUON/AliMUONClusterStoreV2.cxx
MUON/AliMUONGeometryTransformer.cxx
MUON/AliMUONGeometryTransformer.h
MUON/AliMUONLegacyClusterServer.cxx [new file with mode: 0644]
MUON/AliMUONLegacyClusterServer.h [new file with mode: 0644]
MUON/AliMUONRawClusterV2.cxx
MUON/AliMUONRecoParam.cxx
MUON/AliMUONRecoParam.h
MUON/AliMUONReconstructor.cxx
MUON/AliMUONReconstructor.h
MUON/AliMUONRefitter.cxx
MUON/AliMUONSimpleClusterServer.cxx
MUON/AliMUONSimpleClusterServer.h
MUON/AliMUONTrack.cxx
MUON/AliMUONTrackExtrap.cxx
MUON/AliMUONTrackReconstructor.cxx
MUON/AliMUONTrackReconstructor.h
MUON/AliMUONTrackReconstructorK.cxx
MUON/AliMUONTrackReconstructorK.h
MUON/AliMUONTracker.cxx
MUON/AliMUONTracker.h
MUON/AliMUONTriggerTrackToTrackerClusters.cxx [new file with mode: 0644]
MUON/AliMUONTriggerTrackToTrackerClusters.h [new file with mode: 0644]
MUON/AliMUONVClusterServer.h
MUON/AliMUONVTrackReconstructor.cxx
MUON/AliMUONVTrackReconstructor.h
MUON/MUONefficiency.C
MUON/MUONrecLinkDef.h
MUON/libMUONrec.pkg
MUON/runReconstruction.C

index 3fb8fe5..642c462 100644 (file)
@@ -346,6 +346,7 @@ AliMUONCluster::Copy(TObject& obj) const
   ///
   TObject::Copy(obj);
   AliMUONCluster& dest = static_cast<AliMUONCluster&>(obj);
+  delete dest.fPads;
   dest.fPads = 0x0;
   if ( fPads )
   {
index c4142b0..24254a8 100644 (file)
@@ -161,16 +161,16 @@ AliMUONClusterFinderMLEM::NextCluster()
   // pre-cluster and treat it
 
   fPreCluster = fPreClusterFinder->NextCluster();
-  
+
+  fClusterList.Delete(); // reset the list of clusters for this pre-cluster
+  fClusterNumber = -1; //AZ
+    
   if (!fPreCluster)
   {
     // we are done
     return 0x0;
   }
     
-  fClusterList.Delete(); // reset the list of clusters for this pre-cluster
-  fClusterNumber = -1; //AZ
-  
   WorkOnPreCluster();
 
   // WorkOnPreCluster may have used only part of the pads, so we check that
index 9774a3e..aa0b9f3 100644 (file)
@@ -191,10 +191,15 @@ AliMUONVCluster* AliMUONClusterStoreV2::Remove(AliMUONVCluster& cluster)
   /// Remove a cluster
   AliMUONVCluster* c = static_cast<AliMUONVCluster*>(fClusters->Remove(&cluster));
   
-  if (c) {
+  if (c) 
+  {
     fClusters->Compress();
     fMapped = kFALSE;
   }
+  else
+  {
+    AliError("Could not remove cluster from array");
+  }
   
   return c;
 }
@@ -207,16 +212,24 @@ void AliMUONClusterStoreV2::ReMap()
   
   // Create (or clear) the TClonesArray of map
   Int_t nChamber = AliMpConstants::NofTrackingChambers();
-  if (!fMap) fMap = new TClonesArray("AliMpExMap",nChamber);
-  else fMap->Clear("C");
   
-  // Create one map per chamber
-  AliMpExMap *map;
-  for (Int_t chamber=0; chamber<nChamber; chamber++) {
-    map = new((*fMap)[chamber]) AliMpExMap(kTRUE);
-    map->SetOwner(kFALSE);
+  if (!fMap) {
+    fMap = new TClonesArray("AliMpExMap",nChamber);
+    
+    // Create one map per chamber
+    AliMpExMap *map;
+    for (Int_t chamber=0; chamber<nChamber; chamber++) {
+      map = new((*fMap)[chamber]) AliMpExMap(kTRUE);
+      map->SetOwner(kFALSE);
+    }
   }
-  
+  else {
+    for (Int_t chamber=0; chamber<nChamber; chamber++) {
+      AliMpExMap *map = static_cast<AliMpExMap *>(fMap->At(chamber));
+      map->Clear("C");
+    }
+  }  
+
   // Fill the maps
   TIter next(fClusters);
   AliMUONVCluster* cluster;
index 8adc968..0f81ee8 100644 (file)
 #include "AliMpConstants.h"
 #include "AliMpExMap.h"
 #include "AliMpCDB.h"
+#include "AliMpArea.h"
+#include <float.h>
+#include "AliMpVPadIterator.h"
+#include "AliMpPad.h"
+#include "AliMpDEIterator.h"
+#include <TVector2.h>
+#include "AliMpVSegmentation.h"
+#include "AliMpSegmentation.h"
 
 #include "AliLog.h"
 #include "AliAlignObjMatrix.h"
@@ -58,7 +66,8 @@ AliMUONGeometryTransformer::AliMUONGeometryTransformer()
   : TObject(),
     fDetectorName(fgkDefaultDetectorName),
     fModuleTransformers(0),
-    fMisAlignArray(0)
+    fMisAlignArray(0),
+    fDEAreas(0x0)
 {
 /// Standard constructor
 
@@ -72,7 +81,8 @@ AliMUONGeometryTransformer::AliMUONGeometryTransformer(TRootIOCtor* /*ioCtor*/)
   : TObject(),
     fDetectorName(),
     fModuleTransformers(0),
-    fMisAlignArray(0)
+    fMisAlignArray(0),
+    fDEAreas(0x0)
 {
 /// Default constructor
 } 
@@ -84,12 +94,104 @@ AliMUONGeometryTransformer::~AliMUONGeometryTransformer()
 
   delete fModuleTransformers;
   delete fMisAlignArray;
+  delete fDEAreas;
 }
 
 //
 // private methods
 //
 
+
+//_____________________________________________________________________________
+AliMpArea*
+AliMUONGeometryTransformer::GetDEArea(Int_t detElemId) const
+{
+  /// Get area (in global coordinates) covered by a given detection element
+  if (!fDEAreas)
+  {
+    CreateDEAreas();
+  }
+  return static_cast<AliMpArea*>(fDEAreas->GetValue(detElemId));
+}
+
+//_____________________________________________________________________________
+void
+AliMUONGeometryTransformer::CreateDEAreas() const
+{
+  /// Create DE areas
+  
+  fDEAreas = new AliMpExMap(true);
+  
+  AliMpDEIterator it;
+
+  it.First();
+
+  /// Generate the DE areas in global coordinates
+
+  while ( !it.IsDone() )
+  {
+    Int_t detElemId = it.CurrentDEId();
+    
+    if ( !HasDE(detElemId) ) continue;
+    
+    const AliMpVSegmentation* seg = AliMpSegmentation::Instance()->GetMpSegmentation(detElemId,AliMp::kCath0);
+    
+    Double_t xg,yg,zg;
+    
+    AliMp::StationType stationType = AliMpDEManager::GetStationType(detElemId);
+    
+    Double_t xl(0.0), yl(0.0), zl(0.0);
+    Double_t dx(seg->Dimensions().X());
+    Double_t dy(seg->Dimensions().Y());
+    
+    if ( stationType == AliMp::kStation1 || stationType == AliMp::kStation2 ) 
+    {
+      Double_t xmin(FLT_MAX);
+      Double_t xmax(-FLT_MAX);
+      Double_t ymin(FLT_MAX);
+      Double_t ymax(-FLT_MAX);
+      
+      for ( Int_t icathode = 0; icathode < 2; ++icathode ) 
+      {
+        const AliMpVSegmentation* cathode 
+        = AliMpSegmentation::Instance()->GetMpSegmentation(detElemId,AliMp::GetCathodType(icathode));
+        
+        AliMpVPadIterator* it = cathode->CreateIterator();
+        
+        it->First();
+        
+        while ( !it->IsDone() ) 
+        {
+          AliMpPad pad = it->CurrentItem();
+          AliMpArea a(pad.Position(),pad.Dimensions());
+          xmin = TMath::Min(xmin,a.LeftBorder());
+          xmax = TMath::Max(xmax,a.RightBorder());
+          ymin = TMath::Min(ymin,a.DownBorder());
+          ymax = TMath::Max(ymax,a.UpBorder());
+          it->Next();
+        }
+        
+        delete it;
+      }
+      
+      xl = (xmin+xmax)/2.0;
+      yl = (ymin+ymax)/2.0;
+      dx = (xmax-xmin)/2.0;
+      dy = (ymax-ymin)/2.0;
+      
+      Local2Global(detElemId,xl,yl,zl,xg,yg,zg);
+    }
+    else
+    {
+      Local2Global(detElemId,xl,yl,zl,xg,yg,zg);
+    }
+    
+    fDEAreas->Add(detElemId,new AliMpArea(TVector2(xg,yg),TVector2(dx,dy)));
+    
+    it.Next();
+  }
+}
+
 //_____________________________________________________________________________
 Bool_t AliMUONGeometryTransformer::LoadMapping() const
 {
index 07566ed..14a4f48 100644 (file)
@@ -30,6 +30,8 @@ class AliMUONGeometryDetElement;
 
 class TGeoManager;
 class TClonesArray;
+class AliMpExMap;
+class AliMpArea;
 
 class AliMUONGeometryTransformer : public TObject
 {
@@ -92,6 +94,8 @@ class AliMUONGeometryTransformer : public TObject
     
     Bool_t  HasDE(Int_t detElemId) const;
 
+    AliMpArea* GetDEArea(Int_t detElemId) const;
+    
   protected:
     /// Not implemented
     AliMUONGeometryTransformer(const AliMUONGeometryTransformer& right);
@@ -100,6 +104,9 @@ class AliMUONGeometryTransformer : public TObject
  
   private:
     // methods
+      
+      void CreateDEAreas() const;
+    
     Bool_t LoadMapping() const;
     AliMUONGeometryModuleTransformer* GetModuleTransformerNonConst(
                                     Int_t index, Bool_t warn = true) const;
@@ -138,8 +145,9 @@ class AliMUONGeometryTransformer : public TObject
     TString        fDetectorName;       ///< Detector name
     TObjArray*     fModuleTransformers; ///< array of module transformers
     TClonesArray*  fMisAlignArray;      ///< array of misalignment data
-
-  ClassDef(AliMUONGeometryTransformer,3)  // Geometry parametrisation
+    mutable AliMpExMap*    fDEAreas; ///< areas of detection elements in global coordinates
+    
+  ClassDef(AliMUONGeometryTransformer,4)  // Geometry parametrisation
 };
 
 // inline methods
diff --git a/MUON/AliMUONLegacyClusterServer.cxx b/MUON/AliMUONLegacyClusterServer.cxx
new file mode 100644 (file)
index 0000000..8ad26ba
--- /dev/null
@@ -0,0 +1,126 @@
+/**************************************************************************
+* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+*                                                                        *
+* Author: The ALICE Off-line Project.                                    *
+* Contributors are mentioned in the code where appropriate.              *
+*                                                                        *
+* Permission to use, copy, modify and distribute this software and its   *
+* documentation strictly for non-commercial purposes is hereby granted   *
+* without fee, provided that the above copyright notice appears in all   *
+* copies and that both the copyright notice and this permission notice   *
+* appear in the supporting documentation. The authors make no claims     *
+* about the suitability of this software for any purpose. It is          *
+* provided "as is" without express or implied warranty.                  *
+**************************************************************************/
+
+// $Id$
+
+/// \class AliMUONLegacyClusterServer
+///
+/// Special implementation of AliMUONVClusterServer, which will only return 
+/// clusters from a pre-defined cluster store.
+///
+/// Made to recover the old (i.e. before introduction of VClusterServer) behavior
+/// of the MUON recontruction where rec points were always written to TreeR, 
+/// and then the tracking picked them from that tree, in order to have the
+/// possibility to save full rec points (for debugging the spectro, mainly, should
+/// not be an option used during final production).
+///
+/// \author Laurent Aphecetche, Subatech
+///
+
+#include "AliMUONLegacyClusterServer.h"
+
+#include "AliCodeTimer.h"
+#include "AliLog.h"
+#include "AliMUONGeometryTransformer.h"
+#include "AliMUONTriggerTrackToTrackerClusters.h"
+#include "AliMUONVCluster.h"
+#include "AliMUONVClusterStore.h"
+#include "AliMpArea.h"
+#include <TCollection.h>
+
+/// \cond CLASSIMP
+ClassImp(AliMUONLegacyClusterServer)
+/// \endcond
+
+//_____________________________________________________________________________
+AliMUONLegacyClusterServer::AliMUONLegacyClusterServer(const AliMUONGeometryTransformer& transformer, AliMUONVClusterStore* store)
+: AliMUONVClusterServer(), fTransformer(transformer), fClusterStore(store), fTriggerTrackStore(0x0),
+fBypass(0x0)
+{
+  /// ctor. Mode Read : we'll only server clusters from existing store
+}
+
+//_____________________________________________________________________________
+AliMUONLegacyClusterServer::~AliMUONLegacyClusterServer()
+{
+  /// dtor
+  delete fBypass;
+}
+
+//_____________________________________________________________________________
+Int_t 
+AliMUONLegacyClusterServer::Clusterize(Int_t chamberId, 
+                                       AliMUONVClusterStore& clusterStore,
+                                       const AliMpArea& /*area*/)
+{
+  /// Fills clusterStore with clusters in given chamber
+  ///
+  /// Return the number of clusters added to clusterStore
+  
+  AliCodeTimerAuto(Form("Chamber %d",chamberId));
+
+  if ( fBypass && chamberId >= 6 ) 
+  {
+    return fBypass->GenerateClusters(chamberId,clusterStore);
+  }
+  
+  AliDebug(1,Form("chamberId=%d fClusterStore(%p).GetSize()=%d clusterStore(%p).GetSize()=%d",
+                  chamberId,
+                  fClusterStore,fClusterStore->GetSize(),
+                  &clusterStore,clusterStore.GetSize()));
+  
+  TIter next(fClusterStore->CreateChamberIterator(chamberId,chamberId));
+  AliMUONVCluster* cluster;
+  Int_t n(0);
+  TObjArray a;
+  
+  while ( ( cluster = static_cast<AliMUONVCluster*>(next()) ) )
+  {
+    clusterStore.Add(*cluster);
+    a.Add(cluster);
+    ++n;
+  }
+  
+  TIter remove(&a);
+  while ( ( cluster = static_cast<AliMUONVCluster*>(remove()) ) )
+  {
+    fClusterStore->Remove(*cluster);
+  }
+  
+  AliDebug(1,Form("n=%d remaining clusters=%d",n,fClusterStore->GetSize()));
+  
+  return n;
+}
+
+//_____________________________________________________________________________
+Bool_t 
+AliMUONLegacyClusterServer::UseTriggerTrackStore(AliMUONVTriggerTrackStore* trackStore)
+{
+  /// Tells us to use trigger track store, and thus to bypass St45 clusters
+  fTriggerTrackStore = trackStore; // not owner
+  delete fBypass;
+  fBypass = new AliMUONTriggerTrackToTrackerClusters(fTransformer,fTriggerTrackStore);
+  return kTRUE;
+}
+
+//_____________________________________________________________________________
+void
+AliMUONLegacyClusterServer::UseDigits(TIter&)
+{
+  /// Give the iterator to our delegate if we have one, of issue and error
+  
+  AliError("Not implemented for this class, as we're not writing clusters, but reading them instead !");
+}
+
diff --git a/MUON/AliMUONLegacyClusterServer.h b/MUON/AliMUONLegacyClusterServer.h
new file mode 100644 (file)
index 0000000..316325f
--- /dev/null
@@ -0,0 +1,53 @@
+#ifndef ALIMUONLEGACYCLUSTERSERVER_H
+#define ALIMUONLEGACYCLUSTERSERVER_H
+
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* See cxx source for full Copyright notice                               */
+
+// $Id$
+
+/// \ingroup rec
+/// \class AliMUONLegacyClusterServer
+/// \brief Cluster server that always clusterize everything.
+/// 
+// Author Laurent Aphecetche, Subatech
+
+#ifndef ALIMUONVCLUSTERSERVER_H
+#  include "AliMUONVClusterServer.h"
+#endif
+
+class AliMUONTriggerTrackToTrackerClusters;
+class AliMUONVClusterStore;
+class AliMUONGeometryTransformer;
+
+class AliMUONLegacyClusterServer : public AliMUONVClusterServer
+{
+public:
+  AliMUONLegacyClusterServer(const AliMUONGeometryTransformer& transformer, AliMUONVClusterStore* store=0x0);
+
+  virtual ~AliMUONLegacyClusterServer();
+  
+  virtual Int_t Clusterize(Int_t chamberId, 
+                           AliMUONVClusterStore& clusterStore,
+                           const AliMpArea& area);
+  
+  virtual void UseDigits(TIter& next);
+
+  /// Use trigger tracks. Return kFALSE if not used.
+  virtual Bool_t UseTriggerTrackStore(AliMUONVTriggerTrackStore* trackStore);
+
+private:
+    /// not defined
+    AliMUONLegacyClusterServer(const AliMUONLegacyClusterServer& rhs);
+  /// not defined
+  AliMUONLegacyClusterServer& operator=(const AliMUONLegacyClusterServer& rhs);
+
+  const AliMUONGeometryTransformer& fTransformer; //<! geometry convertor
+    AliMUONVClusterStore* fClusterStore; //<! cluster store 
+    AliMUONVTriggerTrackStore* fTriggerTrackStore; //<! trigger track store
+    AliMUONTriggerTrackToTrackerClusters* fBypass; //<! bypass 
+    
+  ClassDef(AliMUONLegacyClusterServer,1) // Implementation of AliMUONVClusterServer
+};
+
+#endif
index f0f62b8..ec54b21 100644 (file)
@@ -158,7 +158,7 @@ void AliMUONRawClusterV2::AddDigitId(UInt_t id)
   UInt_t *digitsIdNew = new UInt_t[fNDigits+1];
   memcpy(digitsIdNew,fDigitsId, fNDigits*sizeof(UInt_t));
   digitsIdNew[fNDigits++] = id;
-  delete fDigitsId;
+  delete[] fDigitsId;
   fDigitsId = digitsIdNew;
 }
 
index 37bc02d..852b4e9 100644 (file)
@@ -40,6 +40,7 @@ AliMUONRecoParam::AliMUONRecoParam()
   fTrackingMode("KALMAN"),
   fMinBendingMomentum(0.),
   fMaxBendingMomentum(0.),
+  fMaxNonBendingSlope(0.),
   fNonBendingVertexDispersion(0.),
   fBendingVertexDispersion(0.),
   fMaxNonBendingDistanceToTrack(0.),
@@ -53,11 +54,13 @@ AliMUONRecoParam::AliMUONRecoParam()
   fTrackAllTracks(kFALSE),
   fRecoverTracks(kFALSE),
   fMakeTrackCandidatesFast(kFALSE),
+  fMakeMoreTrackCandidates(kFALSE),
   fComplementTracks(kFALSE),
   fImproveTracks(kFALSE),
   fUseSmoother(kFALSE),
   fSaveFullClusterInESD(kTRUE),
-  fCalibrationMode("NOGAIN")
+  fCalibrationMode("NOGAIN"),
+  fBypassSt45(kFALSE)
 {
   /// Constructor
   SetNameTitle("MUON","MUON");
@@ -73,6 +76,19 @@ AliMUONRecoParam::~AliMUONRecoParam()
 }
 
 //_____________________________________________________________________________
+Option_t*
+AliMUONRecoParam::GetCalibrationMode() const
+{
+  /// Return the calibration mode. Can be : 
+  /// NOGAIN : only do pedestal subtraction
+  /// GAIN : do pedestal subtraction, and apply gain correction, but with a
+  ///        single capacitance value for all channels
+  /// GAINCONSTANTCAPA : as GAIN, but with a channel-dependent capacitance value
+  
+  return fCalibrationMode.Data();
+}
+
+//_____________________________________________________________________________
 AliMUONRecoParam *AliMUONRecoParam::GetLowFluxParam() 
 {
   /// Return default reconstruction parameters for low flux environment
@@ -99,12 +115,13 @@ void AliMUONRecoParam::SetLowFluxParam()
 {
   /// Set reconstruction parameters for low flux environment
   
-  fMinBendingMomentum = 0.5;
+  fMinBendingMomentum = 1.;
   fMaxBendingMomentum = 3000.;
+  fMaxNonBendingSlope = 0.3;
   fNonBendingVertexDispersion = 10.;
   fBendingVertexDispersion = 10.;
-  fMaxNonBendingDistanceToTrack = 2.;
-  fMaxBendingDistanceToTrack = 2.;
+  fMaxNonBendingDistanceToTrack = 1.;
+  fMaxBendingDistanceToTrack = 1.;
   fSigmaCutForTracking = 6.;
   fSigmaCutForImprovement = 5.;
   fSigmaCutForTrigger = 8.;
@@ -112,9 +129,12 @@ void AliMUONRecoParam::SetLowFluxParam()
   fTrackAllTracks = kTRUE;
   fRecoverTracks = kTRUE;
   fMakeTrackCandidatesFast = kFALSE;
+  fMakeMoreTrackCandidates = kFALSE;
   fComplementTracks = kTRUE;
   fImproveTracks = kTRUE;
   fUseSmoother = kTRUE;
+  for (Int_t iCh = 0; iCh < 10; iCh++) fUseChamber[iCh] = kTRUE;
+  for (Int_t iSt = 0; iSt < 5; iSt++) fRequestStation[iSt] = kTRUE;
   
 }
 
@@ -123,12 +143,13 @@ void AliMUONRecoParam::SetHighFluxParam()
 {
   /// Set reconstruction parameters for high flux environment
   
-  fMinBendingMomentum = 0.5;
+  fMinBendingMomentum = 1.;
   fMaxBendingMomentum = 3000.;
+  fMaxNonBendingSlope = 0.3;
   fNonBendingVertexDispersion = 10.;
   fBendingVertexDispersion = 10.;
-  fMaxNonBendingDistanceToTrack = 2.;
-  fMaxBendingDistanceToTrack = 2.;
+  fMaxNonBendingDistanceToTrack = 1.;
+  fMaxBendingDistanceToTrack = 1.;
   fSigmaCutForTracking = 6.;
   fSigmaCutForImprovement = 5.;
   fSigmaCutForTrigger = 8.;
@@ -136,9 +157,12 @@ void AliMUONRecoParam::SetHighFluxParam()
   fTrackAllTracks = kTRUE;
   fRecoverTracks = kTRUE;
   fMakeTrackCandidatesFast = kFALSE;
+  fMakeMoreTrackCandidates = kFALSE;
   fComplementTracks = kTRUE;
   fImproveTracks = kTRUE;
   fUseSmoother = kTRUE;
+  for (Int_t iCh = 0; iCh < 10; iCh++) fUseChamber[iCh] = kTRUE;
+  for (Int_t iSt = 0; iSt < 5; iSt++) fRequestStation[iSt] = kTRUE;
   
 }
 
@@ -152,8 +176,9 @@ void AliMUONRecoParam::Print(Option_t *option) const
   
   cout<<Form("Calibration mode = %s",fCalibrationMode.Data())<<endl;
   cout<<Form("Clustering mode = %s",fClusteringMode.Data())<<endl;
-  
   cout<<Form("Tracking mode = %s",fTrackingMode.Data())<<endl;
+
+  if (BypassSt45()) cout << "Will bypass St45 (replacing their clusters by generated ones from trigger tracks)" << endl;
   
   if (fCombinedClusterTrackReco) cout<<"Combined cluster/track reconstruction: ON"<<endl;
   else cout<<"Combined cluster/track reconstruction: OFF"<<endl;
@@ -163,6 +188,8 @@ void AliMUONRecoParam::Print(Option_t *option) const
   
   cout<<Form("Bending momentum range = [%5.2f,%5.2f]",fMinBendingMomentum,fMaxBendingMomentum)<<endl;
   
+  cout<<Form("Maximum non bending slope = %5.2f",fMaxNonBendingSlope)<<endl;
+  
   if (strstr(fTrackingMode,"ORIGINAL"))
     cout<<Form("Vertex dispertion = (%5.2f,%5.2f)",fNonBendingVertexDispersion,fBendingVertexDispersion)<<endl;
   else if (strstr(option,"FULL"))
@@ -185,6 +212,13 @@ void AliMUONRecoParam::Print(Option_t *option) const
     cout<<"Make track candidates assuming linear propagation between stations 4 and 5"<<endl;
   
   if (strstr(option,"FULL")) {
+    cout<<"Make track candidates starting from 1 cluster in each of the stations 4 and 5: ";
+    if (fMakeMoreTrackCandidates) cout<<"ON"<<endl;
+    else cout<<"OFF"<<endl;
+  } else if (fMakeMoreTrackCandidates)
+    cout<<"Make track candidates starting from 1 cluster in each of the stations 4 and 5"<<endl;
+  
+  if (strstr(option,"FULL")) {
     cout<<"Try to recover tracks getting lost during tracking: ";
     if (fRecoverTracks) cout<<"ON"<<endl;
     else cout<<"OFF"<<endl;
@@ -214,6 +248,33 @@ void AliMUONRecoParam::Print(Option_t *option) const
   
   cout<<Form("Maximum normalized chi2 of tracking/trigger track matching = %5.2f",fMaxNormChi2MatchTrigger)<<endl;
   
+  Bool_t discardedCh = kFALSE;
+  Int_t ch = 0;
+  do {
+    if (!UseChamber(ch)) {
+      if (!discardedCh) {
+       cout<<"Discarded chambers(1..): "<<ch+1;
+       discardedCh = kTRUE;
+      }
+      else cout<<" "<<ch+1;
+    }
+  } while (++ch < 10);
+  if (discardedCh) cout<<endl;
+  
+  Bool_t discardedSt = kFALSE;
+  Int_t st = 0;
+  do {
+    if (!RequestStation(st)) {
+      if (!discardedSt) {
+       cout<<"Not requested stations(1..): "<<st+1;
+       discardedSt = kTRUE;
+      }
+      else cout<<" "<<st+1;
+    }
+  } while (++st < 5);
+  if (discardedSt) cout<<endl;
+  
+  
   cout<<"\t-------------------------------------"<<endl<<endl;
   
 }
index ad6d058..0375b1c 100644 (file)
@@ -21,11 +21,11 @@ class AliMUONRecoParam : public AliDetectorRecoParam
   static AliMUONRecoParam *GetLowFluxParam();
   static AliMUONRecoParam *GetHighFluxParam();
   
-  /// set the calibration mode
+  /// set the calibration mode (see GetCalibrationMode() for possible modes)
   void SetCalibrationMode(Option_t* mode) { fCalibrationMode = mode; fCalibrationMode.ToUpper();}
-  /// get the calibration mode
-  Option_t* GetCalibrationMode() const { return fCalibrationMode.Data(); }
-  
+
+  Option_t* GetCalibrationMode() const;
+      
   /// set the clustering (pre-clustering) mode
   void      SetClusteringMode(Option_t* mode) {fClusteringMode = mode; fClusteringMode.ToUpper();}
   /// get the clustering (pre-clustering) mode
@@ -57,6 +57,10 @@ class AliMUONRecoParam : public AliDetectorRecoParam
   void     SetMaxBendingMomentum(Double_t val) {fMaxBendingMomentum = val;}
   /// return the maximum value (GeV/c) of momentum in bending plane
   Double_t GetMaxBendingMomentum() const {return fMaxBendingMomentum;}
+  /// set the maximum value of the non bending slope
+  void     SetMaxNonBendingSlope(Double_t val) {fMaxNonBendingSlope = val;}
+  /// return the maximum value of the non bending slope
+  Double_t GetMaxNonBendingSlope() const {return fMaxNonBendingSlope;}
   
   /// set the vertex dispersion (cm) in non bending plane (used for original tracking only)
   void     SetNonBendingVertexDispersion(Double_t val) {fNonBendingVertexDispersion = val;} 
@@ -115,6 +119,11 @@ class AliMUONRecoParam : public AliDetectorRecoParam
   /// return kTRUE/kFALSE if the fast building of track candidates is switched on/off
   Bool_t   MakeTrackCandidatesFast() const {return fMakeTrackCandidatesFast;}
   
+  /// switch on/off the building of track candidates starting from 1 cluster in each of the stations 4 and 5
+  void     MakeMoreTrackCandidates(Bool_t flag) {fMakeMoreTrackCandidates = flag;} 
+  /// return kTRUE/kFALSE if the building of extra track candidates is switched on/off
+  Bool_t   MakeMoreTrackCandidates() const {return fMakeMoreTrackCandidates;}
+  
   /// switch on/off the completion of reconstructed track
   void     ComplementTracks(Bool_t flag) {fComplementTracks = flag;} 
   /// return kTRUE/kFALSE if completion of the reconstructed track is switched on/off
@@ -125,8 +134,23 @@ class AliMUONRecoParam : public AliDetectorRecoParam
   /// return kTRUE/kFALSE if the use of the smoother is switched on/off
   Bool_t   UseSmoother() const {return fUseSmoother;}
   
-  virtual void Print(Option_t *option = "") const;
+  /// switch on/off a chamber in the reconstruction
+  void     UseChamber(Int_t iCh, Bool_t flag) {if (iCh >= 0 && iCh < 10) fUseChamber[iCh] = flag;}
+  /// return kTRUE/kFALSE whether the chamber must be used or not
+  Bool_t   UseChamber(Int_t iCh) const {return (iCh >= 0 && iCh < 10) ? fUseChamber[iCh] : kFALSE;}
+  
+  /// request or not at least one cluster in the station to validate the track
+  void     RequestStation(Int_t iSt, Bool_t flag) {if (iSt >= 0 && iSt < 5) fRequestStation[iSt] = flag;}
+  /// return kTRUE/kFALSE whether at least one cluster is requested in the station to validate the track
+  Bool_t   RequestStation(Int_t iSt) const {return (iSt >= 0 && iSt < 5) ? fRequestStation[iSt] : kFALSE;}
+  
+  /// return kTRUE if we should replace clusters in St 4 and 5 by generated clusters from trigger tracks
+  Bool_t BypassSt45() const { return fBypassSt45; }
   
+  /// set the bypassSt45 value
+  void BypassSt45(Bool_t value) { fBypassSt45 = value; }
+  
+  virtual void Print(Option_t *option = "") const;
   
  private:
   
@@ -139,6 +163,7 @@ class AliMUONRecoParam : public AliDetectorRecoParam
   
   Double32_t fMinBendingMomentum; ///< minimum value (GeV/c) of momentum in bending plane
   Double32_t fMaxBendingMomentum; ///< maximum value (GeV/c) of momentum in bending plane
+  Double32_t fMaxNonBendingSlope; ///< maximum value of the non bending slope
   
   Double32_t fNonBendingVertexDispersion; ///< vertex dispersion (cm) in non bending plane (used for original tracking only)
   Double32_t fBendingVertexDispersion;    ///< vertex dispersion (cm) in bending plane (used for original tracking only)
@@ -164,6 +189,8 @@ class AliMUONRecoParam : public AliDetectorRecoParam
   
   Bool_t     fMakeTrackCandidatesFast; ///< kTRUE to make candidate tracks assuming linear propagation between stations 4 and 5
   
+  Bool_t     fMakeMoreTrackCandidates; ///< kTRUE to make candidate tracks starting from 1 cluster in each of the stations 4 and 5
+  
   Bool_t     fComplementTracks; ///< kTRUE to try to complete the reconstructed tracks by adding missing clusters
   
   Bool_t     fImproveTracks; ///< kTRUE to try to improve the reconstructed tracks by removing bad clusters
@@ -172,15 +199,21 @@ class AliMUONRecoParam : public AliDetectorRecoParam
   
   Bool_t     fSaveFullClusterInESD; ///< kTRUE to save all cluster info (including pads) in ESD
   
-  /// calibration mode:  GAIN, NOGAIN
+  /// calibration mode:  GAIN, NOGAIN, GAINCONSTANTCAPA
   TString fCalibrationMode; ///<\brief calibration mode
   
+  Bool_t fBypassSt45; ///< kTRUE to use trigger tracks to generate "fake" clusters in St 4 and 5
+  
+  Bool_t     fUseChamber[10]; ///< kTRUE to use the chamber i in the tracking algorithm
+  
+  Bool_t     fRequestStation[5]; ///< kTRUE to request at least one cluster in station i to validate the track
+  
   // functions
   void SetLowFluxParam();
   void SetHighFluxParam();
   
   
-  ClassDef(AliMUONRecoParam,2) // MUON reco parameters
+  ClassDef(AliMUONRecoParam,3) // MUON reco parameters
 };
 
 #endif
index 59f0c1e..36294ed 100644 (file)
@@ -83,6 +83,8 @@
 #include "AliMUONClusterFinderSimpleFit.h"
 #include "AliMUONClusterFinderPeakCOG.h"
 #include "AliMUONClusterFinderPeakFit.h"
+#include "AliMUONClusterStoreV1.h"
+#include "AliMUONClusterStoreV2.h"
 #include "AliMUONConstants.h"
 #include "AliMUONDigitCalibrator.h"
 #include "AliMUONDigitMaker.h"
@@ -310,29 +312,37 @@ AliMUONReconstructor::CreateTracker() const
   CreateTriggerCircuit();
   CreateDigitMaker();
   CreateClusterServer();
+
+  AliMUONTracker* tracker(0x0);
   
-  if (!fClusterServer) 
+  if ( ! AliMUONReconstructor::GetRecoParam()->CombineClusterTrackReco() )
   {
-    AliError("ClusterServer is NULL ! Cannot create tracker");
-    return 0x0;
+    tracker = new AliMUONTracker(0x0,
+                                 *DigitStore(),
+                                 fDigitMaker,
+                                 fTransformer,
+                                 fTriggerCircuit);
+  }
+  else
+  {
+    tracker = new AliMUONTracker(fClusterServer,
+                                 *DigitStore(),
+                                 fDigitMaker,
+                                 fTransformer,
+                                 fTriggerCircuit);
   }
   
-  AliMUONTracker* tracker = new AliMUONTracker(*fClusterServer,
-                                              *DigitStore(),
-                                               fDigitMaker,
-                                               fTransformer,
-                                               fTriggerCircuit);
   
   return tracker;
 }
 
 //_____________________________________________________________________________
 AliMUONVClusterFinder*
-AliMUONReconstructor::CreateClusterFinder(const char* clusterFinderType) const
+AliMUONReconstructor::CreateClusterFinder(const char* clusterFinderType)
 {
   /// Create a given cluster finder instance
   
-  AliCodeTimerAuto("")
+  AliCodeTimerAutoGeneral("")
 
   AliMUONVClusterFinder* clusterFinder(0x0);
   
@@ -389,7 +399,7 @@ AliMUONReconstructor::CreateClusterFinder(const char* clusterFinderType) const
   } 
   else
   {
-    AliError(Form("clustering mode \"%s\" does not exist",opt.Data()));
+    AliErrorClass(Form("clustering mode \"%s\" does not exist",opt.Data()));
     return 0x0;
   }
   
@@ -404,17 +414,15 @@ AliMUONReconstructor::CreateClusterServer() const
   
   if ( fClusterServer ) return;
   
-  AliCodeTimerAuto("")
-
-  AliDebug(1,"");
-  
+  AliCodeTimerAuto("");
+    
   AliMUONVClusterFinder* clusterFinder = CreateClusterFinder(GetRecoParam()->GetClusteringMode());
   
   if ( !clusterFinder ) return;
   
   AliInfo(Form("Will use %s for clusterizing",clusterFinder->ClassName()));
   
-  fClusterServer = new AliMUONSimpleClusterServer(*clusterFinder,*fTransformer);
+  fClusterServer = new AliMUONSimpleClusterServer(clusterFinder,*fTransformer);
 }
 
 //_____________________________________________________________________________
@@ -503,19 +511,62 @@ AliMUONReconstructor::FillTreeR(AliMUONVTriggerStore* triggerStore,
   AliDebug(1,"");
   
   Bool_t ok(kFALSE);
+  Bool_t alone(kTRUE); // is trigger the only info in TreeR ?
+  
+  if ( ! AliMUONReconstructor::GetRecoParam()->CombineClusterTrackReco() )
+  {
+    alone = kFALSE; // we'll get both tracker and trigger information in TreeR
+  }
+  
   if ( triggerStore ) 
   {
-    ok = triggerStore->Connect(clustersTree,kTRUE);
+    ok = triggerStore->Connect(clustersTree,alone);
     if (!ok)
     {
       AliError("Could not create triggerStore branches in TreeR");
     }
   }
+
+  AliMUONVClusterStore* clusterStore(0x0);
   
+  if ( !alone )
+  {
+    clusterStore = new AliMUONClusterStoreV2;
+    
+    CreateClusterServer();
+    
+    TIter next(DigitStore()->CreateIterator());
+    fClusterServer->UseDigits(next);
+
+    AliMpArea area;
+    
+    AliDebug(1,Form("Doing full clusterization in local reconstruction using %s ",fClusterServer->ClassName()));
+    
+    for ( Int_t i = 0; i < AliMpConstants::NofTrackingChambers(); ++i ) 
+    {
+      if (AliMUONReconstructor::GetRecoParam()->UseChamber(i))
+      {
+        if ( i >= 6 && AliMUONReconstructor::GetRecoParam()->BypassSt45() ) continue;
+        
+        fClusterServer->Clusterize(i,*clusterStore,area);
+      }
+    }
+    
+    Bool_t cok = clusterStore->Connect(clustersTree,alone);
+    
+    if (!cok) AliError("Could not connect clusterStore to clusterTree");
+    
+    AliDebug(1,Form("Number of clusters found = %d",clusterStore->GetSize()));
+    
+    StdoutToAliDebug(1,clusterStore->Print());
+  }
+         
   if (ok) // at least one type of branches created successfully
   {
     clustersTree.Fill();
   }
+  
+  delete clusterStore;
 }
 
 //_____________________________________________________________________________
index 62a7b3a..0994b9d 100644 (file)
@@ -57,6 +57,8 @@ public:
   
   static const AliMUONRecoParam* GetRecoParam();
   
+  static AliMUONVClusterFinder* CreateClusterFinder(const char* clusterFinderType);
+
 private:
   /// Not implemented
   AliMUONReconstructor(const AliMUONReconstructor&);
@@ -69,7 +71,6 @@ private:
   void Calibrate(AliMUONVDigitStore& digitStore) const;
   AliMUONTriggerCrateStore* CrateManager() const;
   void CreateCalibrator() const;
-  AliMUONVClusterFinder* CreateClusterFinder(const char* clusterFinderType) const;
   void CreateDigitMaker() const;
   void CreateTriggerCircuit() const;
   void CreateClusterServer() const;
@@ -78,7 +79,7 @@ private:
   
   AliMUONVDigitStore* DigitStore() const;
   AliMUONVTriggerStore* TriggerStore() const;
-
+  
 private:
   mutable AliMUONTriggerCrateStore* fCrateManager; //!< Trigger Crate manager
   mutable AliMUONDigitMaker* fDigitMaker; //!< Raw to Digits converter
@@ -93,7 +94,7 @@ private:
   
   static AliMUONRecoParam* fgRecoParam; //!< parameters used to tune the MUON reconstruction
   
-  ClassDef(AliMUONReconstructor,5) // Implementation of AliReconstructor
+  ClassDef(AliMUONReconstructor,6) // Implementation of AliReconstructor
 };
 
 #endif
index 8764784..865256f 100644 (file)
@@ -31,7 +31,7 @@
 #include "AliMUONVClusterStore.h"
 #include "AliMUONVTrackStore.h"
 #include "AliMUONTrack.h"
-
+#include "AliMUONTracker.h"
 #include "AliLog.h"
 
 //-----------------------------------------------------------------------------
@@ -68,7 +68,7 @@ AliMUONRefitter::AliMUONRefitter()
   /// Default constructor
   CreateGeometryTransformer();
   CreateClusterServer(*fGeometryTransformer);
-  if (fClusterServer) CreateTrackReconstructor(*fClusterServer);
+  if (fClusterServer) AliMUONTracker::CreateTrackReconstructor(AliMUONReconstructor::GetRecoParam()->GetTrackingMode(),fClusterServer);
   if (!fClusterServer || !fTracker) {
     AliFatal("refitter initialization failed");
     exit(-1);
@@ -339,53 +339,8 @@ void AliMUONRefitter::CreateGeometryTransformer()
 void AliMUONRefitter::CreateClusterServer(AliMUONGeometryTransformer& transformer)
 {
   /// Create cluster server
-  AliMUONVClusterFinder* clusterFinder = CreateClusterFinder();
-  fClusterServer = clusterFinder ? new AliMUONSimpleClusterServer(*clusterFinder,transformer) : 0x0;
-}
-
-//_____________________________________________________________________________
-AliMUONVClusterFinder* AliMUONRefitter::CreateClusterFinder()
-{
-  /// Create a given cluster finder instance
-  AliMUONVClusterFinder* clusterFinder;
-  Option_t *opt = AliMUONReconstructor::GetRecoParam()->GetClusteringMode();
-  
-  if      (strstr(opt,"PRECLUSTERV2")) clusterFinder = new AliMUONPreClusterFinderV2;
-  else if (strstr(opt,"PRECLUSTERV3")) clusterFinder = new AliMUONPreClusterFinderV3;
-  else if (strstr(opt,"PRECLUSTER"))   clusterFinder = new AliMUONPreClusterFinder;
-  else if (strstr(opt,"COG"))          clusterFinder = new AliMUONClusterFinderCOG(new AliMUONPreClusterFinder);
-  else if (strstr(opt,"SIMPLEFITV3"))  clusterFinder = new AliMUONClusterFinderSimpleFit(new AliMUONClusterFinderCOG(new AliMUONPreClusterFinderV3));
-  else if (strstr(opt,"SIMPLEFIT"))    clusterFinder = new AliMUONClusterFinderSimpleFit(new AliMUONClusterFinderCOG(new AliMUONPreClusterFinder));
-  else if (strstr(opt,"MLEM:DRAW"))    clusterFinder = new AliMUONClusterFinderMLEM(kTRUE,new AliMUONPreClusterFinder);
-  else if (strstr(opt,"MLEMV3"))       clusterFinder = new AliMUONClusterFinderMLEM(kFALSE,new AliMUONPreClusterFinderV3);
-  else if (strstr(opt,"MLEMV2"))       clusterFinder = new AliMUONClusterFinderMLEM(kFALSE,new AliMUONPreClusterFinderV2);
-  else if (strstr(opt,"MLEM"))         clusterFinder = new AliMUONClusterFinderMLEM(kFALSE,new AliMUONPreClusterFinder);
-  else clusterFinder = 0x0;
-  
-  if (clusterFinder) {
-    AliInfo(Form("Will use %s for clusterizing",clusterFinder->ClassName()));
-  } else {
-    AliError(Form("clustering mode \"%s\" does not exist",opt));
-  }
-  
-  return clusterFinder;
-}
-
-//_____________________________________________________________________________
-void AliMUONRefitter::CreateTrackReconstructor(AliMUONVClusterServer& clusterServer)
-{
-  /// Create track reconstructor, depending on tracking mode set in RecoParam
-  Option_t *opt = AliMUONReconstructor::GetRecoParam()->GetTrackingMode();
-  
-  if      (strstr(opt,"ORIGINAL")) fTracker = new AliMUONTrackReconstructor(clusterServer);
-  else if (strstr(opt,"KALMAN"))   fTracker = new AliMUONTrackReconstructorK(clusterServer);
-  else fTracker = 0x0;
-  
-  if (fTracker) {
-    AliInfo(Form("Will use %s for tracking",fTracker->ClassName()));
-  } else {
-    AliError(Form("tracking mode \"%s\" does not exist",opt));
-  }
+  AliMUONVClusterFinder* clusterFinder = AliMUONReconstructor::CreateClusterFinder(AliMUONReconstructor::GetRecoParam()->GetClusteringMode());
+  fClusterServer = clusterFinder ? new AliMUONSimpleClusterServer(clusterFinder,transformer) : 0x0;
 }
 
 //_____________________________________________________________________________
index 853df2b..401b57e 100644 (file)
 
 #include "AliMUONSimpleClusterServer.h"
 
-#include "AliMUONConstants.h"
+#include "AliCodeTimer.h"
+#include "AliLog.h"
 #include "AliMUONCluster.h"
+#include "AliMUONConstants.h"
 #include "AliMUONGeometryTransformer.h"
 #include "AliMUONPad.h"
+#include "AliMUONTriggerTrackToTrackerClusters.h"
 #include "AliMUONVCluster.h"
 #include "AliMUONVClusterFinder.h"
 #include "AliMUONVClusterStore.h"
 #include "AliMpDEIterator.h"
 #include "AliMpDEManager.h"
 #include "AliMpExMap.h"
+#include "AliMpPad.h"
 #include "AliMpSegmentation.h"
-#include "AliMpVPadIterator.h"
 #include "AliMpVSegmentation.h"
-#include "AliESDMuonPad.h"
-#include "AliLog.h"
-#include <float.h>
 #include <Riostream.h>
 #include <TClonesArray.h>
 #include <TString.h>
-
+#include <float.h>
 
 /// \class AliMUONSimpleClusterServer
 ///
@@ -64,95 +64,31 @@ namespace
 }
 
 //_____________________________________________________________________________
-AliMUONSimpleClusterServer::AliMUONSimpleClusterServer(AliMUONVClusterFinder& clusterFinder,
+AliMUONSimpleClusterServer::AliMUONSimpleClusterServer(AliMUONVClusterFinder* clusterFinder,
                                                        const AliMUONGeometryTransformer& transformer)
 : AliMUONVClusterServer(), 
   fClusterFinder(clusterFinder),
   fTransformer(transformer),
   fPads(),
-  fDEAreas(new AliMpExMap(true))
+  fTriggerTrackStore(0x0),
+  fBypass(0x0)
 {
     /// Ctor
+    /// Note that we take ownership of the clusterFinder
     
     fPads[0] = new AliMpExMap(true);
     fPads[1] = new AliMpExMap(true);
     
-    AliMpDEIterator it;
-    
-    it.First();
-    
-    /// Generate the DE areas in global coordinates
-    
-    while ( !it.IsDone() )
-    {
-      Int_t detElemId = it.CurrentDEId();
-      
-      const AliMpVSegmentation* seg = AliMpSegmentation::Instance()->GetMpSegmentation(detElemId,AliMp::kCath0);
-      
-      Double_t xg,yg,zg;
-      
-      AliMp::StationType stationType = AliMpDEManager::GetStationType(detElemId);
-      
-      Double_t xl(0.0), yl(0.0), zl(0.0);
-      Double_t dx(seg->Dimensions().X());
-      Double_t dy(seg->Dimensions().Y());
-      
-      if ( stationType == AliMp::kStation1 || stationType == AliMp::kStation2 ) 
-      {
-        Double_t xmin(FLT_MAX);
-        Double_t xmax(-FLT_MAX);
-        Double_t ymin(FLT_MAX);
-        Double_t ymax(-FLT_MAX);
-        
-        for ( Int_t icathode = 0; icathode < 2; ++icathode ) 
-        {
-          const AliMpVSegmentation* cathode 
-            = AliMpSegmentation::Instance()->GetMpSegmentation(detElemId,AliMp::GetCathodType(icathode));
-          
-          AliMpVPadIterator* it = cathode->CreateIterator();
-          
-          it->First();
-          
-          while ( !it->IsDone() ) 
-          {
-            AliMpPad pad = it->CurrentItem();
-            AliMpArea a(pad.Position(),pad.Dimensions());
-            xmin = TMath::Min(xmin,a.LeftBorder());
-            xmax = TMath::Max(xmax,a.RightBorder());
-            ymin = TMath::Min(ymin,a.DownBorder());
-            ymax = TMath::Max(ymax,a.UpBorder());
-            it->Next();
-          }
-          
-          delete it;
-        }
-        
-        xl = (xmin+xmax)/2.0;
-        yl = (ymin+ymax)/2.0;
-        dx = (xmax-xmin)/2.0;
-        dy = (ymax-ymin)/2.0;
-        
-        fTransformer.Local2Global(detElemId,xl,yl,zl,xg,yg,zg);
-      }
-      else
-      {
-        fTransformer.Local2Global(detElemId,xl,yl,zl,xg,yg,zg);
-      }
-      
-      fDEAreas->Add(detElemId,new AliMpArea(TVector2(xg,yg),TVector2(dx,dy)));
-     
-      it.Next();
-    }
 }
 
 //_____________________________________________________________________________
 AliMUONSimpleClusterServer::~AliMUONSimpleClusterServer()
 {
   /// Dtor
-  delete &fClusterFinder;
+  delete fClusterFinder;
   delete fPads[0];
   delete fPads[1];
-  delete fDEAreas;
+  delete fBypass;
 }
 
 //_____________________________________________________________________________
@@ -167,6 +103,13 @@ AliMUONSimpleClusterServer::Clusterize(Int_t chamberId,
   /// We first find out the list of DE that have a non-zero overlap with area,
   /// and then use the clusterfinder to find clusters in those areas (and DE).
   
+  AliCodeTimerAuto(Form("Chamber %d",chamberId));
+  
+  if ( fTriggerTrackStore && chamberId >= 6 ) 
+  {
+    return fBypass->GenerateClusters(chamberId,clusterStore);
+  }
+  
   AliMpDEIterator it;
   
   it.First(chamberId);
@@ -200,17 +143,17 @@ AliMUONSimpleClusterServer::Clusterize(Int_t chamberId,
       
       if ( ok ) 
       {      
-        if ( fClusterFinder.NeedSegmentation() )
+        if ( fClusterFinder->NeedSegmentation() )
         {
           const AliMpVSegmentation* seg[2] = 
         { AliMpSegmentation::Instance()->GetMpSegmentation(detElemId,AliMp::kCath0),
           AliMpSegmentation::Instance()->GetMpSegmentation(detElemId,AliMp::kCath1)
         };
-          fClusterFinder.Prepare(detElemId,pads,deArea,seg);
+          fClusterFinder->Prepare(detElemId,pads,deArea,seg);
         }
         else
         {
-          fClusterFinder.Prepare(detElemId,pads,deArea);
+          fClusterFinder->Prepare(detElemId,pads,deArea);
         }
         
         AliDebug(1,Form("Clusterizing DE %04d with %3d pads (cath0) and %3d pads (cath1)",
@@ -220,7 +163,7 @@ AliMUONSimpleClusterServer::Clusterize(Int_t chamberId,
         
         AliMUONCluster* cluster;
         
-        while ( ( cluster = fClusterFinder.NextCluster() ) ) 
+        while ( ( cluster = fClusterFinder->NextCluster() ) ) 
         {      
           // add new cluster to the store with information to build its ID
           // increment the number of clusters into the store
@@ -267,6 +210,7 @@ AliMUONSimpleClusterServer::Clusterize(Int_t chamberId,
   return nofAddedClusters;
 }
 
+
 //_____________________________________________________________________________
 void
 AliMUONSimpleClusterServer::Global2Local(Int_t detElemId, const AliMpArea& globalArea,
@@ -297,7 +241,9 @@ AliMUONSimpleClusterServer::Overlap(Int_t detElemId,
   
   Bool_t overlap(kFALSE);
   
-  AliMpArea* globalDEArea = static_cast<AliMpArea*>(fDEAreas->GetValue(detElemId));
+  AliMpArea* globalDEArea = fTransformer.GetDEArea(detElemId);
+  
+  if (!globalDEArea) return kFALSE;
   
   AliMpArea overlapArea;
   
@@ -333,6 +279,17 @@ AliMUONSimpleClusterServer::PadArray(Int_t detElemId, Int_t cathode) const
 }
 
 //_____________________________________________________________________________
+Bool_t 
+AliMUONSimpleClusterServer::UseTriggerTrackStore(AliMUONVTriggerTrackStore* trackStore)
+{
+  /// Tells us to use trigger track store, and thus to bypass St45 clusters
+  fTriggerTrackStore = trackStore; // not owner
+  delete fBypass;
+  fBypass = new AliMUONTriggerTrackToTrackerClusters(fTransformer,fTriggerTrackStore);
+  return kTRUE;
+}
+
+//_____________________________________________________________________________
 void 
 AliMUONSimpleClusterServer::UseDigits(TIter& next)
 {
index 042da88..74612e4 100644 (file)
 #  include "AliMUONVClusterServer.h"
 #endif
 
-class AliMUONVClusterFinder;
+class AliESDMuonPad;
 class AliMUONGeometryTransformer;
+class AliMUONTriggerTrackToTrackerClusters;
+class AliMUONVClusterFinder;
 class AliMpExMap;
-class AliESDMuonPad;
 class TClonesArray;
 
 class AliMUONSimpleClusterServer : public AliMUONVClusterServer
 {
 public:
-  AliMUONSimpleClusterServer(AliMUONVClusterFinder& clusterFinder,
+  AliMUONSimpleClusterServer(AliMUONVClusterFinder* clusterFinder,
                              const AliMUONGeometryTransformer& transformer);
   
   virtual ~AliMUONSimpleClusterServer();
@@ -37,7 +38,10 @@ public:
   void UseDigits(TIter& next);
   
   void Print(Option_t* opt="") const;
-  
+
+  /// Use trigger tracks. Return kFALSE if not used.
+  virtual Bool_t UseTriggerTrackStore(AliMUONVTriggerTrackStore* trackStore);
+
 private:
   /// Not implemented
   AliMUONSimpleClusterServer(const AliMUONSimpleClusterServer& rhs);
@@ -51,10 +55,11 @@ private:
   TClonesArray* PadArray(Int_t detElemId, Int_t cathode) const;
   
 private:
-  AliMUONVClusterFinder& fClusterFinder; //!< the cluster finder (owner)
+  AliMUONVClusterFinder* fClusterFinder; //!< the cluster finder (owner)
   const AliMUONGeometryTransformer& fTransformer; //!< the geometry transformer (not owner)
   AliMpExMap* fPads[2]; ///< map of TClonesArray of AliMUONPads
-  AliMpExMap* fDEAreas; ///< map of detection element areas in global coordinates
+  AliMUONVTriggerTrackStore* fTriggerTrackStore; ///< trigger track store (if bypassing of St45 was requested) (not owner)
+  AliMUONTriggerTrackToTrackerClusters* fBypass; ///< to convert trigger track into tracker clusters (owner)
   
   ClassDef(AliMUONSimpleClusterServer,0) // Cluster server
 };
index 8a38f42..804ca84 100644 (file)
@@ -23,6 +23,8 @@
 
 #include "AliMUONTrack.h"
 
+#include "AliMUONReconstructor.h"
+#include "AliMUONRecoParam.h"
 #include "AliMUONVCluster.h"
 #include "AliMUONVClusterStore.h"
 #include "AliMUONObjectPair.h"
@@ -89,26 +91,8 @@ AliMUONTrack::AliMUONTrack(AliMUONObjectPair *segment)
   fVertexErrXY2[1] = 0.;
   
   // Pointers to clusters from the segment
-  AliMUONVCluster* cluster1 = (AliMUONVCluster*) segment->First();
-  AliMUONVCluster* cluster2 = (AliMUONVCluster*) segment->Second();
-  
-  // check sorting in -Z (spectro z<0)
-  if (cluster1->GetZ() < cluster2->GetZ()) {
-    cluster1 = cluster2;
-    cluster2 = (AliMUONVCluster*) segment->First();
-  }
-  
-  // order the clusters into the track according to the station the segment belong to
-  // to anticipate the direction of propagation in the first tracking step
-  // (go backward if the segment is on the last station / go forward otherwise)
-  AliMUONVCluster *firstCluster, *lastCluster;
-  if (cluster1->GetChamberId() == 8) { // last station
-    firstCluster = cluster1;
-    lastCluster = cluster2;
-  } else {
-    firstCluster = cluster2;
-    lastCluster = cluster1;
-  }
+  AliMUONVCluster* firstCluster = (AliMUONVCluster*) segment->First();
+  AliMUONVCluster* lastCluster = (AliMUONVCluster*) segment->Second();
   
   // Compute track parameters
   Double_t z1 = firstCluster->GetZ();
@@ -126,8 +110,7 @@ AliMUONTrack::AliMUONTrack(AliMUONObjectPair *segment)
   Double_t bendingImpact = bendingCoor1 - z1 * bendingSlope;
   Double_t inverseBendingMomentum = 1. / AliMUONTrackExtrap::GetBendingMomentumFromImpactParam(bendingImpact);
   
-  
-  // Set track parameters at first cluster (needed by any tracking algorithm)
+  // Set track parameters at first cluster
   AliMUONTrackParam trackParamAtFirstCluster;
   trackParamAtFirstCluster.SetZ(z1);
   trackParamAtFirstCluster.SetNonBendingCoor(nonBendingCoor1);
@@ -136,8 +119,7 @@ AliMUONTrack::AliMUONTrack(AliMUONObjectPair *segment)
   trackParamAtFirstCluster.SetBendingSlope(bendingSlope);
   trackParamAtFirstCluster.SetInverseBendingMomentum(inverseBendingMomentum);
   
-  
-  // Set track parameters at last cluster (used by Kalman only)
+  // Set track parameters at last cluster
   AliMUONTrackParam trackParamAtLastCluster;
   trackParamAtLastCluster.SetZ(z2);
   trackParamAtLastCluster.SetNonBendingCoor(nonBendingCoor2);
@@ -146,43 +128,40 @@ AliMUONTrack::AliMUONTrack(AliMUONObjectPair *segment)
   trackParamAtLastCluster.SetBendingSlope(bendingSlope);
   trackParamAtLastCluster.SetInverseBendingMomentum(inverseBendingMomentum);
   
-  
-  // Compute and set track parameters covariances at first cluster (needed by any tracking algorithm)
-  TMatrixD paramCov1(5,5);
-  paramCov1.Zero();
+  // Compute and set track parameters covariances at first cluster
+  TMatrixD paramCov(5,5);
+  paramCov.Zero();
   // Non bending plane
-  paramCov1(0,0) = firstCluster->GetErrX2();
-  paramCov1(0,1) = firstCluster->GetErrX2() / dZ;
-  paramCov1(1,0) = paramCov1(0,1);
-  paramCov1(1,1) = ( firstCluster->GetErrX2() + lastCluster->GetErrX2() ) / dZ / dZ;
+  paramCov(0,0) = firstCluster->GetErrX2();
+  paramCov(0,1) = firstCluster->GetErrX2() / dZ;
+  paramCov(1,0) = paramCov(0,1);
+  paramCov(1,1) = ( firstCluster->GetErrX2() + lastCluster->GetErrX2() ) / dZ / dZ;
   // Bending plane
-  paramCov1(2,2) = firstCluster->GetErrY2();
-  paramCov1(2,3) = firstCluster->GetErrY2() / dZ;
-  paramCov1(3,2) = paramCov1(2,3);
-  paramCov1(3,3) = ( firstCluster->GetErrY2() + lastCluster->GetErrY2() ) / dZ / dZ;
-  // Inverse bending momentum (50% error)
-  paramCov1(4,4) = 0.5*inverseBendingMomentum * 0.5*inverseBendingMomentum;
-  // Set covariances
-  trackParamAtFirstCluster.SetCovariances(paramCov1);
+  paramCov(2,2) = firstCluster->GetErrY2();
+  paramCov(2,3) = firstCluster->GetErrY2() / dZ;
+  paramCov(3,2) = paramCov(2,3);
+  paramCov(3,3) = ( firstCluster->GetErrY2() + lastCluster->GetErrY2() ) / dZ / dZ;
+  // Inverse bending momentum (vertex resolution + bending slope resolution + 10% error on dipole parameters+field)
+  paramCov(4,4) = ((AliMUONReconstructor::GetRecoParam()->GetBendingVertexDispersion() *
+                   AliMUONReconstructor::GetRecoParam()->GetBendingVertexDispersion() +
+                   (z1 * z1 * lastCluster->GetErrY2() + z2 * z2 * firstCluster->GetErrY2()) / dZ / dZ) /
+                  bendingImpact / bendingImpact + 0.1 * 0.1) * inverseBendingMomentum * inverseBendingMomentum;
+  paramCov(2,4) = - z2 * firstCluster->GetErrY2() * inverseBendingMomentum / bendingImpact / dZ;
+  paramCov(4,2) = paramCov(2,4);
+  paramCov(3,4) = - (z1 * lastCluster->GetErrY2() + z2 * firstCluster->GetErrY2()) * inverseBendingMomentum / bendingImpact / dZ / dZ;
+  paramCov(4,3) = paramCov(3,4);
   
-  
-  // Compute and set track parameters covariances at last cluster as if the first cluster did not exist (used by Kalman only)
-  TMatrixD paramCov2(5,5);
-  paramCov2.Zero();
-  // Non bending plane
-  paramCov2(0,0) = paramCov1(0,0);
-  paramCov2(1,1) = 100.*paramCov1(1,1);
-  // Bending plane
-  paramCov2(2,2) = paramCov1(2,2);
-  paramCov2(3,3) = 100.*paramCov1(3,3);
-  // Inverse bending momentum
-  paramCov2(4,4) = paramCov1(4,4);
   // Set covariances
-  trackParamAtLastCluster.SetCovariances(paramCov2);
+  trackParamAtFirstCluster.SetCovariances(paramCov);
   
-  // Flag clusters as being removable
-  trackParamAtFirstCluster.SetRemovable(kTRUE);
-  trackParamAtLastCluster.SetRemovable(kTRUE);
+  // Compute and set track parameters covariances at last cluster
+  paramCov(1,0) = - paramCov(1,0);
+  paramCov(0,1) = - paramCov(0,1);
+  paramCov(3,2) = - paramCov(3,2);
+  paramCov(2,3) = - paramCov(2,3);
+  paramCov(2,4) = z1 * lastCluster->GetErrY2() * inverseBendingMomentum / bendingImpact / dZ;
+  paramCov(4,2) = paramCov(2,4);
+  trackParamAtLastCluster.SetCovariances(paramCov);
   
   // Add track parameters at clusters
   AddTrackParamAtCluster(trackParamAtFirstCluster,*firstCluster);
@@ -451,7 +430,7 @@ void AliMUONTrack::UpdateCovTrackParamAtCluster()
   //__________________________________________________________________________
 Bool_t AliMUONTrack::IsValid()
 {
-  /// check the validity of the current track (at least one cluster per station)
+  /// check the validity of the current track (at least one cluster per requested station)
   
   Int_t nClusters = GetNClusters();
   AliMUONTrackParam *trackParam;
@@ -460,6 +439,10 @@ Bool_t AliMUONTrack::IsValid()
   for (Int_t i = 0; i < nClusters; i++) {
     trackParam = (AliMUONTrackParam*) fTrackParamAtCluster->UncheckedAt(i);
     
+    // skip unrequested stations
+    while (expectedStation < AliMUONConstants::NTrackingSt() &&
+          !AliMUONReconstructor::GetRecoParam()->RequestStation(expectedStation)) expectedStation++;
+    
     currentStation = trackParam->GetClusterPtr()->GetChamberId()/2;
     
     // missing station
@@ -470,23 +453,25 @@ Bool_t AliMUONTrack::IsValid()
     
   }
   
-  return currentStation == AliMUONConstants::NTrackingSt() - 1;
+  return expectedStation == AliMUONConstants::NTrackingSt();
   
 }
 
   //__________________________________________________________________________
 void AliMUONTrack::TagRemovableClusters() {
   /// Identify clusters that can be removed from the track,
-  /// with the only requirement to have at least 1 cluster per station
+  /// with the only requirement to have at least 1 cluster per requested station
   
   Int_t nClusters = GetNClusters();
   AliMUONTrackParam *trackParam, *nextTrackParam;
   Int_t currentCh, nextCh;
   
-  // reset flags to default
+  // reset flags to kFALSE for all clusters in required station
   for (Int_t i = 0; i < nClusters; i++) {
     trackParam = (AliMUONTrackParam*) fTrackParamAtCluster->UncheckedAt(i);
-    trackParam->SetRemovable(kFALSE);
+    if (AliMUONReconstructor::GetRecoParam()->RequestStation(trackParam->GetClusterPtr()->GetChamberId()/2))
+      trackParam->SetRemovable(kFALSE);
+    else trackParam->SetRemovable(kTRUE);
   }
   
   // loop over track parameters
@@ -949,7 +934,7 @@ Double_t AliMUONTrack::GetNormalizedChi2() const
   
   Double_t numberOfDegFree = (2. * GetNClusters() - 5.);
   if (numberOfDegFree > 0.) return fGlobalChi2 / numberOfDegFree;
-  else return 1.e10;
+  else return fGlobalChi2; // system is under-constraint
 }
 
   //__________________________________________________________________________
index 8c9b561..94fa55d 100644 (file)
@@ -53,9 +53,10 @@ Double_t AliMUONTrackExtrap::GetImpactParamFromBendingMomentum(Double_t bendingM
   
   if (bendingMomentum == 0.) return 1.e10;
   
+  const Double_t kCorrectionFactor = 0.9; // impact parameter is 10% overestimated
   Double_t simpleBPosition = 0.5 * (AliMUONConstants::CoilZ() + AliMUONConstants::YokeZ());
   Double_t simpleBLength = 0.5 * (AliMUONConstants::CoilL() + AliMUONConstants::YokeL());
-  Float_t b[3], x[3] = {0.,0.,(Float_t) simpleBPosition};
+  Float_t b[3], x[3] = {50.,50.,(Float_t) simpleBPosition};
   if (fgkField) fgkField->Field(x,b);
   else {
     cout<<"F-AliMUONTrackExtrap::GetField: fgkField = 0x0"<<endl;
@@ -63,7 +64,7 @@ Double_t AliMUONTrackExtrap::GetImpactParamFromBendingMomentum(Double_t bendingM
   }
   Double_t simpleBValue = (Double_t) b[0];
   
-  return (-0.0003 * simpleBValue * simpleBLength * simpleBPosition / bendingMomentum);
+  return kCorrectionFactor * (-0.0003 * simpleBValue * simpleBLength * simpleBPosition / bendingMomentum);
 }
 
 //__________________________________________________________________________
@@ -76,9 +77,10 @@ Double_t AliMUONTrackExtrap::GetBendingMomentumFromImpactParam(Double_t impactPa
   
   if (impactParam == 0.) return 1.e10;
   
+  const Double_t kCorrectionFactor = 1.1; // bending momentum is 10% underestimated
   Double_t simpleBPosition = 0.5 * (AliMUONConstants::CoilZ() + AliMUONConstants::YokeZ());
   Double_t simpleBLength = 0.5 * (AliMUONConstants::CoilL() + AliMUONConstants::YokeL());
-  Float_t b[3], x[3] = {0.,0.,(Float_t) simpleBPosition};
+  Float_t b[3], x[3] = {50.,50.,(Float_t) simpleBPosition};
   if (fgkField) fgkField->Field(x,b);
   else {
     cout<<"F-AliMUONTrackExtrap::GetField: fgkField = 0x0"<<endl;
@@ -86,7 +88,7 @@ Double_t AliMUONTrackExtrap::GetBendingMomentumFromImpactParam(Double_t impactPa
   }
   Double_t simpleBValue = (Double_t) b[0];
   
-  return (-0.0003 * simpleBValue * simpleBLength * simpleBPosition / impactParam);
+  return kCorrectionFactor * (-0.0003 * simpleBValue * simpleBLength * simpleBPosition / impactParam);
 }
 
 //__________________________________________________________________________
@@ -278,7 +280,7 @@ void AliMUONTrackExtrap::ExtrapToZCov(AliMUONTrackParam* trackParam, Double_t zE
   
   // Get reference to the parameter covariance matrix
   const TMatrixD& kParamCov = trackParam->GetCovariances();
-  
+       
   // Extrapolate track parameters to "zEnd"
   ExtrapToZ(trackParam,zEnd);
   
index 2570f74..59dc538 100644 (file)
@@ -92,14 +92,14 @@ void AliMUONTrackReconstructor::MakeTrackCandidates(AliMUONVClusterStore& cluste
 
   for (Int_t i = firstChamber; i <= lastChamber; ++i ) 
   {
-    fClusterServer.Clusterize(i, clusterStore, AliMpArea());
+    if (AliMUONReconstructor::GetRecoParam()->UseChamber(i)) fClusterServer.Clusterize(i, clusterStore, AliMpArea());
   }
   
   // 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(clusterStore,istat);
+    segments = MakeSegmentsBetweenChambers(clusterStore, 2*istat, 2*istat+1);
     
     // Loop over segments
     for (Int_t iseg=0; iseg<segments->GetEntriesFast(); iseg++) 
@@ -110,19 +110,13 @@ void AliMUONTrackReconstructor::MakeTrackCandidates(AliMUONVClusterStore& cluste
       track = new ((*fRecTracksPtr)[fRecTracksPtr->GetLast()+1]) AliMUONTrack((AliMUONObjectPair*)((*segments)[iseg]));
       fNRecTracks++;
       
-      // Printout for debuging
-      if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructor") >= 2) || (AliLog::GetGlobalDebugLevel() >= 2)) {
-        cout<<endl<<"Track parameter covariances at first cluster:"<<endl;
-        ((AliMUONTrackParam*) track->GetTrackParamAtCluster()->First())->GetCovariances().Print();
-      }
-      
       // Look for compatible cluster(s) in the other station
       if (AliMUONReconstructor::GetRecoParam()->MakeTrackCandidatesFast())
        clusterFound = FollowLinearTrackInStation(*track, clusterStore, 7-istat);
       else clusterFound = FollowTrackInStation(*track, clusterStore, 7-istat);
       
       // Remove track if no cluster found
-      if (!clusterFound) {
+      if (!clusterFound && AliMUONReconstructor::GetRecoParam()->RequestStation(7-istat)) {
         fRecTracksPtr->Remove(track);
        fNRecTracks--;
       }
@@ -144,6 +138,77 @@ void AliMUONTrackReconstructor::MakeTrackCandidates(AliMUONVClusterStore& cluste
 }
 
   //__________________________________________________________________________
+void AliMUONTrackReconstructor::MakeMoreTrackCandidates(AliMUONVClusterStore& clusterStore)
+{
+  /// To make extra track candidates (assuming linear propagation if the flag fgkMakeTrackCandidatesFast is set to kTRUE):
+  /// clustering is supposed to be already done
+  /// Start with segments made of 1 cluster in each of the stations 4 and 5 then follow track in remaining chambers.
+  /// Good candidates are made of at least three clusters if both station are requested (two otherwise).
+  /// Keep only best candidates or all of them according to the flag fgkTrackAllTracks.
+  
+  TClonesArray *segments;
+  AliMUONTrack *track;
+  Int_t iCandidate = 0, iCurrentTrack, nCurrentTracks;
+  Bool_t clusterFound;
+  
+  AliDebug(1,"Enter MakeMoreTrackCandidates");
+  
+  // Double loop over chambers in stations(1..) 4 and 5 to make track candidates
+  for (Int_t ich1 = 6; ich1 <= 7; ich1++) {
+    for (Int_t ich2 = 8; ich2 <= 9; ich2++) {
+      
+      // Make segments in the station
+      segments = MakeSegmentsBetweenChambers(clusterStore, ich1, ich2);
+      
+      // 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
+       iCurrentTrack = fRecTracksPtr->GetLast()+1;
+       track = new ((*fRecTracksPtr)[iCurrentTrack]) AliMUONTrack((AliMUONObjectPair*)((*segments)[iseg]));
+       fNRecTracks++;
+       
+       // Look for compatible cluster(s) in the second chamber of station 5
+       if (AliMUONReconstructor::GetRecoParam()->MakeTrackCandidatesFast())
+         clusterFound = FollowLinearTrackInChamber(*track, clusterStore, 17-ich2);
+       else clusterFound = FollowTrackInChamber(*track, clusterStore, 17-ich2);
+       
+       // skip the original track in case it has been removed
+       if (AliMUONReconstructor::GetRecoParam()->TrackAllTracks() && clusterFound) iCurrentTrack++;
+       
+       // loop over every new tracks
+       nCurrentTracks = fRecTracksPtr->GetLast()+1;
+       while (iCurrentTrack < nCurrentTracks) {
+         track = (AliMUONTrack*) fRecTracksPtr->UncheckedAt(iCurrentTrack);
+         
+         // Look for compatible cluster(s) in the second chamber of station 4
+         if (AliMUONReconstructor::GetRecoParam()->MakeTrackCandidatesFast())
+           FollowLinearTrackInChamber(*track, clusterStore, 13-ich1);
+         else FollowTrackInChamber(*track, clusterStore, 13-ich1);
+         
+         iCurrentTrack++;
+       }
+       
+      }
+      
+      // delete the array of segments
+      delete segments;
+    }
+  }
+  
+  fRecTracksPtr->Compress(); // this is essential before checking tracks
+  
+  // Keep all different tracks or only the best ones as required
+  if (AliMUONReconstructor::GetRecoParam()->TrackAllTracks()) RemoveIdenticalTracks();
+  else RemoveDoubleTracks();
+  
+  AliDebug(1,Form("Number of good candidates = %d",fNRecTracks));
+  
+}
+
+  //__________________________________________________________________________
 void AliMUONTrackReconstructor::FollowTracks(AliMUONVClusterStore& clusterStore)
 {
   /// Follow tracks in stations(1..) 3, 2 and 1
@@ -152,7 +217,6 @@ void AliMUONTrackReconstructor::FollowTracks(AliMUONVClusterStore& clusterStore)
   AliMUONTrack *track, *nextTrack;
   AliMUONTrackParam *trackParam, *nextTrackParam;
   Int_t currentNRecTracks;
-  Bool_t clusterFound;
   
   Double_t sigmaCut2 = AliMUONReconstructor::GetRecoParam()->GetSigmaCutForTracking() *
                        AliMUONReconstructor::GetRecoParam()->GetSigmaCutForTracking();
@@ -172,13 +236,18 @@ void AliMUONTrackReconstructor::FollowTracks(AliMUONVClusterStore& clusterStore)
       // 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) Fit(*track, kFALSE, kTRUE, kTRUE);
+      // If there is no cluster out of station 4 or 5 then use the vertex to better constrain the fit
+      if (((AliMUONTrackParam*) track->GetTrackParamAtCluster()->First())->GetClusterPtr()->GetChamberId() > 5)
+       Fit(*track, kFALSE, kTRUE, kTRUE);
       else Fit(*track, kFALSE, kFALSE, kTRUE);
       
-      // Remove the track if the normalized chi2 is too high
-      if (track->GetNormalizedChi2() > sigmaCut2) {
-       fRecTracksPtr->Remove(track);
+      // remove track with absolute bending momentum out of limits
+      // or if the normalized chi2 is too high
+      Double_t bendingMomentum = TMath::Abs(1. / ((AliMUONTrackParam*)track->GetTrackParamAtCluster()->First())->GetInverseBendingMomentum());
+      if (bendingMomentum < AliMUONReconstructor::GetRecoParam()->GetMinBendingMomentum() ||
+         bendingMomentum > AliMUONReconstructor::GetRecoParam()->GetMaxBendingMomentum() ||
+         track->GetNormalizedChi2() > sigmaCut2) {
+       fRecTracksPtr->Remove(track);
        fNRecTracks--;
        continue;
       }
@@ -201,26 +270,30 @@ void AliMUONTrackReconstructor::FollowTracks(AliMUONVClusterStore& clusterStore)
          
        } else { // or save track parameters on last station only
          
-         // save parameters from fit
          trackParam = (AliMUONTrackParam*) track->GetTrackParamAtCluster()->First();
-         trackParam->SetSmoothParameters(trackParam->GetParameters());
-         trackParam->SetSmoothCovariances(trackParam->GetCovariances());
-         
-         // save parameters extrapolated to the second chamber of the same station if it has been hit
-         nextTrackParam = (AliMUONTrackParam*) track->GetTrackParamAtCluster()->After(trackParam);
-         if (nextTrackParam->GetClusterPtr()->GetChamberId() < 2*(station+2)) {
-           
-           // reset parameters and covariances
-           nextTrackParam->SetParameters(trackParam->GetParameters());
-           nextTrackParam->SetZ(trackParam->GetZ());
-           nextTrackParam->SetCovariances(trackParam->GetCovariances());
+         if (trackParam->GetClusterPtr()->GetChamberId() < 2*(station+2)) {
            
-           // extrapolate them to the z of the corresponding cluster
-           AliMUONTrackExtrap::ExtrapToZCov(nextTrackParam, nextTrackParam->GetClusterPtr()->GetZ());
+           // save parameters from fit
+           trackParam->SetSmoothParameters(trackParam->GetParameters());
+           trackParam->SetSmoothCovariances(trackParam->GetCovariances());
            
-           // save them
-           nextTrackParam->SetSmoothParameters(nextTrackParam->GetParameters());
-           nextTrackParam->SetSmoothCovariances(nextTrackParam->GetCovariances());
+           // save parameters extrapolated to the second chamber of the same station if it has been hit
+           nextTrackParam = (AliMUONTrackParam*) track->GetTrackParamAtCluster()->After(trackParam);
+           if (nextTrackParam->GetClusterPtr()->GetChamberId() < 2*(station+2)) {
+             
+             // reset parameters and covariances
+             nextTrackParam->SetParameters(trackParam->GetParameters());
+             nextTrackParam->SetZ(trackParam->GetZ());
+             nextTrackParam->SetCovariances(trackParam->GetCovariances());
+             
+             // extrapolate them to the z of the corresponding cluster
+             AliMUONTrackExtrap::ExtrapToZCov(nextTrackParam, nextTrackParam->GetClusterPtr()->GetZ());
+             
+             // save them
+             nextTrackParam->SetSmoothParameters(nextTrackParam->GetParameters());
+             nextTrackParam->SetSmoothCovariances(nextTrackParam->GetCovariances());
+             
+           }
            
          }
          
@@ -228,23 +301,32 @@ void AliMUONTrackReconstructor::FollowTracks(AliMUONVClusterStore& clusterStore)
        
       }
       
-      // Printout for debuging
-      if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructor") >= 2) || (AliLog::GetGlobalDebugLevel() >= 2)) {
-        cout<<endl<<"Track parameter covariances at first cluster:"<<endl;
-        ((AliMUONTrackParam*) track->GetTrackParamAtCluster()->First())->GetCovariances().Print();
-      }
-      
       // Look for compatible cluster(s) in station(0..) "station"
-      clusterFound = FollowTrackInStation(*track, clusterStore, station);
-      
-      // Try to recover track if required
-      if (!clusterFound && AliMUONReconstructor::GetRecoParam()->RecoverTracks())
-       clusterFound = RecoverTrack(*track, clusterStore, station);
-      
-      // remove track if no cluster found
-      if (!clusterFound) {
-       fRecTracksPtr->Remove(track);
-       fNRecTracks--;
+      if (!FollowTrackInStation(*track, clusterStore, station)) {
+       
+       // Try to recover track if required
+       if (AliMUONReconstructor::GetRecoParam()->RecoverTracks()) {
+         
+         // work on a copy of the track if this station is not required
+         // to keep the case where no cluster is reconstructed as a possible candidate
+         if (!AliMUONReconstructor::GetRecoParam()->RequestStation(station)) {
+           track = new ((*fRecTracksPtr)[fRecTracksPtr->GetLast()+1]) AliMUONTrack(*track);
+           fNRecTracks++;
+         }
+         
+         // try to recover
+         if (!RecoverTrack(*track, clusterStore, station)) {
+           // remove track if no cluster found
+           fRecTracksPtr->Remove(track);
+           fNRecTracks--;
+         }
+         
+       } else if (AliMUONReconstructor::GetRecoParam()->RequestStation(station)) {
+         // remove track if no cluster found
+         fRecTracksPtr->Remove(track);
+         fNRecTracks--;
+       } 
+       
       }
       
     }
@@ -285,26 +367,30 @@ void AliMUONTrackReconstructor::FollowTracks(AliMUONVClusterStore& clusterStore)
     // save parameters from fit into smoothed parameters to complete track afterward
     if (AliMUONReconstructor::GetRecoParam()->ComplementTracks()) {
       
-      // save parameters from fit
       trackParam = (AliMUONTrackParam*) track->GetTrackParamAtCluster()->First();
-      trackParam->SetSmoothParameters(trackParam->GetParameters());
-      trackParam->SetSmoothCovariances(trackParam->GetCovariances());
-      
-      // save parameters extrapolated to the second chamber of the same station if it has been hit
-      nextTrackParam = (AliMUONTrackParam*) track->GetTrackParamAtCluster()->After(trackParam);
-      if (nextTrackParam->GetClusterPtr()->GetChamberId() < 2) {
-       
-       // reset parameters and covariances
-       nextTrackParam->SetParameters(trackParam->GetParameters());
-       nextTrackParam->SetZ(trackParam->GetZ());
-       nextTrackParam->SetCovariances(trackParam->GetCovariances());
+      if (trackParam->GetClusterPtr()->GetChamberId() < 2) {
        
-       // extrapolate them to the z of the corresponding cluster
-       AliMUONTrackExtrap::ExtrapToZCov(nextTrackParam, nextTrackParam->GetClusterPtr()->GetZ());
+       // save parameters from fit
+       trackParam->SetSmoothParameters(trackParam->GetParameters());
+       trackParam->SetSmoothCovariances(trackParam->GetCovariances());
        
-       // save them
-       nextTrackParam->SetSmoothParameters(nextTrackParam->GetParameters());
-       nextTrackParam->SetSmoothCovariances(nextTrackParam->GetCovariances());
+       // save parameters extrapolated to the second chamber of the same station if it has been hit
+       nextTrackParam = (AliMUONTrackParam*) track->GetTrackParamAtCluster()->After(trackParam);
+       if (nextTrackParam->GetClusterPtr()->GetChamberId() < 2) {
+         
+         // reset parameters and covariances
+         nextTrackParam->SetParameters(trackParam->GetParameters());
+         nextTrackParam->SetZ(trackParam->GetZ());
+         nextTrackParam->SetCovariances(trackParam->GetCovariances());
+         
+         // extrapolate them to the z of the corresponding cluster
+         AliMUONTrackExtrap::ExtrapToZCov(nextTrackParam, nextTrackParam->GetClusterPtr()->GetZ());
+         
+         // save them
+         nextTrackParam->SetSmoothParameters(nextTrackParam->GetParameters());
+         nextTrackParam->SetSmoothCovariances(nextTrackParam->GetCovariances());
+         
+       }
        
       }
       
@@ -319,6 +405,144 @@ void AliMUONTrackReconstructor::FollowTracks(AliMUONVClusterStore& clusterStore)
 }
 
   //__________________________________________________________________________
+Bool_t AliMUONTrackReconstructor::FollowTrackInChamber(AliMUONTrack &trackCandidate, AliMUONVClusterStore& clusterStore, Int_t nextChamber)
+{
+  /// Follow trackCandidate in chamber(0..) nextChamber and search for compatible cluster(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 cluster(s) to the "trackCandidate". Try to add a couple of clusters in priority.
+  AliDebug(1,Form("Enter FollowTrackInChamber(1..) %d", nextChamber+1));
+  
+  Double_t chi2WithOneCluster = 1.e10;
+  Double_t maxChi2WithOneCluster = 2. * AliMUONReconstructor::GetRecoParam()->GetSigmaCutForTracking() *
+                                       AliMUONReconstructor::GetRecoParam()->GetSigmaCutForTracking(); // 2 because 2 quantities in chi2
+  Double_t bestChi2WithOneCluster = maxChi2WithOneCluster;
+  Bool_t foundOneCluster = kFALSE;
+  AliMUONTrack *newTrack = 0x0;
+  AliMUONVCluster *cluster;
+  AliMUONTrackParam extrapTrackParam;
+  AliMUONTrackParam extrapTrackParamAtCh;
+  AliMUONTrackParam extrapTrackParamAtCluster;
+  AliMUONTrackParam bestTrackParamAtCluster;
+  
+  // Get track parameters according to the propagation direction
+  if (nextChamber > 7) extrapTrackParamAtCh = *(AliMUONTrackParam*)trackCandidate.GetTrackParamAtCluster()->Last();
+  else extrapTrackParamAtCh = *(AliMUONTrackParam*)trackCandidate.GetTrackParamAtCluster()->First();
+  
+  // Printout for debuging
+  if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructor") >= 2) || (AliLog::GetGlobalDebugLevel() >= 2)) {
+    cout<<endl<<"Track parameters and covariances at first cluster:"<<endl;
+    extrapTrackParamAtCh.GetParameters().Print();
+    extrapTrackParamAtCh.GetCovariances().Print();
+  }
+  
+  // Add MCS effect
+  AliMUONTrackExtrap::AddMCSEffect(&extrapTrackParamAtCh,AliMUONConstants::ChamberThicknessInX0(),1.);
+  
+  // Add MCS in the missing chamber(s) if any
+  Int_t currentChamber = extrapTrackParamAtCh.GetClusterPtr()->GetChamberId();
+  while (currentChamber > nextChamber + 1) {
+    // extrapolation to the missing chamber
+    currentChamber--;
+    AliMUONTrackExtrap::ExtrapToZCov(&extrapTrackParamAtCh, AliMUONConstants::DefaultChamberZ(currentChamber));
+    // add MCS effect
+    AliMUONTrackExtrap::AddMCSEffect(&extrapTrackParamAtCh,AliMUONConstants::ChamberThicknessInX0(),1.);
+  }
+  
+  //Extrapolate trackCandidate to chamber
+  AliMUONTrackExtrap::ExtrapToZCov(&extrapTrackParamAtCh, AliMUONConstants::DefaultChamberZ(nextChamber));
+  
+  // Printout for debuging
+  if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructor") >= 2) || (AliLog::GetGlobalDebugLevel() >= 2)) {
+    cout<<endl<<"Track parameters and covariances at first cluster extrapolated to z = "<<AliMUONConstants::DefaultChamberZ(nextChamber)<<":"<<endl;
+    extrapTrackParamAtCh.GetParameters().Print();
+    extrapTrackParamAtCh.GetCovariances().Print();
+  }
+  
+  // Printout for debuging
+  if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructor") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
+    cout << "FollowTrackInStation: look for clusters in chamber(1..): " << nextChamber+1 << endl;
+  }
+  
+  // Ask the clustering to reconstruct new clusters around the track position in the current chamber
+  // except for station 4 and 5 that are already entirely clusterized
+  if (AliMUONReconstructor::GetRecoParam()->CombineClusterTrackReco()) {
+    if (nextChamber < 6) AskForNewClustersInChamber(extrapTrackParamAtCh, clusterStore, nextChamber);
+  }
+  
+  // Create iterators to loop over clusters in both chambers
+  TIter next(clusterStore.CreateChamberIterator(nextChamber,nextChamber));
+  
+  // look for cluster in chamber
+  while ( ( cluster = static_cast<AliMUONVCluster*>(next()) ) ) {
+    
+    // try to add the current cluster fast
+    if (!TryOneClusterFast(extrapTrackParamAtCh, cluster)) continue;
+    
+    // try to add the current cluster accuratly
+    chi2WithOneCluster = TryOneCluster(extrapTrackParamAtCh, cluster, extrapTrackParamAtCluster);
+    
+    // if good chi2 then consider to add cluster
+    if (chi2WithOneCluster < maxChi2WithOneCluster) {
+      foundOneCluster = kTRUE;
+      
+      // Printout for debuging
+      if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructor") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
+       cout << "FollowTrackInStation: found one cluster in chamber(1..): " << nextChamber+1
+       << " (Chi2 = " << chi2WithOneCluster << ")" << endl;
+       cluster->Print();
+      }
+      
+      if (AliMUONReconstructor::GetRecoParam()->TrackAllTracks()) {
+       // copy trackCandidate into a new track put at the end of fRecTracksPtr and add the new cluster
+       newTrack = new ((*fRecTracksPtr)[fRecTracksPtr->GetLast()+1]) AliMUONTrack(trackCandidate);
+       UpdateTrack(*newTrack,extrapTrackParamAtCluster);
+       fNRecTracks++;
+       
+       // Printout for debuging
+       if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructor") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
+         cout << "FollowTrackInStation: added one cluster in chamber(1..): " << nextChamber+1 << endl;
+         if (AliLog::GetGlobalDebugLevel() >= 3) newTrack->RecursiveDump();
+       }
+       
+      } else if (chi2WithOneCluster < bestChi2WithOneCluster) {
+       // keep track of the best single cluster except if a couple of clusters has already been found
+       bestChi2WithOneCluster = chi2WithOneCluster;
+       bestTrackParamAtCluster = extrapTrackParamAtCluster;
+      }
+      
+    }
+    
+  }
+  
+  // fill out the best track if required else clean up the fRecTracksPtr array
+  if (!AliMUONReconstructor::GetRecoParam()->TrackAllTracks()) {
+    if (foundOneCluster) {
+      UpdateTrack(trackCandidate,bestTrackParamAtCluster);
+      
+      // Printout for debuging
+      if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructor") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
+        cout << "FollowTrackInStation: added the best cluster in chamber(1..): " << bestTrackParamAtCluster.GetClusterPtr()->GetChamberId()+1 << endl;
+        if (AliLog::GetGlobalDebugLevel() >= 3) newTrack->RecursiveDump();
+      }
+      
+    } else return kFALSE;
+    
+  } else if (foundOneCluster) {
+    
+    // remove obsolete track
+    fRecTracksPtr->Remove(&trackCandidate);
+    fNRecTracks--;
+    
+  } else return kFALSE;
+  
+  return kTRUE;
+  
+}
+
+  //__________________________________________________________________________
 Bool_t AliMUONTrackReconstructor::FollowTrackInStation(AliMUONTrack &trackCandidate, AliMUONVClusterStore& clusterStore, Int_t nextStation)
 {
   /// Follow trackCandidate in station(0..) nextStation and search for compatible cluster(s)
@@ -369,13 +593,22 @@ Bool_t AliMUONTrackReconstructor::FollowTrackInStation(AliMUONTrack &trackCandid
   if (nextStation==4) extrapTrackParamAtCh = *(AliMUONTrackParam*)trackCandidate.GetTrackParamAtCluster()->Last();
   else extrapTrackParamAtCh = *(AliMUONTrackParam*)trackCandidate.GetTrackParamAtCluster()->First();
   
+  // Printout for debuging
+  if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructor") >= 2) || (AliLog::GetGlobalDebugLevel() >= 2)) {
+    cout<<endl<<"Track parameters and covariances at first cluster:"<<endl;
+    extrapTrackParamAtCh.GetParameters().Print();
+    extrapTrackParamAtCh.GetCovariances().Print();
+  }
+  
   // Add MCS effect
   AliMUONTrackExtrap::AddMCSEffect(&extrapTrackParamAtCh,AliMUONConstants::ChamberThicknessInX0(),1.);
   
-  // Add MCS in the missing chamber if any (only 1 chamber can be missing according to tracking criteria)
-  if (ch1 < ch2 && extrapTrackParamAtCh.GetClusterPtr()->GetChamberId() > ch2 + 1) {
+  // Add MCS in the missing chamber(s) if any
+  Int_t currentChamber = extrapTrackParamAtCh.GetClusterPtr()->GetChamberId();
+  while (ch1 < ch2 && currentChamber > ch2 + 1) {
     // extrapolation to the missing chamber
-    AliMUONTrackExtrap::ExtrapToZCov(&extrapTrackParamAtCh, AliMUONConstants::DefaultChamberZ(ch2 + 1));
+    currentChamber--;
+    AliMUONTrackExtrap::ExtrapToZCov(&extrapTrackParamAtCh, AliMUONConstants::DefaultChamberZ(currentChamber));
     // add MCS effect
     AliMUONTrackExtrap::AddMCSEffect(&extrapTrackParamAtCh,AliMUONConstants::ChamberThicknessInX0(),1.);
   }
@@ -385,7 +618,8 @@ Bool_t AliMUONTrackReconstructor::FollowTrackInStation(AliMUONTrack &trackCandid
   
   // Printout for debuging
   if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructor") >= 2) || (AliLog::GetGlobalDebugLevel() >= 2)) {
-    cout<<endl<<"Track parameter covariances at first cluster extrapolated to z = "<<AliMUONConstants::DefaultChamberZ(ch2)<<":"<<endl;
+    cout<<endl<<"Track parameters and covariances at first cluster extrapolated to z = "<<AliMUONConstants::DefaultChamberZ(ch2)<<":"<<endl;
+    extrapTrackParamAtCh.GetParameters().Print();
     extrapTrackParamAtCh.GetCovariances().Print();
   }
   
@@ -421,6 +655,7 @@ Bool_t AliMUONTrackReconstructor::FollowTrackInStation(AliMUONTrack &trackCandid
       if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructor") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
         cout << "FollowTrackInStation: found one cluster in chamber(1..): " << ch2+1
             << " (Chi2 = " << chi2WithOneCluster << ")" << endl;
+       clusterCh2->Print();
         cout << "                      look for second clusters in chamber(1..): " << ch1+1 << " ..." << endl;
       }
       
@@ -455,7 +690,8 @@ Bool_t AliMUONTrackReconstructor::FollowTrackInStation(AliMUONTrack &trackCandid
          // Printout for debuging
          if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructor") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
            cout << "FollowTrackInStation: found second cluster in chamber(1..): " << ch1+1
-                << " (Global Chi2 = " << chi2WithTwoClusters << ")" << endl;
+                << " (Global Chi2 = " << chi2WithTwoClusters << ")" << endl;
+           clusterCh1->Print();
          }
          
          if (AliMUONReconstructor::GetRecoParam()->TrackAllTracks()) {
@@ -516,17 +752,24 @@ Bool_t AliMUONTrackReconstructor::FollowTrackInStation(AliMUONTrack &trackCandid
   // if we want to keep all possible tracks or if no good couple of clusters has been found
   if (AliMUONReconstructor::GetRecoParam()->TrackAllTracks() || !foundTwoClusters) {
     
-    // Printout for debuging
-    if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructor") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
-      cout << "FollowTrackInStation: look for single clusters in chamber(1..): " << ch1+1 << endl;
-    }
-    
     // add MCS effect for next step
     AliMUONTrackExtrap::AddMCSEffect(&extrapTrackParamAtCh,AliMUONConstants::ChamberThicknessInX0(),1.);
     
     //Extrapolate trackCandidate to chamber "ch1"
     AliMUONTrackExtrap::ExtrapToZCov(&extrapTrackParamAtCh, AliMUONConstants::DefaultChamberZ(ch1));
     
+    // Printout for debuging
+    if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructor") >= 2) || (AliLog::GetGlobalDebugLevel() >= 2)) {
+      cout<<endl<<"Track parameters and covariances at first cluster extrapolated to z = "<<AliMUONConstants::DefaultChamberZ(ch1)<<":"<<endl;
+      extrapTrackParamAtCh.GetParameters().Print();
+      extrapTrackParamAtCh.GetCovariances().Print();
+    }
+    
+    // Printout for debuging
+    if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructor") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
+      cout << "FollowTrackInStation: look for single clusters in chamber(1..): " << ch1+1 << endl;
+    }
+    
     // reset cluster iterator of chamber 1
     nextInCh1.Reset();
     iCluster1 = -1;
@@ -542,16 +785,17 @@ Bool_t AliMUONTrackReconstructor::FollowTrackInStation(AliMUONTrack &trackCandid
       
       // try to add the current cluster accuratly
       chi2WithOneCluster = TryOneCluster(extrapTrackParamAtCh, clusterCh1, extrapTrackParamAtCluster1);
-    
+      
       // if good chi2 then consider to add clusterCh1
       // We do not try to attach a cluster in the other chamber too since it has already been done above
       if (chi2WithOneCluster < maxChi2WithOneCluster) {
         foundOneCluster = kTRUE;
-         
+       
        // Printout for debuging
        if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructor") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
          cout << "FollowTrackInStation: found one cluster in chamber(1..): " << ch1+1
               << " (Chi2 = " << chi2WithOneCluster << ")" << endl;
+         clusterCh1->Print();
        }
        
        if (AliMUONReconstructor::GetRecoParam()->TrackAllTracks()) {
@@ -737,7 +981,9 @@ void AliMUONTrackReconstructor::UpdateTrack(AliMUONTrack &track, AliMUONTrackPar
                       deltaY*deltaY / cluster->GetErrY2();
   
   // Flag cluster as being not removable
-  trackParamAtCluster.SetRemovable(kFALSE);
+  if (AliMUONReconstructor::GetRecoParam()->RequestStation(cluster->GetChamberId()/2))
+    trackParamAtCluster.SetRemovable(kFALSE);
+  else trackParamAtCluster.SetRemovable(kTRUE);
   trackParamAtCluster.SetLocalChi2(0.); // --> Local chi2 not used
   
   // Update the chi2 of the new track
@@ -797,25 +1043,32 @@ Bool_t AliMUONTrackReconstructor::RecoverTrack(AliMUONTrack &trackCandidate, Ali
   if (nextStation > 1) return kFALSE;
   
   Int_t worstClusterNumber = -1;
-  Double_t localChi2, worstLocalChi2 = 0.;
+  Double_t localChi2, worstLocalChi2 = -1.;
   
   // Look for the cluster to remove
   for (Int_t clusterNumber = 0; clusterNumber < 2; clusterNumber++) {
     AliMUONTrackParam *trackParamAtCluster = (AliMUONTrackParam*)trackCandidate.GetTrackParamAtCluster()->UncheckedAt(clusterNumber);
     
+    // check if current cluster is in the previous station
+    if (trackParamAtCluster->GetClusterPtr()->GetChamberId()/2 != nextStation+1) break;
+    
     // check if current cluster is removable
     if (!trackParamAtCluster->IsRemovable()) return kFALSE;
     
+    // reset the current cluster as beig not removable if it is on a required station
+    if (AliMUONReconstructor::GetRecoParam()->RequestStation(nextStation+1)) trackParamAtCluster->SetRemovable(kFALSE);
+    
     // Pick up cluster with the worst chi2
     localChi2 = trackParamAtCluster->GetLocalChi2();
     if (localChi2 > worstLocalChi2) {
       worstLocalChi2 = localChi2;
       worstClusterNumber = clusterNumber;
     }
+    
   }
   
-  // Reset best cluster as being NOT removable
-  ((AliMUONTrackParam*)trackCandidate.GetTrackParamAtCluster()->UncheckedAt((worstClusterNumber+1)%2))->SetRemovable(kFALSE);
+  // check if worst cluster found
+  if (worstClusterNumber < 0) return kFALSE;
   
   // Remove the worst cluster
   trackCandidate.RemoveTrackParamAtCluster((AliMUONTrackParam*)trackCandidate.GetTrackParamAtCluster()->UncheckedAt(worstClusterNumber));
@@ -910,15 +1163,14 @@ void AliMUONTrackReconstructor::Fit(AliMUONTrack &track, Bool_t includeMCS, Bool
   gMinuit->SetFCN(TrackChi2);
   
   // Set fitted parameters (!! The order is very important for the covariance matrix !!)
+  // Mandatory limits to avoid NaN values of parameters
   trackParam = (AliMUONTrackParam*) (track.GetTrackParamAtCluster()->First());
-  // could be tried with no limits for the search (min=max=0) ????
-  // mandatory limits in non Bending to avoid NaN values of parameters
+  Double_t maxIBM = 1. / AliMUONReconstructor::GetRecoParam()->GetMinBendingMomentum();
   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(1, "NonBenS", trackParam->GetNonBendingSlope(), 0.001, -1., 1., status);
   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.5, 0.5, status);
+  gMinuit->mnparm(3, "BenS", trackParam->GetBendingSlope(), 0.001, -1.5, 1.5, status);
+  gMinuit->mnparm(4, "InvBenP", trackParam->GetInverseBendingMomentum(), 0.003, -maxIBM, maxIBM, status);
   
   // minimization
   gMinuit->mnexcm("MIGRAD", arg, 0, status);
@@ -1156,7 +1408,7 @@ void AliMUONTrackReconstructor::FinalizeTrack(AliMUONTrack &track)
   if (!track.IsImproved()) track.UpdateCovTrackParamAtCluster();
 }
 
-//__________________________________________________________________________
+  //__________________________________________________________________________
 Bool_t AliMUONTrackReconstructor::RefitTrack(AliMUONTrack &track)
 {
   /// re-fit the given track
index d4b63e8..0048ece 100644 (file)
@@ -31,6 +31,7 @@ class AliMUONTrackReconstructor : public AliMUONVTrackReconstructor
 
   // Functions
   virtual void MakeTrackCandidates(AliMUONVClusterStore& clusterStore);
+  virtual void MakeMoreTrackCandidates(AliMUONVClusterStore& clusterStore);
   virtual void FollowTracks(AliMUONVClusterStore& clusterStore);
   virtual void ComplementTracks(const AliMUONVClusterStore& clusterStore);
   virtual void ImproveTrack(AliMUONTrack &track);
@@ -44,6 +45,7 @@ class AliMUONTrackReconstructor : public AliMUONVTrackReconstructor
   /// Not implemented copy assignment operator
   AliMUONTrackReconstructor& operator=(const AliMUONTrackReconstructor& rhs);
   
+  Bool_t FollowTrackInChamber(AliMUONTrack &trackCandidate, AliMUONVClusterStore& clusterStore, Int_t nextChamber);
   Bool_t FollowTrackInStation(AliMUONTrack &trackCandidate, AliMUONVClusterStore& clusterStore, Int_t nextStation);
   
   Double_t TryTwoClusters(const AliMUONTrackParam &trackParamAtCluster, AliMUONVCluster* cluster2, AliMUONTrackParam &trackParamAtCluster2);
index b996cc4..e15560e 100644 (file)
@@ -68,7 +68,7 @@ void AliMUONTrackReconstructorK::MakeTrackCandidates(AliMUONVClusterStore& clust
 {
   /// To make track candidates (assuming linear propagation if the flag fgkMakeTrackCandidatesFast is set to kTRUE):
   /// Start with segments station(1..) 4 or 5 then follow track in station 5 or 4.
-  /// Good candidates are made of at least three clusters.
+  /// Good candidates are made of at least three clusters if both station are requested (two otherwise).
   /// Keep only best candidates or all of them according to the flag fgkTrackAllTracks.
   
   TClonesArray *segments;
@@ -90,14 +90,14 @@ void AliMUONTrackReconstructorK::MakeTrackCandidates(AliMUONVClusterStore& clust
   
   for (Int_t i = firstChamber; i <= lastChamber; ++i ) 
   {
-    fClusterServer.Clusterize(i, clusterStore, AliMpArea());
+    if (AliMUONReconstructor::GetRecoParam()->UseChamber(i)) fClusterServer.Clusterize(i, clusterStore, AliMpArea());
   }
   
   // 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(clusterStore, istat);
+    segments = MakeSegmentsBetweenChambers(clusterStore, 2*istat, 2*istat+1);
     
     // Loop over segments
     for (Int_t iseg=0; iseg<segments->GetEntriesFast(); iseg++) {
@@ -107,26 +107,25 @@ void AliMUONTrackReconstructorK::MakeTrackCandidates(AliMUONVClusterStore& clust
       track = new ((*fRecTracksPtr)[fRecTracksPtr->GetLast()+1]) AliMUONTrack((AliMUONObjectPair*)((*segments)[iseg]));
       fNRecTracks++;
       
-      // Printout for debuging
-      if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 2) || (AliLog::GetGlobalDebugLevel() >= 2)) {
-        cout<<endl<<"Track parameter covariances at first cluster:"<<endl;
-        ((AliMUONTrackParam*) (track->GetTrackParamAtCluster()->First()))->GetCovariances().Print();
-      }
-      
       // Look for compatible cluster(s) in the other station
       if (AliMUONReconstructor::GetRecoParam()->MakeTrackCandidatesFast())
        clusterFound = FollowLinearTrackInStation(*track, clusterStore, 7-istat);
       else {
         // First recompute track parameters and covariances on station(1..) 5 using Kalman filter
         // (to make sure all tracks are treated in the same way)
-        if (istat == 4) RetraceTrack(*track, kFALSE);
+        if (istat == 4) RetraceTrack(*track, kTRUE);
        clusterFound = FollowTrackInStation(*track, clusterStore, 7-istat);
       }
       
-      // Remove track if no cluster found
+      // Remove track if no cluster found on a requested station
       if (!clusterFound) {
-        fRecTracksPtr->Remove(track);
-       fNRecTracks--;
+       if (AliMUONReconstructor::GetRecoParam()->RequestStation(7-istat)) {
+          fRecTracksPtr->Remove(track);
+         fNRecTracks--;
+       } else if (istat == 3 && !AliMUONReconstructor::GetRecoParam()->MakeTrackCandidatesFast()) {
+         // update track parameters and covariances using Kalman filter
+         RetraceTrack(*track, kTRUE);
+       }
       }
       
     }
@@ -168,6 +167,98 @@ void AliMUONTrackReconstructorK::MakeTrackCandidates(AliMUONVClusterStore& clust
 }
 
   //__________________________________________________________________________
+void AliMUONTrackReconstructorK::MakeMoreTrackCandidates(AliMUONVClusterStore& clusterStore)
+{
+  /// To make extra track candidates (assuming linear propagation if the flag fgkMakeTrackCandidatesFast is set to kTRUE):
+  /// clustering is supposed to be already done
+  /// Start with segments made of 1 cluster in each of the stations 4 and 5 then follow track in remaining chambers.
+  /// Good candidates are made of at least three clusters if both station are requested (two otherwise).
+  /// Keep only best candidates or all of them according to the flag fgkTrackAllTracks.
+  
+  TClonesArray *segments;
+  AliMUONTrack *track;
+  Int_t iCandidate = 0, iCurrentTrack, nCurrentTracks;
+  Int_t initialNRecTracks = fNRecTracks;
+  Bool_t clusterFound;
+  
+  AliDebug(1,"Enter MakeMoreTrackCandidates");
+  
+  // Double loop over chambers in stations(1..) 4 and 5 to make track candidates
+  for (Int_t ich1 = 6; ich1 <= 7; ich1++) {
+    for (Int_t ich2 = 8; ich2 <= 9; ich2++) {
+      
+      // Make segments between ch1 and ch2
+      segments = MakeSegmentsBetweenChambers(clusterStore, ich1, ich2);
+      
+      // 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
+       iCurrentTrack = fRecTracksPtr->GetLast()+1;
+       track = new ((*fRecTracksPtr)[iCurrentTrack]) AliMUONTrack((AliMUONObjectPair*)((*segments)[iseg]));
+       fNRecTracks++;
+       
+       // Look for compatible cluster(s) in the second chamber of station 5
+       if (AliMUONReconstructor::GetRecoParam()->MakeTrackCandidatesFast())
+         clusterFound = FollowLinearTrackInChamber(*track, clusterStore, 17-ich2);
+       else clusterFound = FollowTrackInChamber(*track, clusterStore, 17-ich2);
+       
+       // skip the original track in case it has been removed
+       if (AliMUONReconstructor::GetRecoParam()->TrackAllTracks() && clusterFound) iCurrentTrack++;
+       
+       // loop over every new tracks
+       nCurrentTracks = fRecTracksPtr->GetLast()+1;
+       while (iCurrentTrack < nCurrentTracks) {
+         track = (AliMUONTrack*) fRecTracksPtr->UncheckedAt(iCurrentTrack);
+         
+         // Look for compatible cluster(s) in the second chamber of station 4
+         if (AliMUONReconstructor::GetRecoParam()->MakeTrackCandidatesFast())
+           FollowLinearTrackInChamber(*track, clusterStore, 13-ich1);
+         else FollowTrackInChamber(*track, clusterStore, 13-ich1);
+         
+         iCurrentTrack++;
+       }
+       
+      }
+      
+      // delete the array of segments
+      delete segments;
+    }
+  }
+  
+  fRecTracksPtr->Compress(); // this is essential before checking tracks
+  
+  // Retrace tracks using Kalman filter
+  for (Int_t iRecTrack = initialNRecTracks; iRecTrack < fNRecTracks; iRecTrack++) {
+    track = (AliMUONTrack*) fRecTracksPtr->UncheckedAt(iRecTrack);
+    
+    // Recompute track parameters and covariances using Kalman filter
+    RetraceTrack(*track,kTRUE);
+    
+    // Remove the track if the normalized chi2 is too high
+    // (only if the tracking has been done without magnetic field)
+    if (AliMUONReconstructor::GetRecoParam()->MakeTrackCandidatesFast() &&
+       track->GetNormalizedChi2() > AliMUONReconstructor::GetRecoParam()->GetSigmaCutForTracking() *
+                                    AliMUONReconstructor::GetRecoParam()->GetSigmaCutForTracking()) {
+      fRecTracksPtr->Remove(track);
+      fNRecTracks--;
+    }
+    
+  }
+  
+  // this is essential before checking tracks
+  if (AliMUONReconstructor::GetRecoParam()->MakeTrackCandidatesFast()) fRecTracksPtr->Compress();
+  
+  // Keep all different tracks or only the best ones as required
+  if (AliMUONReconstructor::GetRecoParam()->TrackAllTracks()) RemoveIdenticalTracks();
+  else RemoveDoubleTracks();
+  
+  AliDebug(1,Form("Number of good candidates = %d",fNRecTracks));
+  
+}
+
+  //__________________________________________________________________________
 void AliMUONTrackReconstructorK::RetraceTrack(AliMUONTrack &trackCandidate, Bool_t resetSeed)
 {
   /// Re-run the kalman filter from the most downstream cluster to the most uptream one
@@ -199,7 +290,8 @@ void AliMUONTrackReconstructorK::RetraceTrack(AliMUONTrack &trackCandidate, Bool
     lastTrackParam->SetNonBendingSlope((x1 - x2) / dZ);
     lastTrackParam->SetBendingSlope((y1 - y2) / dZ);
     Double_t bendingImpact = y2 - z2 * lastTrackParam->GetBendingSlope();
-    lastTrackParam->SetInverseBendingMomentum(1. / AliMUONTrackExtrap::GetBendingMomentumFromImpactParam(bendingImpact));
+    Double_t inverseBendingMomentum = 1. / AliMUONTrackExtrap::GetBendingMomentumFromImpactParam(bendingImpact);
+    lastTrackParam->SetInverseBendingMomentum(inverseBendingMomentum);
     
     // => Reset track parameter covariances at last cluster (as if the other clusters did not exist)
     TMatrixD lastParamCov(5,5);
@@ -210,8 +302,11 @@ void AliMUONTrackReconstructorK::RetraceTrack(AliMUONTrack &trackCandidate, Bool
     // Bending plane
     lastParamCov(2,2) = cluster2->GetErrY2();
     lastParamCov(3,3) = 100. * ( cluster1->GetErrY2() + cluster2->GetErrY2() ) / dZ / dZ;
-    // Inverse bending momentum (50% error)
-    lastParamCov(4,4) = 0.5*lastTrackParam->GetInverseBendingMomentum() * 0.5*lastTrackParam->GetInverseBendingMomentum();
+    // Inverse bending momentum (vertex resolution + bending slope resolution + 10% error on dipole parameters+field)
+    lastParamCov(4,4) = ((AliMUONReconstructor::GetRecoParam()->GetBendingVertexDispersion() *
+                         AliMUONReconstructor::GetRecoParam()->GetBendingVertexDispersion() +
+                         (z1 * z1 * cluster2->GetErrY2() + z2 * z2 * cluster1->GetErrY2()) / dZ / dZ) /
+                        bendingImpact / bendingImpact + 0.1 * 0.1) * inverseBendingMomentum * inverseBendingMomentum;
     lastTrackParam->SetCovariances(lastParamCov);
     
     // Reset the track chi2
@@ -256,7 +351,7 @@ void AliMUONTrackReconstructorK::RetracePartialTrack(AliMUONTrack &trackCandidat
     // reset propagator for smoother
     if (AliMUONReconstructor::GetRecoParam()->UseSmoother()) trackParamAtCluster->ResetPropagator();
     
-    // add MCS in missing chambers if any (at most 2 chambers can be missing according to tracking criteria)
+    // add MCS in missing chambers if any
     currentChamber = trackParamAtCluster->GetClusterPtr()->GetChamberId();
     while (currentChamber < expectedChamber) {
       // extrapolation to the missing chamber (update the propagator)
@@ -279,7 +374,7 @@ void AliMUONTrackReconstructorK::RetracePartialTrack(AliMUONTrack &trackCandidat
       trackParamAtCluster->SetExtrapCovariances(trackParamAtCluster->GetCovariances());
     }
     
-    // Compute new track parameters including "clusterCh2" using kalman filter
+    // Compute new track parameters using kalman filter
     addChi2TrackAtCluster = RunKalmanFilter(*trackParamAtCluster);
     
     // Update the track chi2
@@ -307,7 +402,6 @@ void AliMUONTrackReconstructorK::FollowTracks(AliMUONVClusterStore& clusterStore
   
   AliMUONTrack *track;
   Int_t currentNRecTracks;
-  Bool_t clusterFound;
   
   for (Int_t station = 2; station >= 0; station--) {
     
@@ -321,23 +415,32 @@ void AliMUONTrackReconstructorK::FollowTracks(AliMUONVClusterStore& clusterStore
       
       track = (AliMUONTrack*) fRecTracksPtr->UncheckedAt(iRecTrack);
       
-      // Printout for debuging
-      if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 2) || (AliLog::GetGlobalDebugLevel() >= 2)) {
-        cout<<endl<<"Track parameter covariances at first cluster:"<<endl;
-        ((AliMUONTrackParam*) (track->GetTrackParamAtCluster()->First()))->GetCovariances().Print();
-      }
-      
       // Look for compatible cluster(s) in station(0..) "station"
-      clusterFound = FollowTrackInStation(*track, clusterStore, station);
-      
-      // Try to recover track if required
-      if (!clusterFound && AliMUONReconstructor::GetRecoParam()->RecoverTracks())
-       clusterFound = RecoverTrack(*track, clusterStore, station);
-      
-      // remove track if no cluster found
-      if (!clusterFound) {
-       fRecTracksPtr->Remove(track);
-       fNRecTracks--;
+      if (!FollowTrackInStation(*track, clusterStore, station)) {
+       
+       // Try to recover track if required
+       if (AliMUONReconstructor::GetRecoParam()->RecoverTracks()) {
+         
+         // work on a copy of the track if this station is not required
+         // to keep the case where no cluster is reconstructed as a possible candidate
+         if (!AliMUONReconstructor::GetRecoParam()->RequestStation(station)) {
+           track = new ((*fRecTracksPtr)[fRecTracksPtr->GetLast()+1]) AliMUONTrack(*track);
+           fNRecTracks++;
+         }
+         
+         // try to recover
+         if (!RecoverTrack(*track, clusterStore, station)) {
+           // remove track if no cluster found
+           fRecTracksPtr->Remove(track);
+           fNRecTracks--;
+         }
+         
+       } else if (AliMUONReconstructor::GetRecoParam()->RequestStation(station)) {
+         // remove track if no cluster found
+         fRecTracksPtr->Remove(track);
+         fNRecTracks--;
+       } 
+       
       }
       
     }
@@ -352,6 +455,168 @@ void AliMUONTrackReconstructorK::FollowTracks(AliMUONVClusterStore& clusterStore
 }
 
   //__________________________________________________________________________
+Bool_t AliMUONTrackReconstructorK::FollowTrackInChamber(AliMUONTrack &trackCandidate, AliMUONVClusterStore& clusterStore, Int_t nextChamber)
+{
+  /// Follow trackCandidate in chamber(0..) nextChamber and search for compatible cluster(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 cluster(s) to the "trackCandidate". Try to add a couple of clusters in priority.
+  /// return kTRUE if new cluster(s) have been found (otherwise return kFALSE)
+  AliDebug(1,Form("Enter FollowTrackInChamber(1..) %d", nextChamber+1));
+  
+  Double_t bendingMomentum;
+  Double_t chi2OfCluster;
+  Double_t maxChi2OfCluster = 2. * AliMUONReconstructor::GetRecoParam()->GetSigmaCutForTracking() *
+                                  AliMUONReconstructor::GetRecoParam()->GetSigmaCutForTracking(); // 2 because 2 quantities in chi2
+  Double_t addChi2TrackAtCluster;
+  Double_t bestAddChi2TrackAtCluster = 1.e10;
+  Bool_t foundOneCluster = kFALSE;
+  AliMUONTrack *newTrack = 0x0;
+  AliMUONVCluster *cluster;
+  AliMUONTrackParam extrapTrackParamAtCh;
+  AliMUONTrackParam extrapTrackParamAtCluster;
+  AliMUONTrackParam bestTrackParamAtCluster;
+  
+  // Get track parameters according to the propagation direction
+  if (nextChamber > 7) extrapTrackParamAtCh = *(AliMUONTrackParam*)trackCandidate.GetTrackParamAtCluster()->Last();
+  else extrapTrackParamAtCh = *(AliMUONTrackParam*)trackCandidate.GetTrackParamAtCluster()->First();
+  
+  // Printout for debuging
+  if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 2) || (AliLog::GetGlobalDebugLevel() >= 2)) {
+    cout<<endl<<"Track parameters and covariances at first cluster:"<<endl;
+    extrapTrackParamAtCh.GetParameters().Print();
+    extrapTrackParamAtCh.GetCovariances().Print();
+  }
+  
+  // Add MCS effect
+  AliMUONTrackExtrap::AddMCSEffect(&extrapTrackParamAtCh,AliMUONConstants::ChamberThicknessInX0(),1.);
+  
+  // reset propagator for smoother
+  if (AliMUONReconstructor::GetRecoParam()->UseSmoother()) extrapTrackParamAtCh.ResetPropagator();
+  
+  // Add MCS in the missing chamber(s) if any
+  Int_t currentChamber = extrapTrackParamAtCh.GetClusterPtr()->GetChamberId();
+  while (currentChamber > nextChamber + 1) {
+    // extrapolation to the missing chamber
+    currentChamber--;
+    AliMUONTrackExtrap::ExtrapToZCov(&extrapTrackParamAtCh, AliMUONConstants::DefaultChamberZ(currentChamber),
+                                    AliMUONReconstructor::GetRecoParam()->UseSmoother());
+    // add MCS effect
+    AliMUONTrackExtrap::AddMCSEffect(&extrapTrackParamAtCh,AliMUONConstants::ChamberThicknessInX0(),1.);
+  }
+  
+  //Extrapolate trackCandidate to chamber
+  AliMUONTrackExtrap::ExtrapToZCov(&extrapTrackParamAtCh, AliMUONConstants::DefaultChamberZ(nextChamber),
+                                  AliMUONReconstructor::GetRecoParam()->UseSmoother());
+  
+  // Printout for debuging
+  if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 2) || (AliLog::GetGlobalDebugLevel() >= 2)) {
+    cout<<endl<<"Track parameters and covariances at first cluster extrapolated to z = "<<AliMUONConstants::DefaultChamberZ(nextChamber)<<":"<<endl;
+    extrapTrackParamAtCh.GetParameters().Print();
+    extrapTrackParamAtCh.GetCovariances().Print();
+  }
+  
+  // Printout for debuging
+  if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
+    cout << "FollowTrackInChamber: look for clusters in chamber(1..): " << nextChamber+1 << endl;
+  }
+  
+  // Ask the clustering to reconstruct new clusters around the track position in the current chamber
+  // except for station 4 and 5 that are already entirely clusterized
+  if (AliMUONReconstructor::GetRecoParam()->CombineClusterTrackReco()) {
+    if (nextChamber < 6) AskForNewClustersInChamber(extrapTrackParamAtCh, clusterStore, nextChamber);
+  }
+  
+  // Create iterators to loop over clusters in both chambers
+  TIter next(clusterStore.CreateChamberIterator(nextChamber,nextChamber));
+  
+  // look for candidates in chamber
+  while ( ( cluster = static_cast<AliMUONVCluster*>(next()) ) ) {
+    
+    // try to add the current cluster fast
+    if (!TryOneClusterFast(extrapTrackParamAtCh, cluster)) continue;
+    
+    // try to add the current cluster accuratly
+    chi2OfCluster = TryOneCluster(extrapTrackParamAtCh, cluster, extrapTrackParamAtCluster,
+                                 AliMUONReconstructor::GetRecoParam()->UseSmoother());
+    
+    // if good chi2 then consider to add cluster
+    if (chi2OfCluster < maxChi2OfCluster) {
+      foundOneCluster = kTRUE;
+      
+      // Printout for debuging
+      if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
+       cout << "FollowTrackInChamber: found one cluster in chamber(1..): " << nextChamber+1
+       << " (Chi2 = " << chi2OfCluster << ")" << endl;
+       cluster->Print();
+      }
+      
+      if (AliMUONReconstructor::GetRecoParam()->UseSmoother()) {
+       // save extrapolated parameters for smoother
+       extrapTrackParamAtCluster.SetExtrapParameters(extrapTrackParamAtCluster.GetParameters());
+       
+       // save extrapolated covariance matrix for smoother
+       extrapTrackParamAtCluster.SetExtrapCovariances(extrapTrackParamAtCluster.GetCovariances());
+      }
+      
+      // Compute new track parameters including new cluster using kalman filter
+      addChi2TrackAtCluster = RunKalmanFilter(extrapTrackParamAtCluster);
+      
+      // skip track with absolute bending momentum out of limits
+      bendingMomentum = TMath::Abs(1. / extrapTrackParamAtCluster.GetInverseBendingMomentum());
+      if (bendingMomentum < AliMUONReconstructor::GetRecoParam()->GetMinBendingMomentum() ||
+         bendingMomentum > AliMUONReconstructor::GetRecoParam()->GetMaxBendingMomentum()) continue;
+      
+      if (AliMUONReconstructor::GetRecoParam()->TrackAllTracks()) {
+       // copy trackCandidate into a new track put at the end of fRecTracksPtr and add the new cluster
+       newTrack = new ((*fRecTracksPtr)[fRecTracksPtr->GetLast()+1]) AliMUONTrack(trackCandidate);
+       UpdateTrack(*newTrack,extrapTrackParamAtCluster,addChi2TrackAtCluster);
+       fNRecTracks++;
+       
+       // Printout for debuging
+       if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
+         cout << "FollowTrackInChamber: added one cluster in chamber(1..): " << nextChamber+1 << endl;
+         if (AliLog::GetGlobalDebugLevel() >= 3) newTrack->RecursiveDump();
+       }
+       
+      } else if (addChi2TrackAtCluster < bestAddChi2TrackAtCluster) {
+       // keep track of the best cluster
+       bestAddChi2TrackAtCluster = addChi2TrackAtCluster;
+       bestTrackParamAtCluster = extrapTrackParamAtCluster;
+      }
+      
+    }
+    
+  }
+  
+  // fill out the best track if required else clean up the fRecTracksPtr array
+  if (!AliMUONReconstructor::GetRecoParam()->TrackAllTracks()) {
+    if (foundOneCluster) {
+      UpdateTrack(trackCandidate,bestTrackParamAtCluster,bestAddChi2TrackAtCluster);
+      
+      // Printout for debuging
+      if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
+        cout << "FollowTrackInChamber: added the best cluster in chamber(1..): " << bestTrackParamAtCluster.GetClusterPtr()->GetChamberId()+1 << endl;
+        if (AliLog::GetGlobalDebugLevel() >= 3) newTrack->RecursiveDump();
+      }
+      
+    } else return kFALSE;
+    
+  } else if (foundOneCluster) {
+    
+    // remove obsolete track
+    fRecTracksPtr->Remove(&trackCandidate);
+    fNRecTracks--;
+    
+  } else return kFALSE;
+  
+  return kTRUE;
+  
+}
+
+  //__________________________________________________________________________
 Bool_t AliMUONTrackReconstructorK::FollowTrackInStation(AliMUONTrack &trackCandidate, AliMUONVClusterStore& clusterStore, Int_t nextStation)
 {
   /// Follow trackCandidate in station(0..) nextStation and search for compatible cluster(s)
@@ -375,6 +640,7 @@ Bool_t AliMUONTrackReconstructorK::FollowTrackInStation(AliMUONTrack &trackCandi
     ch2 = 2*nextStation+1;
   }
   
+  Double_t bendingMomentum;
   Double_t chi2OfCluster;
   Double_t maxChi2OfCluster = 2. * AliMUONReconstructor::GetRecoParam()->GetSigmaCutForTracking() *
                                   AliMUONReconstructor::GetRecoParam()->GetSigmaCutForTracking(); // 2 because 2 quantities in chi2
@@ -403,16 +669,25 @@ Bool_t AliMUONTrackReconstructorK::FollowTrackInStation(AliMUONTrack &trackCandi
   if (nextStation==4) extrapTrackParamAtCh = *(AliMUONTrackParam*)trackCandidate.GetTrackParamAtCluster()->Last();
   else extrapTrackParamAtCh = *(AliMUONTrackParam*)trackCandidate.GetTrackParamAtCluster()->First();
   
+  // Printout for debuging
+  if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 2) || (AliLog::GetGlobalDebugLevel() >= 2)) {
+    cout<<endl<<"Track parameters and covariances at first cluster:"<<endl;
+    extrapTrackParamAtCh.GetParameters().Print();
+    extrapTrackParamAtCh.GetCovariances().Print();
+  }
+  
   // Add MCS effect
   AliMUONTrackExtrap::AddMCSEffect(&extrapTrackParamAtCh,AliMUONConstants::ChamberThicknessInX0(),1.);
   
   // reset propagator for smoother
   if (AliMUONReconstructor::GetRecoParam()->UseSmoother()) extrapTrackParamAtCh.ResetPropagator();
   
-  // Add MCS in the missing chamber if any (only 1 chamber can be missing according to tracking criteria)
-  if (ch1 < ch2 && extrapTrackParamAtCh.GetClusterPtr()->GetChamberId() > ch2 + 1) {
+  // Add MCS in the missing chamber(s) if any
+  Int_t currentChamber = extrapTrackParamAtCh.GetClusterPtr()->GetChamberId();
+  while (ch1 < ch2 && currentChamber > ch2 + 1) {
     // extrapolation to the missing chamber
-    AliMUONTrackExtrap::ExtrapToZCov(&extrapTrackParamAtCh, AliMUONConstants::DefaultChamberZ(ch2 + 1),
+    currentChamber--;
+    AliMUONTrackExtrap::ExtrapToZCov(&extrapTrackParamAtCh, AliMUONConstants::DefaultChamberZ(currentChamber),
                                     AliMUONReconstructor::GetRecoParam()->UseSmoother());
     // add MCS effect
     AliMUONTrackExtrap::AddMCSEffect(&extrapTrackParamAtCh,AliMUONConstants::ChamberThicknessInX0(),1.);
@@ -424,7 +699,8 @@ Bool_t AliMUONTrackReconstructorK::FollowTrackInStation(AliMUONTrack &trackCandi
   
   // Printout for debuging
   if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 2) || (AliLog::GetGlobalDebugLevel() >= 2)) {
-    cout<<endl<<"Track parameter covariances at first cluster extrapolated to z = "<<AliMUONConstants::DefaultChamberZ(ch2)<<":"<<endl;
+    cout<<endl<<"Track parameters and covariances at first cluster extrapolated to z = "<<AliMUONConstants::DefaultChamberZ(ch2)<<":"<<endl;
+    extrapTrackParamAtCh.GetParameters().Print();
     extrapTrackParamAtCh.GetCovariances().Print();
   }
   
@@ -461,6 +737,7 @@ Bool_t AliMUONTrackReconstructorK::FollowTrackInStation(AliMUONTrack &trackCandi
       if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
         cout << "FollowTrackInStation: found one cluster in chamber(1..): " << ch2+1
             << " (Chi2 = " << chi2OfCluster << ")" << endl;
+       clusterCh2->Print();
         cout << "                      look for second clusters in chamber(1..): " << ch1+1 << " ..." << endl;
       }
       
@@ -475,6 +752,11 @@ Bool_t AliMUONTrackReconstructorK::FollowTrackInStation(AliMUONTrack &trackCandi
       // Compute new track parameters including "clusterCh2" using kalman filter
       addChi2TrackAtCluster2 = RunKalmanFilter(extrapTrackParamAtCluster2);
       
+      // skip track with absolute bending momentum out of limits
+      bendingMomentum = TMath::Abs(1. / extrapTrackParamAtCluster2.GetInverseBendingMomentum());
+      if (bendingMomentum < AliMUONReconstructor::GetRecoParam()->GetMinBendingMomentum() ||
+         bendingMomentum > AliMUONReconstructor::GetRecoParam()->GetMaxBendingMomentum()) continue;
+       
       // copy new track parameters for next step
       extrapTrackParam = extrapTrackParamAtCluster2;
       
@@ -501,7 +783,7 @@ Bool_t AliMUONTrackReconstructorK::FollowTrackInStation(AliMUONTrack &trackCandi
        
        // try to add the current cluster accuratly
        chi2OfCluster = TryOneCluster(extrapTrackParam, clusterCh1, extrapTrackParamAtCluster1,
-                                         AliMUONReconstructor::GetRecoParam()->UseSmoother());
+                                     AliMUONReconstructor::GetRecoParam()->UseSmoother());
        
        // if good chi2 then consider to add the 2 clusters to the "trackCandidate"
        if (chi2OfCluster < maxChi2OfCluster) {
@@ -511,7 +793,8 @@ Bool_t AliMUONTrackReconstructorK::FollowTrackInStation(AliMUONTrack &trackCandi
          // Printout for debuging
          if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
            cout << "FollowTrackInStation: found one cluster in chamber(1..): " << ch1+1
-                << " (Chi2 = " << chi2OfCluster << ")" << endl;
+                << " (Chi2 = " << chi2OfCluster << ")" << endl;
+           clusterCh1->Print();
          }
           
           if (AliMUONReconstructor::GetRecoParam()->UseSmoother()) {
@@ -525,6 +808,11 @@ Bool_t AliMUONTrackReconstructorK::FollowTrackInStation(AliMUONTrack &trackCandi
           // Compute new track parameters including "clusterCh1" using kalman filter
           addChi2TrackAtCluster1 = RunKalmanFilter(extrapTrackParamAtCluster1);
           
+         // skip track with absolute bending momentum out of limits
+         bendingMomentum = TMath::Abs(1. / extrapTrackParamAtCluster1.GetInverseBendingMomentum());
+         if (bendingMomentum < AliMUONReconstructor::GetRecoParam()->GetMinBendingMomentum() ||
+             bendingMomentum > AliMUONReconstructor::GetRecoParam()->GetMaxBendingMomentum()) continue;
+         
          if (AliMUONReconstructor::GetRecoParam()->TrackAllTracks()) {
            // copy trackCandidate into a new track put at the end of fRecTracksPtr and add the new clusters
             newTrack = new ((*fRecTracksPtr)[fRecTracksPtr->GetLast()+1]) AliMUONTrack(trackCandidate);
@@ -592,11 +880,6 @@ Bool_t AliMUONTrackReconstructorK::FollowTrackInStation(AliMUONTrack &trackCandi
   // if we want to keep all possible tracks or if no good couple of clusters has been found
   if (AliMUONReconstructor::GetRecoParam()->TrackAllTracks() || !foundTwoClusters) {
     
-    // Printout for debuging
-    if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
-      cout << "FollowTrackInStation: look for single clusters in chamber(1..): " << ch1+1 << endl;
-    }
-    
     // add MCS effect for next step
     AliMUONTrackExtrap::AddMCSEffect(&extrapTrackParamAtCh,AliMUONConstants::ChamberThicknessInX0(),1.);
     
@@ -604,6 +887,18 @@ Bool_t AliMUONTrackReconstructorK::FollowTrackInStation(AliMUONTrack &trackCandi
     AliMUONTrackExtrap::ExtrapToZCov(&extrapTrackParamAtCh, AliMUONConstants::DefaultChamberZ(ch1),
                                     AliMUONReconstructor::GetRecoParam()->UseSmoother());
     
+    // Printout for debuging
+    if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 2) || (AliLog::GetGlobalDebugLevel() >= 2)) {
+      cout<<endl<<"Track parameters and covariances at first cluster extrapolated to z = "<<AliMUONConstants::DefaultChamberZ(ch1)<<":"<<endl;
+      extrapTrackParamAtCh.GetParameters().Print();
+      extrapTrackParamAtCh.GetCovariances().Print();
+    }
+    
+    // Printout for debuging
+    if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
+      cout << "FollowTrackInStation: look for single clusters in chamber(1..): " << ch1+1 << endl;
+    }
+    
     // reset cluster iterator of chamber 1
     nextInCh1.Reset();
     iCluster1 = -1;
@@ -630,6 +925,7 @@ Bool_t AliMUONTrackReconstructorK::FollowTrackInStation(AliMUONTrack &trackCandi
        if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
          cout << "FollowTrackInStation: found one cluster in chamber(1..): " << ch1+1
               << " (Chi2 = " << chi2OfCluster << ")" << endl;
+         clusterCh1->Print();
        }
         
        if (AliMUONReconstructor::GetRecoParam()->UseSmoother()) {
@@ -643,6 +939,11 @@ Bool_t AliMUONTrackReconstructorK::FollowTrackInStation(AliMUONTrack &trackCandi
         // Compute new track parameters including "clusterCh1" using kalman filter
         addChi2TrackAtCluster1 = RunKalmanFilter(extrapTrackParamAtCluster1);
         
+       // skip track with absolute bending momentum out of limits
+       bendingMomentum = TMath::Abs(1. / extrapTrackParamAtCluster1.GetInverseBendingMomentum());
+       if (bendingMomentum < AliMUONReconstructor::GetRecoParam()->GetMinBendingMomentum() ||
+           bendingMomentum > AliMUONReconstructor::GetRecoParam()->GetMaxBendingMomentum()) continue;
+       
        if (AliMUONReconstructor::GetRecoParam()->TrackAllTracks()) {
          // copy trackCandidate into a new track put at the end of fRecTracksPtr and add the new cluster
          newTrack = new ((*fRecTracksPtr)[fRecTracksPtr->GetLast()+1]) AliMUONTrack(trackCandidate);
@@ -679,7 +980,7 @@ Bool_t AliMUONTrackReconstructorK::FollowTrackInStation(AliMUONTrack &trackCandi
       // if we are arrived on station(1..) 5, recompute track parameters and covariances starting from this station
       // (going in the right direction)
       if (nextStation == 4) RetraceTrack(trackCandidate,kTRUE);
-
+      
       // Printout for debuging
       if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
         cout << "FollowTrackInStation: added the two best clusters in station(1..): " << nextStation+1 << endl;
@@ -692,7 +993,7 @@ Bool_t AliMUONTrackReconstructorK::FollowTrackInStation(AliMUONTrack &trackCandi
       // if we are arrived on station(1..) 5, recompute track parameters and covariances starting from this station
       // (going in the right direction)
       if (nextStation == 4) RetraceTrack(trackCandidate,kTRUE);
-
+      
       // Printout for debuging
       if ((AliLog::GetDebugLevel("MUON","AliMUONTrackReconstructorK") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
         cout << "FollowTrackInStation: added the best cluster in chamber(1..): " << bestTrackParamAtCluster1.GetClusterPtr()->GetChamberId()+1 << endl;
@@ -703,6 +1004,7 @@ Bool_t AliMUONTrackReconstructorK::FollowTrackInStation(AliMUONTrack &trackCandi
       delete [] clusterCh1Used;
       return kFALSE;
     }
+    
   } else if (foundOneCluster || foundTwoClusters) {
     
     // remove obsolete track
@@ -712,7 +1014,8 @@ Bool_t AliMUONTrackReconstructorK::FollowTrackInStation(AliMUONTrack &trackCandi
   } else {
     delete [] clusterCh1Used;
     return kFALSE;
-  }  
+  }
+  
   delete [] clusterCh1Used;
   return kTRUE;
   
@@ -791,8 +1094,10 @@ void AliMUONTrackReconstructorK::UpdateTrack(AliMUONTrack &track, AliMUONTrackPa
   /// Add 1 cluster to the track candidate
   /// Update chi2 of the track 
   
-  // Flag cluster as being not removable
-  trackParamAtCluster.SetRemovable(kFALSE);
+  // Flag cluster as being (not) removable
+  if (AliMUONReconstructor::GetRecoParam()->RequestStation(trackParamAtCluster.GetClusterPtr()->GetChamberId()/2))
+    trackParamAtCluster.SetRemovable(kFALSE);
+  else trackParamAtCluster.SetRemovable(kTRUE);
   trackParamAtCluster.SetLocalChi2(0.); // --> Local chi2 not used
   
   // Update the track chi2 into trackParamAtCluster
@@ -864,15 +1169,21 @@ Bool_t AliMUONTrackReconstructorK::RecoverTrack(AliMUONTrack &trackCandidate, Al
   if (nextStation > 1) return kFALSE;
   
   Int_t worstClusterNumber = -1;
-  Double_t localChi2, worstLocalChi2 = 0.;
+  Double_t localChi2, worstLocalChi2 = -1.;
   
   // Look for the cluster to remove
   for (Int_t clusterNumber = 0; clusterNumber < 2; clusterNumber++) {
     AliMUONTrackParam *trackParamAtCluster = (AliMUONTrackParam*)trackCandidate.GetTrackParamAtCluster()->UncheckedAt(clusterNumber);
     
+    // check if current cluster is in the previous station
+    if (trackParamAtCluster->GetClusterPtr()->GetChamberId()/2 != nextStation+1) break;
+    
     // check if current cluster is removable
     if (!trackParamAtCluster->IsRemovable()) return kFALSE;
     
+    // reset the current cluster as being not removable if it is on a required station
+    if (AliMUONReconstructor::GetRecoParam()->RequestStation(nextStation+1)) trackParamAtCluster->SetRemovable(kFALSE);
+    
     // Pick up cluster with the worst chi2
     localChi2 = trackParamAtCluster->GetLocalChi2();
     if (localChi2 > worstLocalChi2) {
@@ -881,8 +1192,8 @@ Bool_t AliMUONTrackReconstructorK::RecoverTrack(AliMUONTrack &trackCandidate, Al
     }
   }
   
-  // Reset best cluster as being NOT removable
-  ((AliMUONTrackParam*)trackCandidate.GetTrackParamAtCluster()->UncheckedAt((worstClusterNumber+1)%2))->SetRemovable(kFALSE);
+  // check if worst cluster found
+  if (worstClusterNumber < 0) return kFALSE;
   
   // Remove the worst cluster
   trackCandidate.RemoveTrackParamAtCluster((AliMUONTrackParam*)trackCandidate.GetTrackParamAtCluster()->UncheckedAt(worstClusterNumber));
@@ -890,6 +1201,11 @@ Bool_t AliMUONTrackReconstructorK::RecoverTrack(AliMUONTrack &trackCandidate, Al
   // Re-calculate track parameters at the (new) first cluster
   RetracePartialTrack(trackCandidate,(AliMUONTrackParam*)trackCandidate.GetTrackParamAtCluster()->UncheckedAt(1));
   
+  // skip track with absolute bending momentum out of limits
+  Double_t bendingMomentum = TMath::Abs(1. / ((AliMUONTrackParam*)trackCandidate.GetTrackParamAtCluster()->First())->GetInverseBendingMomentum());
+  if (bendingMomentum < AliMUONReconstructor::GetRecoParam()->GetMinBendingMomentum() ||
+      bendingMomentum > AliMUONReconstructor::GetRecoParam()->GetMaxBendingMomentum()) return kFALSE;
+  
   // Look for new cluster(s) in next station
   return FollowTrackInStation(trackCandidate, clusterStore, nextStation);
   
index 93d71ab..d8142c4 100644 (file)
@@ -30,6 +30,7 @@ class AliMUONTrackReconstructorK : public AliMUONVTrackReconstructor
 
   // Functions
   virtual void MakeTrackCandidates(AliMUONVClusterStore& clusterStore);
+  virtual void MakeMoreTrackCandidates(AliMUONVClusterStore& clusterStore);
   virtual void FollowTracks(AliMUONVClusterStore& clusterStore);
   virtual void ComplementTracks(const AliMUONVClusterStore& clusterStore);
   virtual void ImproveTrack(AliMUONTrack &track);
@@ -46,6 +47,7 @@ class AliMUONTrackReconstructorK : public AliMUONVTrackReconstructor
   void RetraceTrack(AliMUONTrack &trackCandidate, Bool_t resetSeed);
   void RetracePartialTrack(AliMUONTrack &trackCandidate, const AliMUONTrackParam* startingTrackParam);
   
+  Bool_t FollowTrackInChamber(AliMUONTrack &trackCandidate, AliMUONVClusterStore& clusterStore, Int_t nextChamber);
   Bool_t FollowTrackInStation(AliMUONTrack &trackCandidate, AliMUONVClusterStore& clusterStore, Int_t nextStation);
   
   Double_t RunKalmanFilter(AliMUONTrackParam &trackParamAtCluster);
index 45c299b..30053c9 100644 (file)
 
 #include "AliMUONTracker.h"
 
-#include "AliMUONReconstructor.h"
+#include "AliCodeTimer.h"
+#include "AliESDEvent.h"
+#include "AliESDMuonTrack.h"
+#include "AliESDVertex.h"
+#include "AliLog.h"
+#include "AliMUONClusterStoreV2.h"
+#include "AliMUONESDInterface.h"
+#include "AliMUONLegacyClusterServer.h"
 #include "AliMUONRecoParam.h"
+#include "AliMUONReconstructor.h"
 #include "AliMUONTrack.h"
 #include "AliMUONTrackExtrap.h"
 #include "AliMUONTrackHitPattern.h"
 #include "AliMUONTrackParam.h"
-#include "AliMUONVCluster.h"
-#include "AliMUONVClusterServer.h"
-#include "AliMUONVDigitStore.h"
 #include "AliMUONTrackReconstructor.h"
 #include "AliMUONTrackReconstructorK.h"
 #include "AliMUONTrackStoreV1.h"
 #include "AliMUONTriggerTrackStoreV1.h"
-#include "AliMUONClusterStoreV2.h"
+#include "AliMUONVCluster.h"
+#include "AliMUONVClusterServer.h"
+#include "AliMUONVDigitStore.h"
 #include "AliMUONVTriggerStore.h"
-#include "AliMUONESDInterface.h"
-
-#include "AliESDEvent.h"
-#include "AliESDVertex.h"
-#include "AliESDMuonTrack.h"
-#include "AliLog.h"
-#include "AliCodeTimer.h"
-
 #include <Riostream.h>
-#include <TTree.h>
 #include <TRandom.h>
+#include <TTree.h>
 
 /// \cond CLASSIMP
 ClassImp(AliMUONTracker)
@@ -66,8 +65,8 @@ ClassImp(AliMUONTracker)
 
 
 //_____________________________________________________________________________
-AliMUONTracker::AliMUONTracker(AliMUONVClusterServer& clusterServer,
-                              const AliMUONVDigitStore& digitStore,
+AliMUONTracker::AliMUONTracker(AliMUONVClusterServer* clusterServer,
+                               const AliMUONVDigitStore& digitStore,
                                const AliMUONDigitMaker* digitMaker,
                                const AliMUONGeometryTransformer* transformer,
                                const AliMUONTriggerCircuit* triggerCircuit)
@@ -79,15 +78,28 @@ AliMUONTracker::AliMUONTracker(AliMUONVClusterServer& clusterServer,
   fTrackReco(0x0),
   fClusterStore(0x0),
   fTriggerStore(0x0),
-  fClusterServer(clusterServer), // not owner
-  fDigitStore(digitStore) // not owner
+  fClusterServer(clusterServer), 
+  fIsOwnerOfClusterServer(kFALSE),
+  fDigitStore(digitStore), // not owner
+  fInputClusterStore(0x0),
+  fTriggerTrackStore(0x0)
 {
   /// constructor
   if (fTransformer && fDigitMaker)
     fTrackHitPatternMaker = new AliMUONTrackHitPattern(*fTransformer,*fDigitMaker);
   
-  TIter next(fDigitStore.CreateIterator());
-  fClusterServer.UseDigits(next);
+  if (!fClusterServer)
+  {
+    AliInfo("No cluster server given. Will use AliMUONLegacyClusterServer");
+    fIsOwnerOfClusterServer = kTRUE;
+  }
+  else
+  {
+    TIter next(fDigitStore.CreateIterator());
+    fClusterServer->UseDigits(next);
+    
+    SetupClusterServer(*fClusterServer);
+  }
 }
 
 //_____________________________________________________________________________
@@ -98,6 +110,9 @@ AliMUONTracker::~AliMUONTracker()
   delete fTrackHitPatternMaker;
   delete fClusterStore;
   delete fTriggerStore;
+  if ( fIsOwnerOfClusterServer ) delete fClusterServer;
+  delete fInputClusterStore;
+  delete fTriggerTrackStore;
 }
 
 //_____________________________________________________________________________
@@ -113,13 +128,25 @@ AliMUONTracker::ClusterStore() const
 }
 
 //_____________________________________________________________________________
+AliMUONVTriggerTrackStore*
+AliMUONTracker::TriggerTrackStore() const
+{
+  /// Return (and create if necessary) the trigger track container
+  if (!fTriggerTrackStore) 
+  {
+    fTriggerTrackStore = new AliMUONTriggerTrackStoreV1;
+  }
+  return fTriggerTrackStore;
+}
+
+//_____________________________________________________________________________
 Int_t AliMUONTracker::LoadClusters(TTree* clustersTree)
 {
   /// Load triggerStore from clustersTree
 
-  ClusterStore()->Clear();
-  
   delete fTriggerStore;
+  delete fInputClusterStore;
+  fInputClusterStore=0x0;
 
   if ( ! clustersTree ) {
     AliFatal("No clustersTree");
@@ -134,7 +161,20 @@ Int_t AliMUONTracker::LoadClusters(TTree* clustersTree)
     return 2;
   }
   
-  ClusterStore()->Connect(*clustersTree,kFALSE);
+  if ( fIsOwnerOfClusterServer )
+  {
+    fInputClusterStore = AliMUONVClusterStore::Create(*clustersTree);
+    if ( fInputClusterStore ) 
+    {
+      AliInfo(Form("Created %s from cluster tree",fInputClusterStore->ClassName()));
+      fInputClusterStore->Clear();
+      fInputClusterStore->Connect(*clustersTree,kFALSE);
+    }
+    delete fClusterServer;
+    fClusterServer = new AliMUONLegacyClusterServer(*fTransformer,fInputClusterStore);
+    SetupClusterServer(*fClusterServer);
+  }
+  
   fTriggerStore->Connect(*clustersTree,kFALSE);
   
   clustersTree->GetEvent(0);
@@ -149,7 +189,10 @@ Int_t AliMUONTracker::Clusters2Tracks(AliESDEvent* esd)
   AliDebug(1,"");
   AliCodeTimerAuto("")
   
-  if (!fTrackReco) CreateTrackReconstructor();
+  if (!fTrackReco) 
+  {
+    fTrackReco = CreateTrackReconstructor(AliMUONReconstructor::GetRecoParam()->GetTrackingMode(),fClusterServer);
+  }
   
   // if the required tracking mode does not exist
   if  (!fTrackReco) return 1;
@@ -165,20 +208,21 @@ Int_t AliMUONTracker::Clusters2Tracks(AliESDEvent* esd)
     return 3;
   }
 
+  // Make trigger tracks
+  if ( fTriggerCircuit ) 
+  {
+    TriggerTrackStore()->Clear();
+    fTrackReco->EventReconstructTrigger(*fTriggerCircuit,*fTriggerStore,*(TriggerTrackStore()));
+  }
+  
   // Make tracker tracks
   AliMUONVTrackStore* trackStore = new AliMUONTrackStoreV1;
   fTrackReco->EventReconstruct(*(ClusterStore()),*trackStore);
   
-  // Make trigger tracks
-  AliMUONVTriggerTrackStore* triggerTrackStore(0x0);
-  if ( fTriggerCircuit ) {
-    triggerTrackStore = new AliMUONTriggerTrackStoreV1;
-    fTrackReco->EventReconstructTrigger(*fTriggerCircuit,*fTriggerStore,*triggerTrackStore);
-  }
-
   // Match tracker/trigger tracks
-  if ( triggerTrackStore && fTrackHitPatternMaker ) {
-    fTrackReco->ValidateTracksWithTrigger(*trackStore,*triggerTrackStore,*fTriggerStore,*fTrackHitPatternMaker);
+  if ( fTrackHitPatternMaker ) 
+  {
+    fTrackReco->ValidateTracksWithTrigger(*trackStore,*(TriggerTrackStore()),*fTriggerStore,*fTrackHitPatternMaker);
   }
   
   // Fill ESD
@@ -186,7 +230,6 @@ Int_t AliMUONTracker::Clusters2Tracks(AliESDEvent* esd)
   
   // cleanup
   delete trackStore;
-  delete triggerTrackStore;
   
   return 0;
 }
@@ -231,28 +274,32 @@ void AliMUONTracker::FillESD(AliMUONVTrackStore& trackStore, AliESDEvent* esd) c
 }
 
 //_____________________________________________________________________________
-void AliMUONTracker::CreateTrackReconstructor()
+AliMUONVTrackReconstructor* AliMUONTracker::CreateTrackReconstructor(const char* trackingMode, AliMUONVClusterServer* clusterServer)
 {
   /// Create track reconstructor, depending on tracking mode set in RecoParam
   
-  TString opt(AliMUONReconstructor::GetRecoParam()->GetTrackingMode());
+  AliMUONVTrackReconstructor* trackReco(0x0);
+  
+  TString opt(trackingMode);
   opt.ToUpper();
   
   if (strstr(opt,"ORIGINAL"))
   {
-    fTrackReco = new AliMUONTrackReconstructor(fClusterServer);
+    trackReco = new AliMUONTrackReconstructor(*clusterServer);
   }
   else if (strstr(opt,"KALMAN"))
   {
-    fTrackReco = new AliMUONTrackReconstructorK(fClusterServer);
+    trackReco = new AliMUONTrackReconstructorK(*clusterServer);
   }
   else
   {
-    AliError(Form("tracking mode \"%s\" does not exist",opt.Data()));
-    return;
+    AliErrorClass(Form("tracking mode \"%s\" does not exist",opt.Data()));
+    return 0x0;
   }
   
-  AliInfo(Form("Will use %s for tracking",fTrackReco->ClassName()));
+  AliInfoClass(Form("Will use %s for tracking",trackReco->ClassName()));
+  
+  return trackReco;
 }
 
 //_____________________________________________________________________________
@@ -260,5 +307,31 @@ void AliMUONTracker::UnloadClusters()
 {
   /// Clear internal clusterStore
   
-  ClusterStore()->Clear();
+  delete fInputClusterStore;
+  fInputClusterStore = 0x0;
 }
+
+
+//_____________________________________________________________________________
+void
+AliMUONTracker::SetupClusterServer(AliMUONVClusterServer& clusterServer)
+{
+  /// Setup the cluster server
+  
+  if ( AliMUONReconstructor::GetRecoParam()->BypassSt45() )
+  {
+    Bool_t ok = clusterServer.UseTriggerTrackStore(TriggerTrackStore());
+  
+    if ( ok ) 
+    
+    {
+      AliWarning("WILL USE TRIGGER TRACKS TO GENERATE CLUSTERS IN STATIONS 4 AND 5, THUS BYPASSING REAL CLUSTERS IN THOSE TWO STATIONS !!!");    
+    }
+    else
+    {
+      AliWarning("BYPASSING OF ST45 REQUESTED, BUT CLUSTERSERVER DOES NOT SEEM TO SUPPORT IT !!!");    
+    }
+  }
+}
+
+
index 21fa72f..c55ff77 100644 (file)
@@ -8,7 +8,7 @@
 /// \class AliMUONTracker
 /// \brief MUON base Tracker
 ///
-//  Author: Christian Finck, SUBATECH Nantes
+//  Authors: Christian Finck, Laurent Aphecetche, SUBATECH Nantes
 
 #include "AliTracker.h"
 
@@ -18,19 +18,20 @@ class AliMUONDigitMaker;
 class AliMUONGeometryTransformer;
 class AliMUONTrackHitPattern;
 class AliMUONTriggerCircuit;
+class AliMUONVClusterServer;
 class AliMUONVClusterStore;
+class AliMUONVDigitStore;
 class AliMUONVTrackReconstructor;
 class AliMUONVTrackStore;
 class AliMUONVTriggerStore;
-class AliMUONVClusterServer;
-class AliMUONVDigitStore;
+class AliMUONVTriggerTrackStore;
 
 class AliMUONTracker : public AliTracker
 {
  public:
 
-  AliMUONTracker(AliMUONVClusterServer& clusterServer,
-                const AliMUONVDigitStore& digitStore,
+  AliMUONTracker(AliMUONVClusterServer* clusterServer,
+                 const AliMUONVDigitStore& digitStore,
                  const AliMUONDigitMaker* digitMaker=0,
                  const AliMUONGeometryTransformer* transformer=0,
                  const AliMUONTriggerCircuit* triggerCircuit=0);
@@ -49,6 +50,8 @@ class AliMUONTracker : public AliTracker
   /// Dummy implementation
   virtual AliCluster *GetCluster(Int_t /*index*/) const {return 0;}
 
+  static AliMUONVTrackReconstructor* CreateTrackReconstructor(const char* trackingMode, AliMUONVClusterServer* clusterServer);
+  
 private:
   /// Not implemented
   AliMUONTracker(const AliMUONTracker& rhs);
@@ -57,10 +60,12 @@ private:
     
   AliMUONVClusterStore* ClusterStore() const;
 
-  void CreateTrackReconstructor();
+  AliMUONVTriggerTrackStore* TriggerTrackStore() const;
   
   void FillESD(AliMUONVTrackStore& trackStore, AliESDEvent* esd) const;
 
+  void SetupClusterServer(AliMUONVClusterServer& clusterServer);
+  
 private:
   const AliMUONDigitMaker* fDigitMaker; //!< digit maker (not owner)
   const AliMUONGeometryTransformer* fTransformer; //!< geometry transformer (not owner)
@@ -69,8 +74,11 @@ private:
   AliMUONVTrackReconstructor* fTrackReco; //!< track reconstructor
   mutable AliMUONVClusterStore* fClusterStore; //!< cluster container
   AliMUONVTriggerStore* fTriggerStore; //!< trigger information
-  AliMUONVClusterServer& fClusterServer; //!< to get clusters
+  AliMUONVClusterServer* fClusterServer; //!< to get clusters
+  Bool_t fIsOwnerOfClusterServer; //!< whether we are owner of the cluster server
   const AliMUONVDigitStore& fDigitStore; //!< digit info to fill in ESD
+  mutable AliMUONVClusterStore* fInputClusterStore; //!< cluster container
+  mutable AliMUONVTriggerTrackStore* fTriggerTrackStore; //!< trigger track store
   
   ClassDef(AliMUONTracker,0)  //tracker base class for MUON
 };
diff --git a/MUON/AliMUONTriggerTrackToTrackerClusters.cxx b/MUON/AliMUONTriggerTrackToTrackerClusters.cxx
new file mode 100644 (file)
index 0000000..571e9c5
--- /dev/null
@@ -0,0 +1,229 @@
+/**************************************************************************
+* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+*                                                                        *
+* Author: The ALICE Off-line Project.                                    *
+* Contributors are mentioned in the code where appropriate.              *
+*                                                                        *
+* Permission to use, copy, modify and distribute this software and its   *
+* documentation strictly for non-commercial purposes is hereby granted   *
+* without fee, provided that the above copyright notice appears in all   *
+* copies and that both the copyright notice and this permission notice   *
+* appear in the supporting documentation. The authors make no claims     *
+* about the suitability of this software for any purpose. It is          *
+* provided "as is" without express or implied warranty.                  *
+**************************************************************************/
+
+// $Id$
+
+#include "AliMUONTriggerTrackToTrackerClusters.h"
+
+///\class AliMUONTriggerTrackToTrackerClusters
+/// 
+/// Class to convert trigger tracks into "fake" clusters in stations 4 and 5
+///
+/// Only intent is to be able to reconstruct data where stations 4 and 5 were
+/// not functionning, typically early cosmic runs
+///
+///\author Laurent Aphecetche, Subatech
+
+#include "AliCodeTimer.h"
+#include "AliLog.h"
+#include "AliMUONConstants.h"
+#include "AliMUONGeometryTransformer.h"
+#include "AliMUONTrack.h"
+#include "AliMUONTrackExtrap.h"
+#include "AliMUONTriggerTrack.h"
+#include "AliMUONVCluster.h"
+#include "AliMUONVClusterStore.h"
+#include "AliMUONVTriggerTrackStore.h"
+#include "AliMpArea.h"
+#include "AliMpDEManager.h"
+#include <TMath.h>
+
+///\cond CLASSIMP
+ClassImp(AliMUONTriggerTrackToTrackerClusters)
+///\endcond
+
+//_____________________________________________________________________________
+AliMUONTriggerTrackToTrackerClusters::AliMUONTriggerTrackToTrackerClusters(const AliMUONGeometryTransformer& transformer,
+                                                                           AliMUONVTriggerTrackStore* trackStore)
+: TObject(), fTransformer(transformer), fTriggerTrackStore(trackStore)
+{
+  /// ctor. We do not take ownership of the trigger track store.
+}
+
+//_____________________________________________________________________________
+AliMUONTriggerTrackToTrackerClusters::~AliMUONTriggerTrackToTrackerClusters()
+{
+  /// dtor
+}
+
+//_____________________________________________________________________________
+Int_t 
+AliMUONTriggerTrackToTrackerClusters::DetElemId(Int_t chamber, Double_t x, Double_t y,
+                                                Double_t ex, Double_t ey,
+                                                Double_t& z) const
+{
+  /// Find in which detection element (x,y) (global) position is.
+  
+  AliMpDEIterator it;
+  
+  AliMpArea a( TVector2(x,y), TVector2(ex,ey) );
+  
+  it.First(chamber);
+  
+  while ( !it.IsDone() )
+  {
+    Int_t detElemId = it.CurrentDEId();
+    
+    AliMpArea* area = fTransformer.GetDEArea(detElemId);
+    
+    if ( area->Overlap(a) ) 
+    {
+      // get z of the center of that DE.
+      Double_t dummyx, dummyy;
+      fTransformer.Local2Global(detElemId,0,0,0,dummyx,dummyy,z);
+      return detElemId;
+    }
+    it.Next();
+  }
+  
+  return -1;
+}
+
+//_____________________________________________________________________________
+Int_t 
+AliMUONTriggerTrackToTrackerClusters::GenerateClusters(Int_t iChamber,
+                                                       AliMUONVClusterStore& clusterStore) const
+{
+  /// Generate clusters in given chamber
+  /// Return the number of clusters added to the clusterStore
+  
+  AliCodeTimerAuto(Form("Chamber %d",iChamber));
+  
+  TIter next(fTriggerTrackStore->CreateIterator());
+  
+  AliMUONTriggerTrack* track;
+  Int_t nadded(0);
+  
+  while ( ( track = static_cast<AliMUONTriggerTrack*>(next()) ) )
+  {
+    nadded += GenerateClusters(iChamber,*track,clusterStore);
+  }
+  return nadded;
+}
+
+//_____________________________________________________________________________
+Int_t 
+AliMUONTriggerTrackToTrackerClusters::GenerateClusters(Int_t iChamber,
+                                                       const AliMUONTriggerTrack& track,
+                                                       AliMUONVClusterStore& clusterStore) const
+{
+  /// From a trigger track, generate 1 cluster in given chamber
+  
+  /// Get a (rough) guestimate of the track momentum
+  
+  Int_t nadded(0);
+  
+  Double_t z = AliMUONConstants::DefaultChamberZ(10);
+  
+  Double_t bendingCoord = track.GetY11();
+  Double_t bendingSlope = TMath::Tan(track.GetThetay());
+  
+  Double_t bendingImpact = bendingCoord - z * bendingSlope;
+  
+  AliDebug(1,Form("TriggerTrack impact parameter=%e",bendingImpact));
+  
+  //  StdoutToAliDebug(1,track.Print());
+  
+  Double_t inverseBendingMomentum = 1. / AliMUONTrackExtrap::GetBendingMomentumFromImpactParam(bendingImpact);
+  
+  // Construct an AliMUONTrackParam from the trigger track, in order to be able to extrapolate it
+  // to chambers 6..9 planes.
+  
+  AliMUONTrackParam trackParam;
+  
+  trackParam.SetZ(z);
+  trackParam.SetNonBendingCoor(track.GetX11());
+  trackParam.SetNonBendingSlope(TMath::Tan(track.GetThetax()));
+  trackParam.SetBendingCoor(bendingCoord);
+  trackParam.SetBendingSlope(bendingSlope);
+  trackParam.SetInverseBendingMomentum(inverseBendingMomentum);
+  
+  Double_t dZ = TMath::Abs(AliMUONConstants::DefaultChamberZ(12) - AliMUONConstants::DefaultChamberZ(10));
+  
+  Double_t sigmaX = AliMUONConstants::TriggerNonBendingReso();
+  
+  Double_t sigmaY = AliMUONConstants::TriggerBendingReso();
+  
+  // Compute and set track parameters covariances
+  TMatrixD paramCov(5,5);
+  paramCov.Zero();
+  
+  // Non bending plane
+  paramCov(0,0) = sigmaX*sigmaX;
+  paramCov(0,1) = -sigmaX/dZ;
+  paramCov(1,0) = paramCov(0,1);
+  
+  paramCov(1,1) = 2.0*sigmaX/dZ/dZ;
+  
+  // Bending plane
+  paramCov(2,2) = sigmaY*sigmaY;
+  paramCov(2,3) = -sigmaY/dZ;
+  paramCov(3,2) = paramCov(2,3);
+  
+  paramCov(3,3) = 2.0*sigmaY/dZ/dZ;
+  
+  // Inverse bending momentum (50% error)
+  paramCov(4,4) = 0.5*inverseBendingMomentum * 0.5*inverseBendingMomentum;
+  
+  // Set covariances
+  trackParam.SetCovariances(paramCov);
+  
+  // Now we extrapolate this trackParam to chambers 6 -> 9
+  
+  const Float_t kFilterThickness = TMath::Abs(AliMUONConstants::MuonFilterZEnd()-AliMUONConstants::MuonFilterZBeg()); // cm
+  
+  Int_t nclusters = clusterStore.GetSize();
+  
+  AliMUONTrackParam tp(trackParam);
+  
+  Double_t zg = AliMUONConstants::DefaultChamberZ(iChamber);
+  AliMUONTrackExtrap::ExtrapToZCov(&tp, zg); // Extrap to iChamber
+  
+  AliMUONTrackExtrap::AddMCSEffect(&tp, kFilterThickness, AliMUONConstants::MuonFilterX0()); // Add MCS effects
+  
+  AliDebug(1,Form("iChamber=%d",iChamber));
+  
+  StdoutToAliDebug(1,tp.Print("FULLCOV"););
+  
+  Double_t x = tp.GetNonBendingCoor();
+  Double_t y = tp.GetBendingCoor();
+  const TMatrixD& cov = tp.GetCovariances();
+  Double_t ex = TMath::Sqrt(cov(0,0));
+  Double_t ey = TMath::Sqrt(cov(2,2));
+  
+  Double_t zde;
+  
+  Int_t detElemId = DetElemId(iChamber,x,y,ex,ey,zde);
+  
+  AliDebug(1,Form("zg = %e zde = %e",zg,zde));
+  
+  if ( AliMpDEManager::IsValidDetElemId(detElemId) ) 
+  {
+    AliMUONVCluster* rawCluster = clusterStore.Add(AliMpDEManager::GetChamberId(detElemId), detElemId, nclusters);
+    
+    ++nclusters;
+    ++nadded;
+    
+    rawCluster->SetCharge(100.0);
+    rawCluster->SetXYZ(x, y, zg);
+    rawCluster->SetErrXY(ex,ey);
+  }
+  else
+  {
+    AliWarning(Form("No DE found at xg=%e yg=%e",detElemId,x,y));
+  }
+  
+  return nadded;
+}
diff --git a/MUON/AliMUONTriggerTrackToTrackerClusters.h b/MUON/AliMUONTriggerTrackToTrackerClusters.h
new file mode 100644 (file)
index 0000000..ffe4669
--- /dev/null
@@ -0,0 +1,52 @@
+#ifndef ALIMUONTRIGGERTRACKTOTRACKERCLUSTERS_H
+#define ALIMUONTRIGGERTRACKTOTRACKERCLUSTERS_H
+
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* See cxx source for full Copyright notice                               */
+
+// $Id$
+
+/// \ingroup rec
+/// \class AliMUONTriggerTrackToTrackerClusters
+/// \brief Convertor of trigger track to tracker clusters
+/// 
+// Author Laurent Aphecetche, Subatech
+
+#ifndef ROOT_TObject
+#  include "TObject.h"
+#endif
+
+class AliMUONTriggerTrack;
+class AliMUONVClusterStore;
+class AliMUONVTriggerTrackStore;
+class AliMUONGeometryTransformer;
+
+class AliMUONTriggerTrackToTrackerClusters : public TObject
+{
+public:
+  AliMUONTriggerTrackToTrackerClusters(const AliMUONGeometryTransformer& transformer, AliMUONVTriggerTrackStore* trackStore);
+  virtual ~AliMUONTriggerTrackToTrackerClusters();
+
+  Int_t GenerateClusters(Int_t iChamber, AliMUONVClusterStore& clusterStore) const;
+  
+  Int_t GenerateClusters(Int_t iChamber,
+                        const AliMUONTriggerTrack& track,
+                        AliMUONVClusterStore& clusterStore) const;
+    
+  Int_t DetElemId(Int_t chamber, Double_t x, Double_t y,
+                  Double_t ex, Double_t ey, Double_t& z) const;
+    
+private:
+    /// not defined
+    AliMUONTriggerTrackToTrackerClusters(const AliMUONTriggerTrackToTrackerClusters& rhs);
+  /// not defined
+  AliMUONTriggerTrackToTrackerClusters& operator=(const AliMUONTriggerTrackToTrackerClusters& rhs);
+  
+private:
+    const AliMUONGeometryTransformer& fTransformer; ///< to go from local to global
+    AliMUONVTriggerTrackStore* fTriggerTrackStore; ///< not owner
+  
+  ClassDef(AliMUONTriggerTrackToTrackerClusters,1) // Convertor of trigger tracks to tracker clusters
+};
+
+#endif
index 3de623c..7a48420 100644 (file)
@@ -17,6 +17,7 @@
 #endif
 
 class AliMUONVClusterStore;
+class AliMUONVTriggerTrackStore;
 class AliMpArea;
 class TIter;
 
@@ -31,9 +32,12 @@ public:
                            AliMUONVClusterStore& clusterStore,
                            const AliMpArea& area) = 0;
   
-  /// Use digits from the given digitstore to perform our job.
+  /// Specify an iterator to loop over the digits needed to perform our job.
   virtual void UseDigits(TIter& next) = 0;
   
+  /// Use trigger tracks. Return kFALSE if not used.
+  virtual Bool_t UseTriggerTrackStore(AliMUONVTriggerTrackStore* /*trackStore*/) { return kFALSE; }
+  
   ClassDef(AliMUONVClusterServer,1) // Cluster server interface
 };
 
index 4b0e24e..6eedfe7 100644 (file)
@@ -136,9 +136,12 @@ void AliMUONVTrackReconstructor::EventReconstruct(AliMUONVClusterStore& clusterS
   // Reset array of tracks
   ResetTracks();
   
-  // Look for candidates from at least 3 aligned points in stations(1..) 4 and 5
+  // Look for candidates from clusters in stations(1..) 4 and 5
   MakeTrackCandidates(clusterStore);
   
+  // Look for extra candidates from clusters in stations(1..) 4 and 5
+  if (AliMUONReconstructor::GetRecoParam()->MakeMoreTrackCandidates()) MakeMoreTrackCandidates(clusterStore);
+  
   // Stop tracking if no candidate found
   if (fRecTracksPtr->GetEntriesFast() == 0) return;
   
@@ -167,18 +170,16 @@ void AliMUONVTrackReconstructor::EventReconstruct(AliMUONVClusterStore& clusterS
 }
 
   //__________________________________________________________________________
-TClonesArray* AliMUONVTrackReconstructor::MakeSegmentsInStation(const AliMUONVClusterStore& clusterStore, Int_t station)
+TClonesArray* AliMUONVTrackReconstructor::MakeSegmentsBetweenChambers(const AliMUONVClusterStore& clusterStore, Int_t ch1, Int_t ch2)
 {
-  /// To make the list of segments in station(0..) "Station" from the list of clusters to be reconstructed.
+  /// To make the list of segments from the list of clusters in the 2 given chambers.
   /// Return a new TClonesArray of segments.
   /// It is the responsibility of the user to delete it afterward.
-  AliDebug(1,Form("Enter MakeSegmentsPerStation (1..) %d",station+1));
+  AliDebug(1,Form("Enter MakeSegmentsBetweenChambers (1..) %d-%d", ch1+1, ch2+1));
   
   AliMUONVCluster *cluster1, *cluster2;
   AliMUONObjectPair *segment;
-  Double_t bendingSlope = 0, impactParam = 0., bendingMomentum = 0.; // to avoid compilation warning
-  Int_t ch1 = 2 * station;
-  Int_t ch2 = ch1 + 1;
+  Double_t nonBendingSlope = 0, bendingSlope = 0, impactParam = 0., bendingMomentum = 0.; // to avoid compilation warning
   
   // Create iterators to loop over clusters in both chambers
   TIter nextInCh1(clusterStore.CreateChamberIterator(ch1,ch1));
@@ -196,6 +197,9 @@ TClonesArray* AliMUONVTrackReconstructor::MakeSegmentsInStation(const AliMUONVCl
     // Loop over clusters in the second chamber of the station
     while ( ( cluster2 = static_cast<AliMUONVCluster*>(nextInCh2()) ) ) {
       
+      // non bending slope
+      nonBendingSlope = (cluster1->GetX() - cluster2->GetX()) / (cluster1->GetZ() - cluster2->GetZ());
+      
       // bending slope
       bendingSlope = (cluster1->GetY() - cluster2->GetY()) / (cluster1->GetZ() - cluster2->GetZ());
       
@@ -205,9 +209,10 @@ TClonesArray* AliMUONVTrackReconstructor::MakeSegmentsInStation(const AliMUONVCl
       // absolute value of bending momentum
       bendingMomentum = TMath::Abs(AliMUONTrackExtrap::GetBendingMomentumFromImpactParam(impactParam));
       
-      // check for bending momentum within tolerances
-      if ((bendingMomentum < AliMUONReconstructor::GetRecoParam()->GetMaxBendingMomentum()) &&
-         (bendingMomentum > AliMUONReconstructor::GetRecoParam()->GetMinBendingMomentum())) {
+      // check for non bending slope and bending momentum within tolerances
+      if (TMath::Abs(nonBendingSlope) < AliMUONReconstructor::GetRecoParam()->GetMaxNonBendingSlope() &&
+         bendingMomentum < AliMUONReconstructor::GetRecoParam()->GetMaxBendingMomentum() &&
+         bendingMomentum > AliMUONReconstructor::GetRecoParam()->GetMinBendingMomentum()) {
         
        // make new segment
         segment = new ((*segments)[segments->GetLast()+1]) AliMUONObjectPair(cluster1, cluster2, kFALSE, kFALSE);
@@ -229,7 +234,7 @@ TClonesArray* AliMUONVTrackReconstructor::MakeSegmentsInStation(const AliMUONVCl
   }
   
   // Printout for debug
-  AliDebug(1,Form("Station: %d  NSegments:  %d ", station+1, segments->GetEntriesFast()));
+  AliDebug(1,Form("chambers%d-%d: NSegments =  %d ", ch1+1, ch2+1, segments->GetEntriesFast()));
   
   return segments;
 }
@@ -333,37 +338,49 @@ void AliMUONVTrackReconstructor::RemoveDoubleTracks()
 }
 
   //__________________________________________________________________________
-void AliMUONVTrackReconstructor::AskForNewClustersInStation(const AliMUONTrackParam &trackParam,
-                                                           AliMUONVClusterStore& clusterStore, Int_t station)
+void AliMUONVTrackReconstructor::AskForNewClustersInChamber(const AliMUONTrackParam &trackParam,
+                                                           AliMUONVClusterStore& clusterStore, Int_t chamber)
 {
   /// Ask the clustering to reconstruct new clusters around the track candidate position
-  /// in the 2 chambers of the given station
   
-  // maximum shift of the searching area due to distance between detection elements and the track slope
-  static const Double_t kgMaxShift = 2.; // 2 cm
+  // check if the current chamber is useable
+  if (!AliMUONReconstructor::GetRecoParam()->UseChamber(chamber)) return;
   
-  // extrapolate track parameters to the second chamber of the station
-  AliMUONTrackParam extrapTrackParam(trackParam);
-  AliMUONTrackExtrap::ExtrapToZ(&extrapTrackParam, AliMUONConstants::DefaultChamberZ(2*station+1));
+  // maximum distance between the center of the chamber and a detection element
+  // (accounting for the inclination of the chamber)
+  static const Double_t gkMaxDZ = 15.; // 15 cm
   
-  // build the searching area
+  // extrapolate track parameters to the chamber
+  AliMUONTrackParam extrapTrackParam(trackParam);
+  AliMUONTrackExtrap::ExtrapToZCov(&extrapTrackParam, AliMUONConstants::DefaultChamberZ(chamber));
+  
+  // build the searching area using the track resolution and the maximum-distance-to-track value
+  const TMatrixD& kParamCov = extrapTrackParam.GetCovariances();
+  Double_t errX2 = kParamCov(0,0) + gkMaxDZ * gkMaxDZ * kParamCov(1,1) + 2. * gkMaxDZ * TMath::Abs(kParamCov(0,1));
+  Double_t errY2 = kParamCov(2,2) + gkMaxDZ * gkMaxDZ * kParamCov(3,3) + 2. * gkMaxDZ * TMath::Abs(kParamCov(2,3));
+  Double_t dX = TMath::Abs(trackParam.GetNonBendingSlope()) * gkMaxDZ +
+               AliMUONReconstructor::GetRecoParam()->GetMaxNonBendingDistanceToTrack() +
+               AliMUONReconstructor::GetRecoParam()->GetSigmaCutForTracking() * TMath::Sqrt(errX2);
+  Double_t dY = TMath::Abs(trackParam.GetBendingSlope()) * gkMaxDZ +
+               AliMUONReconstructor::GetRecoParam()->GetMaxBendingDistanceToTrack() +
+               AliMUONReconstructor::GetRecoParam()->GetSigmaCutForTracking() * TMath::Sqrt(errY2);
+  TVector2 dimensions(dX, dY);
   TVector2 position(extrapTrackParam.GetNonBendingCoor(), extrapTrackParam.GetBendingCoor());
-  TVector2 dimensions(AliMUONReconstructor::GetRecoParam()->GetMaxNonBendingDistanceToTrack() + kgMaxShift,
-                     AliMUONReconstructor::GetRecoParam()->GetMaxBendingDistanceToTrack() + kgMaxShift);
-  AliMpArea area2(position, dimensions);
+  AliMpArea area(position, dimensions);
   
   // ask to cluterize in the given area of the given chamber
-  fClusterServer.Clusterize(2*station+1, clusterStore, area2);
+  fClusterServer.Clusterize(chamber, clusterStore, area);
   
-  // extrapolate track parameters to the first chamber of the station
-  AliMUONTrackExtrap::ExtrapToZ(&extrapTrackParam, AliMUONConstants::DefaultChamberZ(2*station));
-  
-  // build the searching area
-  position.Set(extrapTrackParam.GetNonBendingCoor(), extrapTrackParam.GetBendingCoor());
-  AliMpArea area1(position, dimensions);
-  
-  // ask to cluterize in the given area of the given chamber
-  fClusterServer.Clusterize(2*station, clusterStore, area1);
+}
+
+  //__________________________________________________________________________
+void AliMUONVTrackReconstructor::AskForNewClustersInStation(const AliMUONTrackParam &trackParam,
+                                                           AliMUONVClusterStore& clusterStore, Int_t station)
+{
+  /// Ask the clustering to reconstruct new clusters around the track candidate position
+  /// in the 2 chambers of the given station
+  AskForNewClustersInChamber(trackParam, clusterStore, 2*station+1);
+  AskForNewClustersInChamber(trackParam, clusterStore, 2*station);
 }
 
   //__________________________________________________________________________
@@ -398,16 +415,24 @@ Double_t AliMUONVTrackReconstructor::TryOneCluster(const AliMUONTrackParam &trac
   //__________________________________________________________________________
 Bool_t AliMUONVTrackReconstructor::TryOneClusterFast(const AliMUONTrackParam &trackParam, AliMUONVCluster* cluster)
 {
-/// Test the compatibility between the track and the cluster within a wide fix window
-/// assuming linear propagation of the track:
+/// Test the compatibility between the track and the cluster
+/// given the track resolution + the maximum-distance-to-track value
+/// and assuming linear propagation of the track:
 /// return kTRUE if they are compatibles
   
   Double_t dZ = cluster->GetZ() - trackParam.GetZ();
   Double_t dX = cluster->GetX() - (trackParam.GetNonBendingCoor() + trackParam.GetNonBendingSlope() * dZ);
   Double_t dY = cluster->GetY() - (trackParam.GetBendingCoor() + trackParam.GetBendingSlope() * dZ);
+  const TMatrixD& kParamCov = trackParam.GetCovariances();
+  Double_t errX2 = kParamCov(0,0) + dZ * dZ * kParamCov(1,1) + 2. * dZ * kParamCov(0,1);
+  Double_t errY2 = kParamCov(2,2) + dZ * dZ * kParamCov(3,3) + 2. * dZ * kParamCov(2,3);
+
+  Double_t dXmax = AliMUONReconstructor::GetRecoParam()->GetSigmaCutForTracking() * TMath::Sqrt(errX2) +
+                   AliMUONReconstructor::GetRecoParam()->GetMaxNonBendingDistanceToTrack();
+  Double_t dYmax = AliMUONReconstructor::GetRecoParam()->GetSigmaCutForTracking() * TMath::Sqrt(errY2) +
+                  AliMUONReconstructor::GetRecoParam()->GetMaxBendingDistanceToTrack();
   
-  if (TMath::Abs(dX) > AliMUONReconstructor::GetRecoParam()->GetMaxNonBendingDistanceToTrack() ||
-      TMath::Abs(dY) > AliMUONReconstructor::GetRecoParam()->GetMaxBendingDistanceToTrack()) return kFALSE;
+  if (TMath::Abs(dX) > dXmax || TMath::Abs(dY) > dYmax) return kFALSE;
   
   return kTRUE;
   
@@ -457,6 +482,127 @@ Double_t AliMUONVTrackReconstructor::TryTwoClustersFast(const AliMUONTrackParam
 }
 
   //__________________________________________________________________________
+Bool_t AliMUONVTrackReconstructor::FollowLinearTrackInChamber(AliMUONTrack &trackCandidate, const AliMUONVClusterStore& clusterStore,
+                                                             Int_t nextChamber)
+{
+  /// Follow trackCandidate in chamber(0..) nextChamber assuming linear propagation, and search for compatible cluster(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 cluster(s) to the "trackCandidate". Try to add a couple of clusters in priority.
+  /// return kTRUE if new cluster(s) have been found (otherwise return kFALSE)
+  AliDebug(1,Form("Enter FollowLinearTrackInChamber(1..) %d", nextChamber+1));
+  
+  Double_t chi2WithOneCluster = 1.e10;
+  Double_t maxChi2WithOneCluster = 2. * AliMUONReconstructor::GetRecoParam()->GetSigmaCutForTracking() *
+                                       AliMUONReconstructor::GetRecoParam()->GetSigmaCutForTracking(); // 2 because 2 quantities in chi2
+  Double_t bestChi2WithOneCluster = maxChi2WithOneCluster;
+  Bool_t foundOneCluster = kFALSE;
+  AliMUONTrack *newTrack = 0x0;
+  AliMUONVCluster *cluster;
+  AliMUONTrackParam trackParam;
+  AliMUONTrackParam extrapTrackParamAtCluster;
+  AliMUONTrackParam bestTrackParamAtCluster;
+  
+  // Get track parameters according to the propagation direction
+  if (nextChamber > 7) trackParam = *(AliMUONTrackParam*)trackCandidate.GetTrackParamAtCluster()->Last();
+  else trackParam = *(AliMUONTrackParam*)trackCandidate.GetTrackParamAtCluster()->First();
+  
+  // Printout for debuging
+  if ((AliLog::GetDebugLevel("MUON","AliMUONVTrackReconstructor") >= 2) || (AliLog::GetGlobalDebugLevel() >= 2)) {
+    cout<<endl<<"Track parameters and covariances at first cluster:"<<endl;
+    trackParam.GetParameters().Print();
+    trackParam.GetCovariances().Print();
+  }
+  
+  // Add MCS effect
+  AliMUONTrackExtrap::AddMCSEffect(&trackParam,AliMUONConstants::ChamberThicknessInX0(),1.);
+  
+  // Printout for debuging
+  if ((AliLog::GetDebugLevel("MUON","AliMUONVTrackReconstructor") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
+    cout << "FollowLinearTrackInChamber: look for cluster in chamber(1..): " << nextChamber+1 << endl;
+  }
+  
+  // Create iterators to loop over clusters in chamber
+  TIter next(clusterStore.CreateChamberIterator(nextChamber,nextChamber));
+  
+  // look for candidates in chamber
+  while ( ( cluster = static_cast<AliMUONVCluster*>(next()) ) ) {
+    
+    // try to add the current cluster fast
+    if (!TryOneClusterFast(trackParam, cluster)) continue;
+    
+    // try to add the current cluster accuratly
+    extrapTrackParamAtCluster = trackParam;
+    AliMUONTrackExtrap::LinearExtrapToZ(&extrapTrackParamAtCluster, cluster->GetZ());
+    chi2WithOneCluster = TryOneCluster(extrapTrackParamAtCluster, cluster, extrapTrackParamAtCluster);
+    
+    // if good chi2 then consider to add cluster
+    if (chi2WithOneCluster < maxChi2WithOneCluster) {
+      foundOneCluster = kTRUE;
+      
+      // Printout for debuging
+      if ((AliLog::GetDebugLevel("MUON","AliMUONVTrackReconstructor") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
+       cout << "FollowLinearTrackInChamber: found one cluster in chamber(1..): " << nextChamber+1
+       << " (Chi2 = " << chi2WithOneCluster << ")" << endl;
+       cluster->Print();
+      }
+      
+      if (AliMUONReconstructor::GetRecoParam()->TrackAllTracks()) {
+       // copy trackCandidate into a new track put at the end of fRecTracksPtr and add the new cluster
+       newTrack = new ((*fRecTracksPtr)[fRecTracksPtr->GetLast()+1]) AliMUONTrack(trackCandidate);
+       if (AliMUONReconstructor::GetRecoParam()->RequestStation(nextChamber/2))
+         extrapTrackParamAtCluster.SetRemovable(kFALSE);
+       else extrapTrackParamAtCluster.SetRemovable(kTRUE);
+       newTrack->AddTrackParamAtCluster(extrapTrackParamAtCluster,*cluster);
+       fNRecTracks++;
+       
+       // Printout for debuging
+       if ((AliLog::GetDebugLevel("MUON","AliMUONVTrackReconstructor") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
+         cout << "FollowLinearTrackInChamber: added one cluster in chamber(1..): " << nextChamber+1 << endl;
+         if (AliLog::GetGlobalDebugLevel() >= 3) newTrack->RecursiveDump();
+       }
+       
+      } else if (chi2WithOneCluster < bestChi2WithOneCluster) {
+       // keep track of the best cluster
+       bestChi2WithOneCluster = chi2WithOneCluster;
+       bestTrackParamAtCluster = extrapTrackParamAtCluster;
+      }
+      
+    }
+    
+  }
+  
+  // fill out the best track if required else clean up the fRecTracksPtr array
+  if (!AliMUONReconstructor::GetRecoParam()->TrackAllTracks()) {
+    if (foundOneCluster) {
+      if (AliMUONReconstructor::GetRecoParam()->RequestStation(nextChamber/2))
+       bestTrackParamAtCluster.SetRemovable(kFALSE);
+      else bestTrackParamAtCluster.SetRemovable(kTRUE);
+      trackCandidate.AddTrackParamAtCluster(bestTrackParamAtCluster,*(bestTrackParamAtCluster.GetClusterPtr()));
+      
+      // Printout for debuging
+      if ((AliLog::GetDebugLevel("MUON","AliMUONVTrackReconstructor") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
+        cout << "FollowLinearTrackInChamber: added the best cluster in chamber(1..): " << bestTrackParamAtCluster.GetClusterPtr()->GetChamberId()+1 << endl;
+        if (AliLog::GetGlobalDebugLevel() >= 3) newTrack->RecursiveDump();
+      }
+      
+    } else return kFALSE;
+    
+  } else if (foundOneCluster) {
+    
+    // remove obsolete track
+    fRecTracksPtr->Remove(&trackCandidate);
+    fNRecTracks--;
+    
+  } else return kFALSE;
+  
+  return kTRUE;
+  
+}
+
+//__________________________________________________________________________
 Bool_t AliMUONVTrackReconstructor::FollowLinearTrackInStation(AliMUONTrack &trackCandidate, const AliMUONVClusterStore& clusterStore,
                                                              Int_t nextStation)
 {
@@ -508,6 +654,13 @@ Bool_t AliMUONVTrackReconstructor::FollowLinearTrackInStation(AliMUONTrack &trac
   if (nextStation==4) trackParam = *(AliMUONTrackParam*)trackCandidate.GetTrackParamAtCluster()->Last();
   else trackParam = *(AliMUONTrackParam*)trackCandidate.GetTrackParamAtCluster()->First();
   
+  // Printout for debuging
+  if ((AliLog::GetDebugLevel("MUON","AliMUONVTrackReconstructor") >= 2) || (AliLog::GetGlobalDebugLevel() >= 2)) {
+    cout<<endl<<"Track parameters and covariances at first cluster:"<<endl;
+    trackParam.GetParameters().Print();
+    trackParam.GetCovariances().Print();
+  }
+  
   // Add MCS effect
   AliMUONTrackExtrap::AddMCSEffect(&trackParam,AliMUONConstants::ChamberThicknessInX0(),1.);
   
@@ -539,6 +692,7 @@ Bool_t AliMUONVTrackReconstructor::FollowLinearTrackInStation(AliMUONTrack &trac
       if ((AliLog::GetDebugLevel("MUON","AliMUONVTrackReconstructor") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
         cout << "FollowLinearTrackInStation: found one cluster in chamber(1..): " << ch2+1
             << " (Chi2 = " << chi2WithOneCluster << ")" << endl;
+       clusterCh2->Print();
         cout << "                      look for second clusters in chamber(1..): " << ch1+1 << " ..." << endl;
       }
       
@@ -567,7 +721,8 @@ Bool_t AliMUONVTrackReconstructor::FollowLinearTrackInStation(AliMUONTrack &trac
          // Printout for debuging
          if ((AliLog::GetDebugLevel("MUON","AliMUONVTrackReconstructor") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
            cout << "FollowLinearTrackInStation: found one cluster in chamber(1..): " << ch1+1
-                << " (Chi2 = " << chi2WithTwoClusters << ")" << endl;
+                << " (Chi2 = " << chi2WithTwoClusters << ")" << endl;
+           clusterCh1->Print();
          }
          
          if (AliMUONReconstructor::GetRecoParam()->TrackAllTracks()) {
@@ -606,7 +761,9 @@ Bool_t AliMUONVTrackReconstructor::FollowLinearTrackInStation(AliMUONTrack &trac
        if (AliMUONReconstructor::GetRecoParam()->TrackAllTracks()) {
          // copy trackCandidate into a new track put at the end of fRecTracksPtr and add the new cluster
           newTrack = new ((*fRecTracksPtr)[fRecTracksPtr->GetLast()+1]) AliMUONTrack(trackCandidate);
-         extrapTrackParamAtCluster2.SetRemovable(kFALSE);
+         if (AliMUONReconstructor::GetRecoParam()->RequestStation(nextStation))
+           extrapTrackParamAtCluster2.SetRemovable(kFALSE);
+         else extrapTrackParamAtCluster2.SetRemovable(kTRUE);
          newTrack->AddTrackParamAtCluster(extrapTrackParamAtCluster2,*clusterCh2);
          fNRecTracks++;
          
@@ -642,7 +799,7 @@ Bool_t AliMUONVTrackReconstructor::FollowLinearTrackInStation(AliMUONTrack &trac
     
     // add MCS effect for next step
     AliMUONTrackExtrap::AddMCSEffect(&trackParam,AliMUONConstants::ChamberThicknessInX0(),1.);
-      
+    
     // reset cluster iterator of chamber 1
     nextInCh1.Reset();
     iCluster1 = -1;
@@ -655,12 +812,12 @@ Bool_t AliMUONVTrackReconstructor::FollowLinearTrackInStation(AliMUONTrack &trac
       
       // try to add the current cluster fast
       if (!TryOneClusterFast(trackParam, clusterCh1)) continue;
-       
+      
       // try to add the current cluster accuratly
       extrapTrackParamAtCluster1 = trackParam;
       AliMUONTrackExtrap::LinearExtrapToZ(&extrapTrackParamAtCluster1, clusterCh1->GetZ());
       chi2WithOneCluster = TryOneCluster(extrapTrackParamAtCluster1, clusterCh1, extrapTrackParamAtCluster1);
-    
+      
       // if good chi2 then consider to add clusterCh1
       // We do not try to attach a cluster in the other chamber too since it has already been done above
       if (chi2WithOneCluster < maxChi2WithOneCluster) {
@@ -670,12 +827,15 @@ Bool_t AliMUONVTrackReconstructor::FollowLinearTrackInStation(AliMUONTrack &trac
        if ((AliLog::GetDebugLevel("MUON","AliMUONVTrackReconstructor") >= 1) || (AliLog::GetGlobalDebugLevel() >= 1)) {
          cout << "FollowLinearTrackInStation: found one cluster in chamber(1..): " << ch1+1
               << " (Chi2 = " << chi2WithOneCluster << ")" << endl;
+         clusterCh1->Print();
        }
        
        if (AliMUONReconstructor::GetRecoParam()->TrackAllTracks()) {
          // copy trackCandidate into a new track put at the end of fRecTracksPtr and add the new cluster
          newTrack = new ((*fRecTracksPtr)[fRecTracksPtr->GetLast()+1]) AliMUONTrack(trackCandidate);
-         extrapTrackParamAtCluster1.SetRemovable(kFALSE);
+         if (AliMUONReconstructor::GetRecoParam()->RequestStation(nextStation))
+           extrapTrackParamAtCluster1.SetRemovable(kFALSE);
+         else extrapTrackParamAtCluster1.SetRemovable(kTRUE);
          newTrack->AddTrackParamAtCluster(extrapTrackParamAtCluster1,*clusterCh1);
          fNRecTracks++;
          
@@ -712,7 +872,9 @@ Bool_t AliMUONVTrackReconstructor::FollowLinearTrackInStation(AliMUONTrack &trac
       }
       
     } else if (foundOneCluster) {
-      bestTrackParamAtCluster1.SetRemovable(kFALSE);
+      if (AliMUONReconstructor::GetRecoParam()->RequestStation(nextStation))
+       bestTrackParamAtCluster1.SetRemovable(kFALSE);
+      else bestTrackParamAtCluster1.SetRemovable(kTRUE);
       trackCandidate.AddTrackParamAtCluster(bestTrackParamAtCluster1,*(bestTrackParamAtCluster1.GetClusterPtr()));
       
       // Printout for debuging
index 73264be..259072c 100644 (file)
@@ -64,8 +64,10 @@ class AliMUONVTrackReconstructor : public TObject {
   AliMUONVTrackReconstructor (const AliMUONVTrackReconstructor& rhs); ///< copy constructor
   AliMUONVTrackReconstructor& operator=(const AliMUONVTrackReconstructor& rhs); ///< assignment operator
   
-  /// Make track candidats from clusters in stations(1..) 4 and 5
+  /// Make track candidates from clusters in stations(1..) 4 and 5
   virtual void MakeTrackCandidates(AliMUONVClusterStore& clusterStore) = 0;
+  /// Make extra track candidates from clusters in stations(1..) 4 and 5
+  virtual void MakeMoreTrackCandidates(AliMUONVClusterStore& clusterStore) = 0;
   /// Follow tracks in stations(1..) 3, 2 and 1
   virtual void FollowTracks(AliMUONVClusterStore& clusterStore) = 0;
   /// Complement the reconstructed tracks
@@ -77,13 +79,15 @@ class AliMUONVTrackReconstructor : public TObject {
   /// Finalize the given track
   virtual void FinalizeTrack(AliMUONTrack &track) = 0;
   
-  TClonesArray* MakeSegmentsInStation(const AliMUONVClusterStore& clusterStore, Int_t station);
+  TClonesArray* MakeSegmentsBetweenChambers(const AliMUONVClusterStore& clusterStore, Int_t ch1, Int_t ch2);
 
   void RemoveIdenticalTracks();
   void RemoveDoubleTracks();
 
   void AskForNewClustersInStation(const AliMUONTrackParam &trackParam,
                                  AliMUONVClusterStore& clusterStore, Int_t station);
+  void AskForNewClustersInChamber(const AliMUONTrackParam &trackParam,
+                                 AliMUONVClusterStore& clusterStore, Int_t chamber);
   
   Double_t TryOneCluster(const AliMUONTrackParam &trackParam, AliMUONVCluster* cluster,
                         AliMUONTrackParam &trackParamAtCluster, Bool_t updatePropagator = kFALSE);
@@ -91,8 +95,8 @@ class AliMUONVTrackReconstructor : public TObject {
   Double_t TryTwoClustersFast(const AliMUONTrackParam &trackParamAtCluster1, AliMUONVCluster* cluster2,
                              AliMUONTrackParam &trackParamAtCluster2);
 
-  Bool_t FollowLinearTrackInStation(AliMUONTrack &trackCandidate, const AliMUONVClusterStore& clusterStore,
-                                   Int_t nextStation);
+  Bool_t FollowLinearTrackInChamber(AliMUONTrack &trackCandidate, const AliMUONVClusterStore& clusterStore, Int_t nextChamber);
+  Bool_t FollowLinearTrackInStation(AliMUONTrack &trackCandidate, const AliMUONVClusterStore& clusterStore, Int_t nextStation);
   
 
  private:
index dd78e03..46adede 100644 (file)
@@ -65,6 +65,7 @@
 #include <Riostream.h>
 #include <TGeoManager.h>
 #include <TROOT.h>
+#include <TF1.h>
 
 #endif
 
@@ -588,7 +589,16 @@ Bool_t MUONefficiency( char* filename = "galice.root", char* geoFilename = "geom
   cout << "Chi2Cut for muon tracks = " << Chi2Cut << endl;
   cout << "PtCutMin for muon tracks = " << PtCutMin << endl;
   cout << "PtCutMax for muon tracks = " << PtCutMax << endl;
+  
+  hInvMassAll->Fit("gaus","q0");
+                   
+  TF1* f1 = hInvMassAll->GetFunction("gaus");
+  
+  cout << "Entries (unlike sign dimuons) : " << hInvMassAll->GetEntries() 
+    << Form(". Rough sigma = %7.2f MeV/c2",f1->GetParameter(2)*1000.0) << endl;
+  
   cout << "Entries (unlike sign dimuons) in the mass range  ["<<invMassMinInPeak<<";"<<invMassMaxInPeak<<"] : " << EventInMass <<endl;
+  
   if (ptTrig==0x800) cout << "Unlike Pair - All Pt" ;   
   if (ptTrig==0x400) cout << "Unlike Pair - High Pt" ;   
   if (ptTrig==0x200) cout << "Unlike Pair - Low Pt" ; 
index b7de853..ff65c4c 100644 (file)
@@ -51,6 +51,8 @@
 
 #pragma link C++ class AliMUONVClusterServer+;
 #pragma link C++ class AliMUONSimpleClusterServer+;
+#pragma link C++ class AliMUONLegacyClusterServer+;
+#pragma link C++ class AliMUONTriggerTrackToTrackerClusters+;
 
 #pragma link C++ class AliMUONESDInterface+;
 
index 1359734..a4b65e1 100644 (file)
@@ -42,7 +42,9 @@ SRCS:= AliMUONReconstructor.cxx \
        AliMUONClusterFinderPeakCOG.cxx \
        AliMUONClusterFinderPeakFit.cxx \
        AliMUONRefitter.cxx \
-       AliMUONESDInterface.cxx
+       AliMUONESDInterface.cxx \
+       AliMUONLegacyClusterServer.cxx \
+       AliMUONTriggerTrackToTrackerClusters.cxx
 
 HDRS:= $(SRCS:.cxx=.h)
 
index b4637b6..6461e56 100644 (file)
@@ -57,11 +57,18 @@ void runReconstruction(int seed, const char* input, const char* recoptions)
   //  MuonRec->SetEventRange(319,319);
   MuonRec->SetWriteAOD();
   
-  AliMUONRecoParam *muonRecoParam = AliMUONRecoParam::GetLowFluxParam();
-  muonRecoParam->CombineClusterTrackReco(kTRUE);
-  //muonRecoParam->SetClusteringMode("PEAKFIT");
-  //muonRecoParam->SetClusteringMode("PEAKCOG");
+  AliMUONRecoParam* muonRecoParam = AliMUONRecoParam::GetLowFluxParam();
+  muonRecoParam->CombineClusterTrackReco(kFALSE);
+  muonRecoParam->BypassSt45(kTRUE);
+  //  muonRecoParam->SetMaxBendingMomentum(10000000.0);
+  //  muonRecoParam->SetMaxNonBendingDistanceToTrack(200.0);
+  //  muonRecoParam->SetMaxBendingDistanceToTrack(200.0);
+  muonRecoParam->SetSigmaCutForTracking(20.0);
+  //  muonRecoParam->UseSmoother(kFALSE);  
+  muonRecoParam->RequestStation(2,kFALSE);
+  muonRecoParam->ImproveTracks(kFALSE);
   muonRecoParam->Print("FULL");
+
   AliRecoParam::Instance()->RegisterRecoParam(muonRecoParam);
   
   MuonRec->Run();
@@ -70,4 +77,3 @@ void runReconstruction(int seed, const char* input, const char* recoptions)
   
   //gObjectTable->Print();
 }
-