diff --git a/Trigger/TrigFTK/FTK_RecTools/CMakeLists.txt b/Trigger/TrigFTK/FTK_RecTools/CMakeLists.txt
index b6f47d680a707522ef9ee448358e5e5f9222ad8f..6e68377a4954dee3fa433e7c838cdb7e9fe0af37 100644
--- a/Trigger/TrigFTK/FTK_RecTools/CMakeLists.txt
+++ b/Trigger/TrigFTK/FTK_RecTools/CMakeLists.txt
@@ -7,18 +7,34 @@ atlas_subdir( FTK_RecTools )
 
 # Declare the package's dependencies:
 atlas_depends_on_subdirs( PUBLIC
+                          AtlasPolicy
                           Control/AthenaBaseComps
+                          Event/xAOD/xAODTracking
                           GaudiKernel
                           Tools/PyJobTransforms
+                          DetectorDescription/GeoPrimitives
                           Tracking/TrkEvent/TrkTrack
                           Tracking/TrkEvent/VxVertex
+                          Tracking/TrkVertexFitter/TrkVxEdmCnv
                           Trigger/TrigFTK/FTK_DataProviderInterfaces
                           Trigger/TrigFTK/FTK_RecToolInterfaces
                           Trigger/TrigFTK/TrigFTK_RawData
-                          Event/xAOD/xAODTracking
-                          Tracking/TrkVertexFitter/TrkVxEdmCnv 
-			  PRIVATE 
-			  Tracking/TrkEvent/TrkParameters)
+                          InnerDetector/InDetDetDescr/SCT_ModuleDistortions
+                          InnerDetector/InDetRecEvent/InDetPrepRawData
+                          InnerDetector/InDetRecEvent/InDetRIO_OnTrack
+                          Tracking/TrkEvent/TrkParameters
+                          Tracking/TrkTools/TrkToolInterfaces
+                          Tracking/TrkTools/TrkAmbiguityProcessor
+                          PRIVATE
+                          Event/EventPrimitives
+                          InnerDetector/InDetConditions/PixelConditionsServices
+                          InnerDetector/InDetConditions/PixelConditionsTools
+                          InnerDetector/InDetDetDescr/InDetIdentifier
+                          InnerDetector/InDetDetDescr/InDetReadoutGeometry
+                          InnerDetector/InDetDetDescr/PixelGeoModel
+                          InnerDetector/InDetRecTools/SiClusterizationTool
+                          Tracking/TrkDetDescr/TrkSurfaces )
+
 
 # External dependencies:
 find_package( ROOT COMPONENTS Core Tree MathCore Hist RIO pthread )
@@ -28,10 +44,10 @@ atlas_add_library( FTK_RecToolsLib
                    src/*.cxx
                    PUBLIC_HEADERS FTK_RecTools
                    INCLUDE_DIRS ${ROOT_INCLUDE_DIRS}
-                   LINK_LIBRARIES ${ROOT_LIBRARIES} AthenaBaseComps GaudiKernel TrkTrack TrkParameters VxVertex FTK_DataProviderInterfaces TrigFTK_RawData xAODTracking TrkVxEdmCnvLib)
+                   LINK_LIBRARIES ${ROOT_LIBRARIES} AthenaBaseComps GeoPrimitives xAODTracking TrkTrack VxVertex FTK_DataProviderInterfaces TrigFTK_RawData TrkVxEdmCnvLib  InDetPrepRawData InDetRIO_OnTrack TrkParameters TrkToolInterfaces TrkAmbiguityProcessorLib StoreGateLib SGtests EventPrimitives InDetIdentifier InDetReadoutGeometry SiClusterizationToolLib TrkSurfaces)
 
 atlas_add_component( FTK_RecTools
-                     src/components/*.cxx
+                     src/*.cxx src/components/*.cxx
                      INCLUDE_DIRS ${ROOT_INCLUDE_DIRS}
-                     LINK_LIBRARIES ${ROOT_LIBRARIES} AthenaBaseComps GaudiKernel TrkTrack TrkParameters VxVertex FTK_DataProviderInterfaces TrigFTK_RawData xAODTracking TrkVxEdmCnvLib FTK_RecToolsLib )
+                     LINK_LIBRARIES ${ROOT_LIBRARIES} AthenaBaseComps GeoPrimitives xAODTracking TrkTrack VxVertex TrkVxEdmCnvLib FTK_DataProviderInterfaces TrigFTK_RawData TrkParameters FTK_RecToolsLib InDetPrepRawData InDetRIO_OnTrack TrkParameters TrkToolInterfaces TrkAmbiguityProcessorLib StoreGateLib SGtests EventPrimitives InDetIdentifier InDetReadoutGeometry SiClusterizationToolLib TrkSurfaces)
 
diff --git a/Trigger/TrigFTK/FTK_RecTools/FTK_RecTools/FTK_PixelClusterOnTrackTool.h b/Trigger/TrigFTK/FTK_RecTools/FTK_RecTools/FTK_PixelClusterOnTrackTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..8533a1e0c21dc0867eef4fb84dd22bca97a57017
--- /dev/null
+++ b/Trigger/TrigFTK/FTK_RecTools/FTK_RecTools/FTK_PixelClusterOnTrackTool.h
@@ -0,0 +1,207 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+//  Header file for class  FTK_PixelClusterOnTrackTool
+///////////////////////////////////////////////////////////////////
+
+#ifndef FTK_PixelClusterOnTrackTool_H
+#define FTK_PixelClusterOnTrackTool_H
+
+#include "GaudiKernel/ToolHandle.h"
+#include "AthenaBaseComps/AthAlgTool.h"
+
+
+#include "TrkToolInterfaces/IRIO_OnTrackCreator.h"
+#include "TrkToolInterfaces/IRIO_OnTrackErrorScalingTool.h"
+#include "InDetRIO_OnTrack/PixelClusterOnTrack.h"
+
+#include "InDetPrepRawData/PixelGangedClusterAmbiguities.h"
+#include "TrkParameters/TrackParameters.h"
+//#include "InDetIdentifier/PixelID.h"
+#include "GeoPrimitives/GeoPrimitives.h"
+#include "TrkAmbiguityProcessor/dRMap.h"
+#include "SiClusterizationTool/NnClusterizationFactory.h"
+
+//#include "PixelConditionsServices/IPixelOfflineCalibSvc.h"
+//#include "PixelConditionsTools/IModuleDistortionsTool.h"
+
+#include "AthenaPoolUtilities/CondAttrListCollection.h"
+class PixelID;
+class IPixelOfflineCalibSvc;
+class IModuleDistortionsTool;
+
+class StoreGateSvc;
+class IBLParameterSvc;
+
+//namespace InDet {
+
+  /** @brief creates FTK_PixelClusterOnTrack objects allowing to
+      calibrate cluster position and error using a given track hypothesis. 
+
+      See doxygen of Trk::RIO_OnTrackCreator for details.
+      Different strategies to calibrate the cluster error can be chosen
+      by job Option. Also the handle to the general hit-error scaling
+      is implemented.
+
+      Special strategies for correction can be invoked by calling the
+      correct method with an additional argument from the 
+      PixelClusterStrategy enumeration
+
+  */
+
+
+namespace InDet {
+  enum PixelClusterStrategy {
+    PIXELCLUSTER_DEFAULT=0,
+    PIXELCLUSTER_OUTLIER=1,
+    PIXELCLUSTER_SHARED =2,
+    PIXELCLUSTER_SPLIT  =3
+    };
+}
+
+  class FTK_PixelClusterOnTrackTool: 
+        public AthAlgTool, virtual public Trk::IRIO_OnTrackCreator
+{
+  ///////////////////////////////////////////////////////////////////
+  // Public methods:
+  ///////////////////////////////////////////////////////////////////
+
+public:
+
+  //! AlgTool constructor 
+  FTK_PixelClusterOnTrackTool(const std::string&,const std::string&,
+                          const IInterface*);
+  virtual ~FTK_PixelClusterOnTrackTool ();
+  //! AlgTool initialisation
+  virtual StatusCode initialize() override;
+  //! AlgTool termination
+  virtual StatusCode finalize  () override;
+  
+  
+ 
+  void correctBow(const Identifier&, Amg::Vector2D& locpos, const double tanphi, const double taneta) const;
+
+  double splineIBLPullX(float x, int layer) const;
+
+  /** @brief produces a PixelClusterOnTrack (object factory!).
+
+      Depending on job options it changes the pixel cluster position
+      and error according to the parameters (in particular, the angle)
+      of the intersecting track.
+  */
+  virtual const InDet::PixelClusterOnTrack* correct(const Trk::PrepRawData&,
+                                                    const Trk::TrackParameters&) const;
+
+  virtual const InDet::PixelClusterOnTrack* correctDefault(const Trk::PrepRawData&, 
+                                                           const Trk::TrackParameters&) const;
+
+  virtual const InDet::PixelClusterOnTrack* correctNN(const Trk::PrepRawData&, const Trk::TrackParameters&) const;
+	
+  virtual bool getErrorsDefaultAmbi( const InDet::PixelCluster*, const Trk::TrackParameters&, 
+                           Amg::Vector2D&,  Amg::MatrixX&) const;
+													 
+  virtual bool getErrorsTIDE_Ambi( const InDet::PixelCluster*, const Trk::TrackParameters&,  
+                        Amg::Vector2D&,  Amg::MatrixX&) const;
+
+  virtual const InDet::PixelClusterOnTrack* correct
+    (const Trk::PrepRawData&, const Trk::TrackParameters&, 
+     const InDet::PixelClusterStrategy) const;
+
+     
+  ///////////////////////////////////////////////////////////////////
+  // Private methods:
+  ///////////////////////////////////////////////////////////////////
+  
+ private:
+
+  /** @brief parametrizes the pixel cluster position error as a function of 
+      the track angle alpha and the cluster width (number of rows) deltax */
+  //  double getBarrelPhiError(double& alpha, int& deltax) const;
+  //  double getBarrelEtaError(double eta, int deltax, int deltay) const;
+  // double getEndcapPhiError(int etasize, int phisize) const;
+  // double getEndcapEtaError(int etasize, int phisize) const;
+  
+  void FillFromDataBase() const;
+
+  ///////////////////////////////////////////////////////////////////
+  // Private data:
+  ///////////////////////////////////////////////////////////////////
+
+  ToolHandle<IModuleDistortionsTool>            m_pixDistoTool    ;
+  ToolHandle<Trk::IRIO_OnTrackErrorScalingTool> m_errorScalingTool;
+  ServiceHandle<IPixelOfflineCalibSvc>          m_calibSvc        ;
+  StoreGateSvc*                                 m_detStore        ;
+  /* ME: Test histos have nothing to do with production code, use a flag
+    IHistogram1D* m_h_Resx;
+    IHistogram1D* m_h_Resy;
+    IHistogram1D* m_h_Locx;
+    IHistogram1D* m_h_Locy;
+    IHistogram1D* m_h_PhiTrack;
+    IHistogram1D* m_h_ThetaTrack;
+    IHistogram1D* m_h_Rad; 
+    IHistogram1D* m_h_Slope;
+  */
+
+  //! toolhandle for central error scaling
+  //! flag storing if errors need scaling or should be kept nominal
+  bool                               m_scalePixelCov     ;
+  bool                               m_disableDistortions;
+  bool                               m_rel13like         ;
+  int                                m_positionStrategy  ;
+  mutable int                        m_errorStrategy     ;
+  
+  
+  /** @brief Flag controlling how module distortions are taken into account:
+      
+  case 0 -----> No distorsions implemented;
+  
+  case 1 -----> Set curvature (in 1/meter) and twist (in radiant) equal for all modules;
+  
+  case 2 -----> Read curvatures and twists from textfile containing Survey data;
+  
+  case 3 -----> Set curvature and twist from Gaussian random generator with mean and RMS coming from Survey data;
+  
+  case 4 -----> Read curvatures and twists from database (not ready yet);
+  */
+  //! identifier-helper
+  const PixelID*                     m_pixelid;
+  
+  /** Enable NN based calibration (do only if NN calibration is applied) **/
+  mutable bool                      m_applyNNcorrection;
+  mutable bool                      m_applydRcorrection;
+  bool				    m_NNIBLcorrection;
+  bool				    m_IBLAbsent;
+  
+  /** NN clusterizationi factory for NN based positions and errors **/
+  ToolHandle<InDet::NnClusterizationFactory>                   m_NnClusterizationFactory;
+  ServiceHandle<StoreGateSvc>                           m_storeGate;            //!< Event store
+  ServiceHandle<IBLParameterSvc>                        m_IBLParameterSvc;
+
+
+  SG::ReadHandleKey<InDet::DRMap>                      m_dRMap;      //!< the actual dR map         
+  std::string                                          m_dRMapName;
+  
+  bool                                                  m_doNotRecalibrateNN;
+  bool                                                  m_noNNandBroadErrors;
+	
+	/** Enable different treatment of  cluster errors based on NN information (do only if TIDE ambi is run) **/
+  bool                      m_usingTIDE_Ambi;
+  std::string m_splitClusterMapName; //no longer used
+  mutable std::vector< std::vector<float> > m_fX, m_fY, m_fB, m_fC, m_fD;
+  
+  //moved from static to member variable
+  static constexpr int nbinphi=9;
+  static constexpr int nbineta=6;
+  double calphi[nbinphi];
+  double caleta[nbineta][3];
+  double calerrphi[nbinphi][3];
+  double calerreta[nbineta][3];
+  double phix[nbinphi+1];
+  double etax[nbineta+1];
+};
+
+//} // end of namespace FTK
+
+#endif // FTK_PixelClusterOnTrackTool_H
diff --git a/Trigger/TrigFTK/FTK_RecTools/FTK_RecTools/FTK_SCTClusterOnTrackTool.h b/Trigger/TrigFTK/FTK_RecTools/FTK_RecTools/FTK_SCTClusterOnTrackTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..c6f76ff562169df433d7cc2e78bfa5787b743000
--- /dev/null
+++ b/Trigger/TrigFTK/FTK_RecTools/FTK_RecTools/FTK_SCTClusterOnTrackTool.h
@@ -0,0 +1,107 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+//  Header file for class  FTK_SCTClusterOnTrackTool
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+// Interface for SCT_ClusterOnTrack production
+///////////////////////////////////////////////////////////////////
+// started 1/05/2004 I.Gavrilenko - see ChangeLog for details
+///////////////////////////////////////////////////////////////////
+
+#ifndef FTK_SCTClusterOnTrackTool_H
+#define FTK_SCTClusterOnTrackTool_H
+
+#include "GaudiKernel/ToolHandle.h"
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "TrkToolInterfaces/IRIO_OnTrackCreator.h"
+#include "TrkToolInterfaces/IRIO_OnTrackErrorScalingTool.h"
+#include "TrkParameters/TrackParameters.h"
+#include "InDetRIO_OnTrack/SCT_ClusterOnTrack.h"
+#include "SCT_ModuleDistortions/ISCT_ModuleDistortionsTool.h"
+
+//namespace InDet {
+
+
+/** @brief creates SCT_ClusterOnTrack objects allowing to
+    calibrate cluster position and error using a given track hypothesis. 
+
+    See doxygen of Trk::RIO_OnTrackCreator for details.
+    Different strategies to calibrate the cluster error can be chosen
+    by job Option. Also the handle to the general hit-error scaling
+    is implemented.
+*/
+  class FTK_SCTClusterOnTrackTool: 
+    public AthAlgTool,virtual public Trk::IRIO_OnTrackCreator
+{
+  ///////////////////////////////////////////////////////////////////
+  // Public methods:
+  ///////////////////////////////////////////////////////////////////
+
+public:
+
+  //! AlgTool constructor 
+  FTK_SCTClusterOnTrackTool(const std::string&,const std::string&,const IInterface*);
+  virtual ~FTK_SCTClusterOnTrackTool ();
+  //! AlgTool initialisation
+  virtual StatusCode initialize();
+  //! AlgTool termination
+  virtual StatusCode finalize  ();
+
+  
+/** @brief produces an SCT_ClusterOnTrack using the measured
+    SCT_Cluster and the track prediction. 
+
+    This method is a factory, so the client has to take care
+     of management/deletion of the  SCT_ClusterOnTrack.
+ */
+  virtual const InDet::SCT_ClusterOnTrack* correct
+    (const Trk::PrepRawData&, const Trk::TrackParameters&) const; 
+
+  
+/** @brief Returns a correction to be applied to the SCT cluster local x position
+    in simulated events to remove a position bias introduced by the SCT digitisation.
+
+      @param [in] phi     angle of track relative to Lorentz drift direction, in transverse plane
+      @param [in] nstrip  SCT cluster size (number of strips)
+ */
+  double getCorrection(double phi, int nstrip) const;
+  
+
+/** @brief Returns the resolution on the reconstructed position (local x) of SCT clusters
+    in simulated events.
+
+      @param [in] phi     angle of track relative to Lorentz drift direction, in transverse plane
+      @param [in] nstrip  SCT cluster size (number of strips)
+
+    The parameterisation of the resolution contained in getError() was derived from SCT
+    barrel clusters (80 micron pitch).  It can be applied also to endcap clusters, after
+    rescaling to the appropriate pitch.
+ */
+  double getError(double phi, int nstrip) const;
+
+ private:
+
+  ///////////////////////////////////////////////////////////////////
+  // Private data:
+  ///////////////////////////////////////////////////////////////////
+
+   //! toolhandle for central error scaling
+   ToolHandle< Trk::IRIO_OnTrackErrorScalingTool > m_errorScalingTool;
+   ToolHandle<ISCT_ModuleDistortionsTool> m_distortionsTool;
+   //! flag storing if errors need scaling or should be kept nominal
+   bool                               m_scaleSctCov;
+
+   //! job options
+   bool                               m_option_make2dimBarrelClusters;
+   bool                               m_doDistortions ;//!< Flag to set Distortions
+   int                                m_option_errorStrategy;
+   int                                m_option_correctionStrategy;
+};
+
+//} // end of namespace FTK
+
+#endif // FTK_SCTClusterOnTrackTool_H
diff --git a/Trigger/TrigFTK/FTK_RecTools/src/FTK_PixelClusterOnTrackTool.cxx b/Trigger/TrigFTK/FTK_RecTools/src/FTK_PixelClusterOnTrackTool.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..aa756c64222fa1a075e9ddbb72d652e1218d9b81
--- /dev/null
+++ b/Trigger/TrigFTK/FTK_RecTools/src/FTK_PixelClusterOnTrackTool.cxx
@@ -0,0 +1,1058 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+/////////////////////////////////////////////////////////////////
+//   Implementation file for class FTK_PixelClusterOnTrackTool
+///////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////
+// AlgTool used for FTK_PixelClusterOnTrack object production
+///////////////////////////////////////////////////////////////////
+// Created 9/11/2016 J. Baines based on version by I.Gavrilenko
+///////////////////////////////////////////////////////////////////
+
+#include "FTK_RecTools/FTK_PixelClusterOnTrackTool.h"
+#include "InDetReadoutGeometry/SiDetectorManager.h"
+#include "InDetReadoutGeometry/PixelModuleDesign.h"
+#include "InDetIdentifier/PixelID.h"
+#include "PixelConditionsServices/IPixelOfflineCalibSvc.h"
+#include "PixelConditionsTools/IModuleDistortionsTool.h"
+#include "TrkSurfaces/PlaneSurface.h"
+#include "StoreGate/StoreGateSvc.h"
+#include "GaudiKernel/IIncidentSvc.h"
+#include "EventPrimitives/EventPrimitives.h"
+#include "PixelGeoModel/IBLParameterSvc.h"
+#include "InDetReadoutGeometry/SiDetectorElement.h"
+
+#include "CoralBase/AttributeListSpecification.h"
+#include "CoralBase/Attribute.h"
+#include "AthenaPoolUtilities/CondAttrListCollection.h"
+#include "AthenaPoolUtilities/AthenaAttributeList.h"
+using CLHEP::mm;
+using CLHEP::micrometer;
+
+///////////////////////////////////////////////////////////////////
+// Constructor
+///////////////////////////////////////////////////////////////////
+
+namespace
+{
+  // using x*x might be quicker than pow(x,2), depends on compiler optimisation
+  inline double
+  square(const double x) {
+    return x * x;
+  }
+
+  double
+  distance(const std::vector<Amg::Vector2D> &vectorOfPositions,
+           const std::vector<Amg::Vector2D> &allLocalPositions,
+           const std::vector<Amg::MatrixX> &allErrorMatrix,
+           const int i, const int j, const int k) {
+    return
+      square(vectorOfPositions[i][0] - allLocalPositions[0][0]) / allErrorMatrix[0](0, 0) +
+      square(vectorOfPositions[j][0] - allLocalPositions[1][0]) / allErrorMatrix[1](0, 0) +
+      square(vectorOfPositions[k][0] - allLocalPositions[2][0]) / allErrorMatrix[2](0, 0) +
+      square(vectorOfPositions[i][1] - allLocalPositions[0][1]) / allErrorMatrix[0](1, 1) +
+      square(vectorOfPositions[j][1] - allLocalPositions[1][1]) / allErrorMatrix[1](1, 1) +
+      square(vectorOfPositions[k][1] - allLocalPositions[2][1]) / allErrorMatrix[2](1, 1);
+  }
+
+  // avoid a lot of '/sqrt(12)' in loops, declare the constant here
+  // constexpr sqrt is a gcc extension, unsupported by clang.
+  //constexpr double TOPHAT_SIGMA = 1. / sqrt(12.);
+  static double TOPHAT_SIGMA = 1. / sqrt(12.);
+}
+
+
+FTK_PixelClusterOnTrackTool::FTK_PixelClusterOnTrackTool
+  (const std::string &t, const std::string &n, const IInterface *p) :
+  ::AthAlgTool(t, n, p),
+  m_pixDistoTool("PixelDistortionsTool", this),
+  m_errorScalingTool("Trk::RIO_OnTrackErrorScalingTool/RIO_OnTrackErrorScalingTool", this),
+  m_calibSvc("PixelOfflineCalibSvc", n),
+  m_detStore(nullptr),
+  m_scalePixelCov(false),
+  m_disableDistortions(false),
+  m_rel13like(false),
+  m_pixelid(nullptr),
+  m_applyNNcorrection(false),
+  m_applydRcorrection(false),
+  m_NNIBLcorrection(false),
+  m_IBLAbsent(true),
+  m_NnClusterizationFactory("InDet::NnClusterizationFactory/NnClusterizationFactory", this),
+  m_storeGate("StoreGateSvc", n),
+  m_IBLParameterSvc("IBLParameterSvc", n),
+  m_dRMap(""),
+  m_dRMapName("dRMap"),
+  m_doNotRecalibrateNN(false),
+  m_noNNandBroadErrors(false),
+  m_usingTIDE_Ambi(false),
+  m_splitClusterMapName("SplitClusterAmbiguityMap") {
+  declareInterface<IRIO_OnTrackCreator>(this);
+
+  declareProperty("ErrorScalingTool", m_errorScalingTool, "The error scaling tool");
+  declareProperty("PixelDistortionsTool", m_pixDistoTool, "Tool to retrieve pixel distortions");
+  declareProperty("PositionStrategy", m_positionStrategy = 1, "Which calibration of cluster positions");
+  declareProperty("ErrorStrategy", m_errorStrategy = 2, "Which calibration of cluster position errors");
+  declareProperty("DisableDistortions", m_disableDistortions, "Disable simulation of module distortions");
+  declareProperty("Release13like", m_rel13like, "Activate release-13 like settigs");
+  declareProperty("PixelOfflineCalibSvc", m_calibSvc, "Offline calibration svc");
+  declareProperty("applyNNcorrection", m_applyNNcorrection);
+  declareProperty("applydRcorrection", m_applydRcorrection);
+  declareProperty("NNIBLcorrection", m_NNIBLcorrection);
+  declareProperty("EventStore", m_storeGate);
+  declareProperty("NnClusterizationFactory", m_NnClusterizationFactory);
+  declareProperty("SplitClusterAmbiguityMap", m_splitClusterMapName);//Remove Later
+  declareProperty("dRMapName", m_dRMapName);  //This is a string to prevent the scheduler seeing trkAmbSolver as both creating and requiring the map
+  declareProperty("doNotRecalibrateNN", m_doNotRecalibrateNN);
+  declareProperty("m_noNNandBroadErrors", m_noNNandBroadErrors);
+  declareProperty("RunningTIDE_Ambi", m_usingTIDE_Ambi);
+}
+
+///////////////////////////////////////////////////////////////////
+// Destructor
+///////////////////////////////////////////////////////////////////
+
+FTK_PixelClusterOnTrackTool::~FTK_PixelClusterOnTrackTool() {
+}
+
+///////////////////////////////////////////////////////////////////
+// Initialisation
+///////////////////////////////////////////////////////////////////
+
+StatusCode
+FTK_PixelClusterOnTrackTool::initialize() {
+  StatusCode sc = AthAlgTool::initialize();
+
+  ATH_MSG_INFO(name() << " initialize()");
+  ATH_MSG_DEBUG("Error strategy is" << m_errorStrategy);
+  ATH_MSG_DEBUG("Release 13 flag is" << m_rel13like);
+
+  if (m_IBLParameterSvc.retrieve().isFailure()) {
+    ATH_MSG_WARNING("Could not retrieve IBLParameterSvc");
+  } else {
+    m_IBLParameterSvc->setBoolParameters(m_applyNNcorrection, "doPixelClusterSplitting");
+    m_IBLParameterSvc->setBoolParameters(m_IBLAbsent, "IBLAbsent");
+  }
+
+  // get the offline calibration service
+  sc = m_calibSvc.retrieve();
+  if (sc.isFailure() || !m_calibSvc) {
+    ATH_MSG_ERROR(m_calibSvc.type() << " not found! ");
+  } else {
+    ATH_MSG_INFO("Retrieved tool " << m_calibSvc.type());
+  }
+
+  // get the error scaling tool
+  if (m_errorScalingTool.retrieve().isFailure()) {
+    msg(MSG::FATAL) << "Failed to retrieve tool " << m_errorScalingTool << endmsg;
+    return StatusCode::FAILURE;
+  } else {
+    ATH_MSG_INFO("Retrieved tool " << m_errorScalingTool);
+    m_scalePixelCov = m_errorScalingTool->needToScalePixel();
+    if (m_scalePixelCov) {
+      ATH_MSG_DEBUG("Detected need for scaling Pixel errors.");
+    }
+  }
+
+  // the NN corrections
+  if (m_applyNNcorrection) {
+    msg(MSG::WARNING) << " NNcorrection not possible for FTK clusters - using default correction" << endmsg;
+    m_applyNNcorrection=false;
+  }
+
+  // get the module distortions tool
+  if (!m_disableDistortions) {
+    if (!m_pixDistoTool.empty()) {
+      sc = m_pixDistoTool.retrieve();
+      if (sc != StatusCode::SUCCESS) {
+        msg(MSG::ERROR) << "Can't get pixel distortions tool " << endmsg;
+      } else {
+        ATH_MSG_INFO("Pixel distortions tool retrieved");
+      }
+    } else {
+      ATH_MSG_INFO("No PixelDistortionsTool selected.");
+    }
+  } else {
+    ATH_MSG_INFO("No PixelDistortions will be simulated.");
+  }
+
+  if (detStore()->retrieve(m_pixelid, "PixelID").isFailure()) {
+    ATH_MSG_FATAL("Could not get Pixel ID helper");
+    return StatusCode::FAILURE;
+  }
+
+  sc = service("DetectorStore", m_detStore);
+  if (!sc.isSuccess() || 0 == m_detStore) {
+    return msg(MSG:: ERROR) << "Could not find DetStore" << endmsg, StatusCode::FAILURE;
+  }
+  if (m_storeGate.retrieve().isFailure()) {
+    ATH_MSG_WARNING("Can not retrieve " << m_storeGate << ". Exiting.");
+    return StatusCode::FAILURE;
+  }
+
+  /* ME : booking of test histos is something to be hidden from production code !
+     sc = service("HistogramDataSvc", m_HistSvc, true);
+     // Define here the histograms;
+     m_h_Resx = m_HistSvc->book(m_foldername,"Resx","X shift (um)",400,-400.,400.);
+     m_h_Resy = m_HistSvc->book(m_foldername,"Resy","Y shift (um)",400,-400.,400.);
+     m_h_Locx = m_HistSvc->book(m_foldername,"Locx","X position (mm)",400,-20.,20.);
+     m_h_Locy = m_HistSvc->book(m_foldername,"Locy","Y position (mm)",800,-40.,40.);
+     m_h_ThetaTrack = m_HistSvc->book(m_foldername,"ThetaTrack","Theta Track (rad)",140,-7.,7);
+     m_h_PhiTrack = m_HistSvc->book(m_foldername,"PhiTrack","Phi Track (rad)",140,-7.,7);
+   */
+   
+   
+  m_dRMap = SG::ReadHandleKey<InDet::DRMap>(m_dRMapName);
+  ATH_CHECK( m_dRMap.initialize() );
+  // Include IBL calibration constants
+  //Moved to initialize to remove statics and prevent repitition
+  
+  constexpr double phimin=-0.27, phimax=0.27;
+  for (int i=0; i<=nbinphi; i++) phix[i]=phimin+i*(phimax-phimin)/nbinphi;
+  constexpr double etacen[nbineta]={-0.,1.,1.55,1.9,2.15,2.35};
+  etax[0]=0.; etax[nbineta]=2.7;
+  for (int i=0; i<nbineta-1; i++) etax[i+1]=(etacen[i]+etacen[i+1])/2.;
+
+  ///UGLY!
+#include "IBL_calibration.h"
+  ///  
+
+   
+  return sc;
+}
+
+
+
+///////////////////////////////////////////////////////////////////
+// Finalize
+///////////////////////////////////////////////////////////////////
+
+StatusCode
+FTK_PixelClusterOnTrackTool::finalize() {
+  return AlgTool::finalize();
+}
+
+void
+FTK_PixelClusterOnTrackTool::FillFromDataBase() const{
+    if (m_fX.empty()) {
+      const CondAttrListCollection *atrlistcol = nullptr;
+      if (StatusCode::SUCCESS == m_detStore->retrieve(atrlistcol, "/PIXEL/PixelClustering/PixelCovCorr")) {
+        // loop over objects in collection
+        for (CondAttrListCollection::const_iterator citr = atrlistcol->begin(); citr != atrlistcol->end(); ++citr) {
+          std::vector<float> fx, fy, fb, fc, fd;
+          const coral::AttributeList &atrlist = citr->second;
+
+          fx.push_back(atrlist["fX1"].data<float>());
+          fx.push_back(atrlist["fX2"].data<float>());
+          fx.push_back(atrlist["fX3"].data<float>());
+          fx.push_back(atrlist["fX4"].data<float>());
+          fx.push_back(atrlist["fX5"].data<float>());
+          fx.push_back(atrlist["fX6"].data<float>());
+          fx.push_back(atrlist["fX7"].data<float>());
+          m_fX.emplace_back(std::move(fx));
+
+          fy.push_back(atrlist["fY1"].data<float>());
+          fy.push_back(atrlist["fY2"].data<float>());
+          fy.push_back(atrlist["fY3"].data<float>());
+          fy.push_back(atrlist["fY4"].data<float>());
+          fy.push_back(atrlist["fY5"].data<float>());
+          fy.push_back(atrlist["fY6"].data<float>());
+          fy.push_back(atrlist["fY7"].data<float>());
+          m_fY.emplace_back(std::move(fy));
+
+          fb.push_back(atrlist["fB1"].data<float>());
+          fb.push_back(atrlist["fB2"].data<float>());
+          fb.push_back(atrlist["fB3"].data<float>());
+          fb.push_back(atrlist["fB4"].data<float>());
+          fb.push_back(atrlist["fB5"].data<float>());
+          fb.push_back(atrlist["fB6"].data<float>());
+          fb.push_back(atrlist["fB7"].data<float>());
+          m_fB.emplace_back(std::move(fb));
+
+          fc.push_back(atrlist["fC1"].data<float>());
+          fc.push_back(atrlist["fC2"].data<float>());
+          fc.push_back(atrlist["fC3"].data<float>());
+          fc.push_back(atrlist["fC4"].data<float>());
+          fc.push_back(atrlist["fC5"].data<float>());
+          fc.push_back(atrlist["fC6"].data<float>());
+          fc.push_back(atrlist["fC7"].data<float>());
+          m_fC.emplace_back(std::move(fc));
+
+          fd.push_back(atrlist["fD1"].data<float>());
+          fd.push_back(atrlist["fD2"].data<float>());
+          fd.push_back(atrlist["fD3"].data<float>());
+          fd.push_back(atrlist["fD4"].data<float>());
+          fd.push_back(atrlist["fD5"].data<float>());
+          fd.push_back(atrlist["fD6"].data<float>());
+          fd.push_back(atrlist["fD7"].data<float>());
+          m_fD.emplace_back(std::move(fd));
+        }
+      }else {
+        msg(MSG::ERROR) << "Cannot find covariance corrections for key "
+                        << "/PIXEL/PixelClustering/PixelCovCorr" << " - no correction " << endmsg;
+        
+      }
+    }
+}
+
+
+///////////////////////////////////////////////////////////////////
+// Trk::SiClusterOnTrack  production
+///////////////////////////////////////////////////////////////////
+
+
+const InDet::PixelClusterOnTrack *
+FTK_PixelClusterOnTrackTool::correct
+  (const Trk::PrepRawData &rio, const Trk::TrackParameters &trackPar) const {
+
+
+  if (!m_applyNNcorrection ||
+      ((dynamic_cast<const InDetDD::SiDetectorElement *>(rio.detectorElement()))->isBlayer() && !m_NNIBLcorrection &&
+       !m_IBLAbsent)) {
+    return correctDefault(rio, trackPar);
+  }else {
+    if (m_errorStrategy == 0 || m_errorStrategy == 1) {
+      // version from Giacinto
+      if (m_noNNandBroadErrors) {
+        return 0;
+      }
+      // if we try broad errors, get Pixel Cluster to test if it is split
+      const InDet::PixelCluster *pix = dynamic_cast<const InDet::PixelCluster *>(&rio);
+      if (!pix) {
+        return 0;
+      }
+      if (pix->isSplit()) {
+        return correctNN(rio, trackPar);
+      } else {
+        return correctDefault(rio, trackPar);
+      }
+    } else {
+      return correctNN(rio, trackPar);
+    }
+  }
+}
+
+/** The correct method produces a PixelClusterOnTrack using the
+ *  measured PixelCluster and the track prediction.
+ */
+const InDet::PixelClusterOnTrack *
+FTK_PixelClusterOnTrackTool::correctDefault
+  (const Trk::PrepRawData &rio, const Trk::TrackParameters &trackPar) const {
+  //  const InDet::SiCluster* SC = dynamic_cast<const InDet::SiCluster*> (&rio);
+  const InDet::PixelCluster *pix = nullptr;
+
+  if (!(pix = dynamic_cast<const InDet::PixelCluster *>(&rio))) {
+    return 0;
+  }
+
+  ATH_MSG_VERBOSE("Correct called with Error strategy " << m_errorStrategy);
+
+  // PixelClusterOnTrack production
+  //
+  Trk::LocalParameters locpar;
+  Amg::Vector3D glob(pix->globalPosition());
+
+
+  // Get pointer to detector element
+  const InDetDD::SiDetectorElement *element = pix->detectorElement();
+  if (!element) {
+    return 0;
+  }
+  bool blayer = element->isBlayer();
+  IdentifierHash iH = element->identifyHash();
+
+  double errphi = -1;
+  double erreta = -1;
+
+  if (pix->rdoList().empty()) {
+    ATH_MSG_WARNING("Pixel RDO-list size is 0, check integrity of pixel clusters! stop ROT creation.");
+    return NULL;
+  } else {
+
+    // get candidate track angle in module local frame
+    Amg::Vector3D my_track = trackPar.momentum();
+    Amg::Vector3D my_normal = element->normal();
+    Amg::Vector3D my_phiax = element->phiAxis();
+    Amg::Vector3D my_etaax = element->etaAxis();
+    float trkphicomp = my_track.dot(my_phiax);
+    float trketacomp = my_track.dot(my_etaax);
+    float trknormcomp = my_track.dot(my_normal);
+    double bowphi = atan2(trkphicomp, trknormcomp);
+    double boweta = atan2(trketacomp, trknormcomp);
+    float etatrack = trackPar.eta();
+
+    float tanl = element->getTanLorentzAnglePhi();
+    int readoutside = element->design().readoutSide();
+
+    // map the angles of inward-going tracks onto [-PI/2, PI/2]
+    if (bowphi > M_PI *0.5) {
+      bowphi -= M_PI;
+    }
+    if (bowphi < -M_PI *0.5) {
+      bowphi += M_PI;
+    }
+    // finally, subtract the Lorentz angle effect
+    // the readoutside term is needed because of a bug in old
+    // geometry versions (CSC-01-* and CSC-02-*)
+    double angle = atan(tan(bowphi) - readoutside * tanl);
+
+    // try to understand...
+    const Identifier element_id = element->identify();
+    int PixEtaModule = m_pixelid->eta_module(element_id);
+    int PixPhiModule = m_pixelid->phi_module(element_id);
+    double PixTrkPt = trackPar.pT();
+    double PixTrkEta = trackPar.eta();
+    ATH_MSG_VERBOSE("tanl = " << tanl << " readout side is " << readoutside <<
+                    " module " << PixEtaModule << " " << PixPhiModule <<
+                    " track pt, eta = " << PixTrkPt << " " << PixTrkEta <<
+                    " track momentum phi, norm = " << trkphicomp << " " <<
+                    trknormcomp << " bowphi = " << bowphi << " angle = " << angle);
+
+    float omegaphi = pix->omegax();
+    float omegaeta = pix->omegay();
+    double localphi = -9999.;
+    double localeta = -9999.;
+
+    const std::vector<Identifier> & rdos = pix->rdoList();
+    std::vector<Identifier>::const_iterator oneRDO = rdos.begin();
+    Identifier rId = *oneRDO;
+    const int row = m_pixelid->phi_index(rId);
+    const int col = m_pixelid->eta_index(rId);
+
+    InDetDD::SiLocalPosition centroid = pix->localPosition();
+    double shift = element->getLorentzCorrection();
+    int nrows = pix->width().colRow()[Trk::locX];
+    int ncol = pix->width().colRow()[Trk::locX];
+    double ang = 999.;
+    double eta = 999.;
+    ATH_MSG_VERBOSE(" row " << row << " col " << col << " nrows " << nrows << 
+		    " ncol " << ncol << " locX " << centroid.xPhi() << " locY " << centroid.xEta());
+    
+    //    ATH_MSG_VERBOSE ( << "Position strategy = "
+    //    << m_positionStrategy << "omegaphi = " << omegaphi )
+
+    // TOT interpolation for collision data
+    // Force IBL to use digital clustering and broad errors.
+    if (m_positionStrategy > 0 && omegaphi > -0.5 && omegaeta > -0.5) {
+      localphi = centroid.xPhi() + shift;
+      localeta = centroid.xEta();
+      // barrel
+      if (element->isBarrel()) {
+        ang = 180 * angle * M_1_PI; //M_1_PI in cmath, = 1/pi
+        double delta = 0.;
+        if (m_IBLAbsent || !blayer) {
+          delta = m_calibSvc->getBarrelDeltaX(nrows, ang);
+        } else {             // special calibration for IBL
+          if (angle < phix[0] || angle > phix[nbinphi] || nrows != 2) {
+            delta = 0.;
+          }else {
+            int bin = -1;
+            while (angle > phix[bin + 1]) {
+              bin++;
+            }
+            if ((bin >= 0)and(bin < nbinphi)) {
+              delta = calphi[bin];
+            } else {
+              ATH_MSG_ERROR("bin out of range in line " << __LINE__ << " of FTK_PixelClusterOnTrackTool.cxx.");
+            }
+          }
+          if (m_calibSvc->includesIBLParams()) {
+            delta = m_calibSvc->getIBLDeltaX(nrows, ang);
+          }
+        }
+        localphi += delta * (omegaphi - 0.5);
+	ATH_MSG_VERBOSE(" shifting localphi by delta * (omegaphi - 0.5) = " << delta << " * " << (omegaphi - 0.5)); 
+        // settle the sign/pi periodicity issues
+        double thetaloc = -999.;
+        if (boweta > -0.5 * M_PI && boweta < M_PI / 2.) { //M_PI_2 in cmath
+          thetaloc = M_PI_2 - boweta;
+        }else if (boweta > M_PI_2 && boweta < M_PI) {
+          thetaloc = 1.5 * M_PI - boweta;
+        } else { // 3rd quadrant
+          thetaloc = -M_PI_2 - boweta;
+        }
+        double etaloc = -1 * log(tan(thetaloc * 0.5));
+        if (m_IBLAbsent || !blayer) {
+          delta = m_calibSvc->getBarrelDeltaY(ncol, etaloc);
+	  ATH_MSG_VERBOSE(" Barrel Pixel: shifting localeta by delta * (omegaeta - 0.5) = " << delta << " * " << (omegaeta - 0.5)); 
+        } else {     // special calibration for IBL
+          etaloc = fabs(etaloc);
+          if (etaloc < etax[0] || etaloc > etax[nbineta]) {
+            delta = 0.;
+          } else {
+            int bin = -1;
+            while (etaloc > etax[bin + 1]) {
+              bin++;
+            }
+            if ((bin >= 0)and(bin < nbineta)) {
+              if (ncol == bin) {
+                delta = caleta[bin][0];
+              } else if (ncol == bin + 1) {
+                delta = caleta[bin][1];
+              } else if (ncol == bin + 2) {
+                delta = caleta[bin][2];
+              } else {
+                delta = 0.;
+              }
+            } else {// bin out of range of array indices
+              ATH_MSG_ERROR("bin out of range in line " << __LINE__ << " of FTK_PixelClusterOnTrackTool.cxx.");
+            }
+
+          }
+          if (m_calibSvc->includesIBLParams()) {
+            delta = m_calibSvc->getIBLDeltaY(ncol, etaloc);
+          }
+	  ATH_MSG_VERBOSE(" IBL: shifting localeta by delta * (omegaeta - 0.5) = " << delta << " * " << (omegaeta - 0.5)); 
+        }
+        localeta += delta * (omegaeta - 0.5);
+      }else {
+        // collision endcap data
+        if (m_positionStrategy == 1) {
+          double deltax = m_calibSvc->getEndcapDeltaX();
+          double deltay = m_calibSvc->getEndcapDeltaY();
+          localphi += deltax * (omegaphi - 0.5);
+          localeta += deltay * (omegaeta - 0.5);
+	  ATH_MSG_VERBOSE(" endcap pixel shifting localphi by deltax * (omegaphi - 0.5) = " << deltax << " * " << (omegaphi - 0.5)); 
+	  ATH_MSG_VERBOSE(" endcap pixel shifting localeta by deltay * (omegaeta - 0.5) = " << deltay << " * " << (omegaeta - 0.5)); 
+        }
+        // SR1 cosmics endcap data
+        // some parametrization dependent on track angle
+        // would be better here
+        else if (m_positionStrategy == 20) {
+          double deltax = 35 * micrometer;
+          double deltay = 35 * micrometer;
+          localphi += deltax * (omegaphi - 0.5);
+          localeta += deltay * (omegaeta - 0.5);
+        }
+      }
+    }
+// digital
+    else {
+      localphi = centroid.xPhi() + shift;
+      localeta = centroid.xEta();
+    }
+
+    InDet::SiWidth width = pix->width();
+
+    // Error strategies
+
+    // For very shallow tracks the cluster can easily break as
+    // the average charge per pixel is of the order of the threshold
+    // In this case, an error equal to the geometrical projection
+    // of the track path in silicon onto the module surface seems
+    // appropriate
+    if (fabs(angle) > 1) {
+      errphi = 250 * micrometer * tan(fabs(angle)) * TOPHAT_SIGMA;
+      erreta = width.z() > 250 * micrometer * tan(fabs(boweta)) ?
+               width.z() * TOPHAT_SIGMA : 250 * micrometer * tan(fabs(boweta)) * TOPHAT_SIGMA;
+      ATH_MSG_VERBOSE("Shallow track with tanl = " << tanl << " bowphi = " <<
+                      bowphi << " angle = " << angle << " width.z = " << width.z() <<
+                      " errphi = " << errphi << " erreta = " << erreta);
+    }else if (m_errorStrategy == 0) {
+      errphi = width.phiR() * TOPHAT_SIGMA;
+      erreta = width.z() * TOPHAT_SIGMA;
+    }else if (m_errorStrategy == 1) {
+      errphi = (width.phiR() / nrows) * TOPHAT_SIGMA;
+      erreta = (width.z() / ncol) * TOPHAT_SIGMA;
+    }else if (m_errorStrategy == 2) {
+      if (element->isBarrel()) {
+        if (m_IBLAbsent || !blayer) {
+          errphi = m_calibSvc->getBarrelNewErrorPhi(ang, nrows);
+        } else {       // special calibration for IBL
+          if (angle < phix[0] || angle > phix[nbinphi]) {
+            errphi = width.phiR() * TOPHAT_SIGMA;
+          } else {
+            int bin = -1;// cannot be used as array index, which will happen if angle<phix[bin+1]
+            while (angle > phix[bin + 1]) {
+              bin++;
+            }
+            if ((bin >= 0)and(bin < nbinphi)) {
+              if (nrows == 1) {
+                errphi = calerrphi[bin][0];
+              } else if (nrows == 2) {
+                errphi = calerrphi[bin][1];
+              } else {
+                errphi = calerrphi[bin][2];
+              }
+            } else {
+              ATH_MSG_ERROR("bin out of range in line " << __LINE__ << " of FTK_PixelClusterOnTrackTool.cxx.");
+            }
+          }
+        }
+
+        if (m_rel13like) {
+          erreta = m_calibSvc->getBarrelErrorEta(eta, ncol, nrows);
+        }else if (m_IBLAbsent || !blayer) {
+          erreta = m_calibSvc->getBarrelNewErrorEta(fabs(etatrack), nrows, ncol);
+        } else {    // special calibration for IBL
+          double etaloc = fabs(etatrack);
+          if (etaloc < etax[0] || etaloc > etax[nbineta]) {
+            erreta = width.z() * TOPHAT_SIGMA;
+          } else {
+            int bin = 0;
+            while (etaloc > etax[bin + 1]) {
+              ++bin;
+            }
+            if (bin >= nbineta) {
+              ATH_MSG_ERROR("bin out of range in line " << __LINE__ << " of FTK_PixelClusterOnTrackTool.cxx.");
+            } else {
+              if (ncol == bin) {
+                erreta = calerreta[bin][0];
+              } else if (ncol == bin + 1) {
+                erreta = calerreta[bin][1];
+              } else if (ncol == bin + 2) {
+                erreta = calerreta[bin][2];
+              } else {
+                erreta = width.z() * TOPHAT_SIGMA;
+              }
+            }
+          }
+        }
+      }else {
+        errphi = m_calibSvc->getEndCapErrorPhi(ncol, nrows);
+        erreta = m_calibSvc->getEndCapErrorEta(ncol, nrows);
+      }
+      if (errphi > erreta) {
+        erreta = width.z() * TOPHAT_SIGMA;
+      }
+    }
+
+    Amg::Vector2D locpos = Amg::Vector2D(localphi, localeta);
+    if (element->isBarrel() && !m_disableDistortions) {
+      correctBow(element->identify(), locpos, bowphi, boweta);
+    }
+
+
+    locpar = Trk::LocalParameters(locpos);
+    centroid = InDetDD::SiLocalPosition(localeta, localphi, 0.);
+    glob = element->globalPosition(centroid);
+  }
+
+  // Error matrix production
+
+  Amg::MatrixX cov = pix->localCovariance();
+
+  // corrected phi error
+  if (errphi > 0) {
+    cov(0, 0) = errphi * errphi;
+  }
+  if (erreta > 0) {
+    cov(1, 1) = erreta * erreta;
+  }
+
+  ATH_MSG_VERBOSE(" errphi =  " << errphi << " erreta = " << erreta);
+
+  // create new copy of error matrix
+  if (m_scalePixelCov) {
+    Amg::MatrixX *newCov = m_errorScalingTool->createScaledPixelCovariance(cov, element->identify());
+    if (!newCov) {
+      ATH_MSG_WARNING("Failed to create scaled error for Pixel");
+      return 0;
+    }
+    cov = *newCov;
+    delete newCov;
+  }
+  bool isbroad = (m_errorStrategy == 0) ? true : false;
+
+  ATH_MSG_VERBOSE("returning corrected cluster at locX " << locpar.get(Trk::locX) << " locY " << locpar.get(Trk::locY));
+
+  return new InDet::PixelClusterOnTrack(pix, locpar, cov, iH, glob, pix->gangedPixel(), isbroad);
+}
+
+void
+FTK_PixelClusterOnTrackTool::correctBow(const Identifier &id, Amg::Vector2D &localpos, const double phi,
+                                           const double theta) const {
+  Amg::Vector3D dir(tan(phi), tan(theta), 1.);
+  Amg::Vector2D newpos =
+    m_pixDistoTool->correctReconstruction(id, localpos, dir);
+
+  localpos = newpos;
+  return;
+}
+
+const InDet::PixelClusterOnTrack *
+FTK_PixelClusterOnTrackTool::correct
+  (const Trk::PrepRawData &rio, const Trk::TrackParameters &trackPar,
+   const InDet::PixelClusterStrategy strategy) const {
+  int initial_errorStrategy;
+  const InDet::PixelClusterOnTrack *newROT;
+
+  switch (strategy) {
+  case InDet::PIXELCLUSTER_OUTLIER: // if cluster is outlier, increase errors
+  case InDet::PIXELCLUSTER_SHARED:
+    initial_errorStrategy = m_errorStrategy;
+    if (!m_rel13like) {
+      m_errorStrategy = 0; // error as size of cluster /sqrt(12)
+    }
+    newROT = correct(rio, trackPar);
+    m_errorStrategy = initial_errorStrategy;
+    return newROT;
+
+  default:
+    return correct(rio, trackPar);
+  }
+}
+
+// GP: NEW correct() method in case of NN based calibration  */
+const InDet::PixelClusterOnTrack *
+FTK_PixelClusterOnTrackTool::correctNN
+  (const Trk::PrepRawData &rio, const Trk::TrackParameters &trackPar) const {
+  
+  return correct(rio, trackPar);
+}
+
+bool
+FTK_PixelClusterOnTrackTool::getErrorsDefaultAmbi(const InDet::PixelCluster *pixelPrepCluster,
+                                                     const Trk::TrackParameters &trackPar,
+                                                     Amg::Vector2D &finalposition,
+                                                     Amg::MatrixX &finalerrormatrix) const {
+  std::vector<Amg::Vector2D> vectorOfPositions;
+  int numberOfSubclusters = 1;
+
+  vectorOfPositions.push_back(pixelPrepCluster->localPosition());
+
+
+
+  // A.S. hack for the moment: isSplit is also set for modified (non-split) 1-pixel-clusters ... is this needed anyway ?
+  //
+  // if (pixelPrepCluster->isSplit() && numberOfSubclusters<2)
+  // {
+  // msg(MSG::WARNING) << " Cluster is split but no further clusters found in split cluster map." << endmsg;
+  // }
+
+  // now you have numberOfSubclusters and the vectorOfPositions (Amg::Vector2D)
+
+  const Trk::AtaPlane *parameters = dynamic_cast<const Trk::AtaPlane *>(&trackPar);
+  if (parameters == 0) {
+    msg(MSG::WARNING) << "Parameters are not at a plane ! Aborting cluster correction... " << endmsg;
+    return false;
+  }
+
+  std::vector<Amg::Vector2D>     allLocalPositions;
+  std::vector<Amg::MatrixX>      allErrorMatrix;
+
+  allLocalPositions =
+    m_NnClusterizationFactory->estimatePositions(*pixelPrepCluster,
+                                                 parameters->associatedSurface(),
+                                                 *parameters,
+                                                 allErrorMatrix,
+                                                 numberOfSubclusters);
+
+  if (allLocalPositions.size() == 0) {
+    if (msgLvl(MSG::DEBUG)) {
+      msg(MSG::DEBUG) << " Cluster cannot be treated by NN. Giving back to default clusterization " << endmsg;
+    }
+    return false;
+  }
+
+  if (allLocalPositions.size() != size_t(numberOfSubclusters)) {
+    msg(MSG::WARNING) << "Returned position vector size " << allLocalPositions.size() <<
+    " not according to expected number of subclusters: " << numberOfSubclusters << ". Abort cluster correction..." <<
+    endmsg;
+    return false;
+  }
+
+
+  // GP: now the not so nice part of matching the new result with the old one...
+  // Takes the error into account to improve the matching
+
+  if (numberOfSubclusters == 1) {
+    finalposition = allLocalPositions[0];
+    finalerrormatrix = allErrorMatrix[0];
+  }
+
+  else if (numberOfSubclusters == 2) {
+    double distancesq1 =
+      square(vectorOfPositions[0][0] - allLocalPositions[0][0]) / allErrorMatrix[0](0, 0) +
+      square(vectorOfPositions[1][0] - allLocalPositions[1][0]) / allErrorMatrix[1](0, 0) +
+      square(vectorOfPositions[0][1] - allLocalPositions[0][1]) / allErrorMatrix[0](1, 1) +
+      square(vectorOfPositions[1][1] - allLocalPositions[1][1]) / allErrorMatrix[1](1, 1);
+
+    double distancesq2 =
+      square(vectorOfPositions[1][0] - allLocalPositions[0][0]) / allErrorMatrix[0](0, 0) +
+      square(vectorOfPositions[0][0] - allLocalPositions[1][0]) / allErrorMatrix[1](0, 0) +
+      square(vectorOfPositions[1][1] - allLocalPositions[0][1]) / allErrorMatrix[0](1, 1) +
+      square(vectorOfPositions[0][1] - allLocalPositions[1][1]) / allErrorMatrix[1](1, 1);
+
+    if (msgLvl(MSG::DEBUG)) {
+      msg(MSG::DEBUG) << " Old pix (1) x: " << vectorOfPositions[0][0] << " y: " << vectorOfPositions[0][1] << endmsg;
+      msg(MSG::DEBUG) << " Old pix (2) x: " << vectorOfPositions[1][0] << " y: " << vectorOfPositions[1][1] << endmsg;
+      msg(MSG::DEBUG) << " Pix (1) x: " << allLocalPositions[0][0] << " +/- " << sqrt(allErrorMatrix[0](0, 0))
+                      << " y: " << allLocalPositions[0][1] << " +/- " << sqrt(allErrorMatrix[0](1, 1)) << endmsg;
+      msg(MSG::DEBUG) << " Pix (2) x: " << allLocalPositions[1][0] << " +/- " << sqrt(allErrorMatrix[1](0, 0))
+                      << " y: " << allLocalPositions[1][1] << " +/- " << sqrt(allErrorMatrix[1](1, 1)) << endmsg;
+      msg(MSG::DEBUG) << " Old (1) new (1) dist: " << sqrt(distancesq1) << " Old (1) new (2) " << sqrt(distancesq2) <<
+      endmsg;
+    }
+
+    if (distancesq1 < distancesq2) {
+      finalposition = allLocalPositions[0];
+      finalerrormatrix = allErrorMatrix[0];
+    }else {
+      finalposition = allLocalPositions[1];
+      finalerrormatrix = allErrorMatrix[1];
+    }
+  }
+
+
+  else if (numberOfSubclusters == 3) {
+    double distances[6];
+
+    distances[0] = distance(vectorOfPositions, allLocalPositions, allErrorMatrix, 0, 1, 2);
+    distances[1] = distance(vectorOfPositions, allLocalPositions, allErrorMatrix, 0, 2, 1);
+    distances[2] = distance(vectorOfPositions, allLocalPositions, allErrorMatrix, 1, 0, 2);
+    distances[3] = distance(vectorOfPositions, allLocalPositions, allErrorMatrix, 1, 2, 0);
+    distances[4] = distance(vectorOfPositions, allLocalPositions, allErrorMatrix, 2, 0, 1);
+    distances[5] = distance(vectorOfPositions, allLocalPositions, allErrorMatrix, 2, 1, 0);
+
+    int smallestDistanceIndex = -10;
+    double minDistance = 1e10;
+
+    for (int i = 0; i < 6; i++) {
+      ATH_MSG_VERBOSE(" distance n.: " << i << " distance is: " << distances[i]);
+
+      if (distances[i] < minDistance) {
+        minDistance = distances[i];
+        smallestDistanceIndex = i;
+      }
+    }
+
+    ATH_MSG_DEBUG(" The minimum distance is : " << minDistance << " for index: " << smallestDistanceIndex);
+
+    if (smallestDistanceIndex == 0 || smallestDistanceIndex == 1) {
+      finalposition = allLocalPositions[0];
+      finalerrormatrix = allErrorMatrix[0];
+    }
+    if (smallestDistanceIndex == 2 || smallestDistanceIndex == 4) {
+      finalposition = allLocalPositions[1];
+      finalerrormatrix = allErrorMatrix[1];
+    }
+    if (smallestDistanceIndex == 3 || smallestDistanceIndex == 5) {
+      finalposition = allLocalPositions[2];
+      finalerrormatrix = allErrorMatrix[2];
+    }
+  }
+  return true;
+}
+
+bool
+FTK_PixelClusterOnTrackTool::getErrorsTIDE_Ambi(const InDet::PixelCluster *pixelPrepCluster,
+                                                   const Trk::TrackParameters &trackPar,
+                                                   Amg::Vector2D &finalposition,
+                                                   Amg::MatrixX &finalerrormatrix) const {
+  std::vector<Amg::Vector2D> vectorOfPositions;
+
+  int numberOfSubclusters = 1;
+  // now you have numberOfSubclusters and the vectorOfPositions (Amg::Vector2D)
+
+  const Trk::AtaPlane *parameters = dynamic_cast<const Trk::AtaPlane *>(&trackPar);
+  if (parameters == 0) {
+    ATH_MSG_WARNING("Parameters are not at a plane ! Aborting cluster correction... ");
+    return false;
+  }
+
+  std::vector<Amg::Vector2D>     allLocalPositions;
+  std::vector<Amg::MatrixX>      allErrorMatrix;
+  allLocalPositions =
+    m_NnClusterizationFactory->estimatePositions(*pixelPrepCluster,
+                                                 parameters->associatedSurface(),
+                                                 *parameters,
+                                                 allErrorMatrix,
+                                                 numberOfSubclusters);
+
+  if (allLocalPositions.empty()) {
+    ATH_MSG_DEBUG(
+      " Cluster cannot be treated by NN. Giving back to default clusterization, too big: " <<
+    pixelPrepCluster->tooBigToBeSplit());
+    return false;
+  }
+
+  if (allLocalPositions.size() != size_t(numberOfSubclusters)) {
+    ATH_MSG_WARNING(
+      "Returned position vector size " << allLocalPositions.size() << " not according to expected number of subclusters: " << numberOfSubclusters <<
+    ". Abort cluster correction...");
+    return false;
+  }
+
+  bool correctdR = false;
+  
+  std::array<float, 3> correctiondR = {0., 0., 0.};
+  
+  if(m_applydRcorrection){
+    SG::ReadHandle<InDet::DRMap> mapHandle(m_dRMap);
+    if(!mapHandle.isValid()){
+       ATH_MSG_ERROR("Error retreving " << m_dRMap.key());
+       return false;
+    }
+  
+    if(!mapHandle->empty() && pixelPrepCluster->isSplit() ){
+
+    const InDetDD::SiDetectorElement *det = pixelPrepCluster->detectorElement();
+
+    if (det->isBarrel()) {
+      int pixelLayer = m_pixelid->layer_disk(det->identify());
+
+      float correctiondRX = 1.0; // correction factor to be applied to covariance(!)
+      float correctiondRZ = 1.0; // correction factor to be applied to covariance(!)
+
+      const InDetDD::PixelModuleDesign *design(dynamic_cast<const InDetDD::PixelModuleDesign *>(&det->design()));
+      if (! design){
+        ATH_MSG_WARNING("Design cannot be cast to a pixel design");
+        return false;
+      }
+      const float pitchX = design->phiPitch();
+      const float pitchZ = design->etaPitch();
+
+      ATH_MSG_DEBUG("FTK_PixelClusterOnTrackTool: Trying to apply dR correction for pixelLayer " << pixelLayer);
+
+      InDet::DRMap::const_iterator it = mapHandle->find(pixelPrepCluster);
+      if (it != mapHandle->end()) {
+        correctdR = true;
+        float mindX = it->second.first;
+        float mindZ = it->second.second;
+        float mindXOverPitch = mindX / pitchX;
+        float mindZOverPitch = mindZ / pitchZ;
+
+        float dR = sqrt(mindX * mindX + mindZ * mindZ);
+
+        ATH_MSG_DEBUG(" ---- Min dX ---- " << mindX << " mindZ " << mindZ);
+
+        if (dR > 0. && dR < 2.0) {
+          correctiondRX = splineIBLPullX(mindXOverPitch, pixelLayer);
+          correctiondRZ = splineIBLPullX(mindZOverPitch, pixelLayer);
+
+          if (correctiondRX > 3.75) {
+            correctiondRX = 3.75;
+          }
+          if (correctiondRZ > 3.75) {
+            correctiondRZ = 3.75;
+          }
+        }else {
+          correctiondRX = 2.35;
+          correctiondRZ = 1.70;
+        }
+
+        ATH_MSG_DEBUG(
+          "FTK_PixelClusterOnTrackTool: Correction factor calculation for distX/pitch= " << mindXOverPitch << " -> " << correctiondRX << " distZ/pitch= " << mindZOverPitch << " -> " <<
+        correctiondRZ);
+      }else {
+        ATH_MSG_WARNING("Split Pixel cluster not found in dRmap! " << pixelPrepCluster);
+      }
+
+      ATH_MSG_DEBUG(
+        " ++++ Hit Error ++++ Layer " << pixelLayer << " Correction Flag " << m_applydRcorrection << " Split " << pixelPrepCluster->isSplit() << " Scaling " << correctiondRX << " " <<
+      correctiondRZ);
+
+      correctiondRX *= correctiondRX;
+      correctiondRZ *= correctiondRZ;
+
+      correctiondR[0] = correctiondRX * correctiondRX;
+      correctiondR[1] = correctiondRZ * correctiondRZ;
+      correctiondR[2] = correctiondRX * correctiondRZ;
+    }
+   }
+  }
+  // AKM: now the not so nice part find the best match position option
+  // Takes the error into account to scale the importance of the measurement
+
+  if (numberOfSubclusters == 1) {
+    finalposition = allLocalPositions[0];
+
+    if (correctdR) {
+      allErrorMatrix[0](0, 0) *= correctiondR[0];
+      allErrorMatrix[0](1, 1) *= correctiondR[1];
+      allErrorMatrix[0](0, 1) *= correctiondR[2];
+      allErrorMatrix[0](1, 0) *= correctiondR[2];
+      ATH_MSG_DEBUG(
+        " ++++ Hit Error ++++ " << numberOfSubclusters << " Split " << pixelPrepCluster->isSplit() << " Scaling " <<
+      sqrt(correctiondR[0]) << " " << sqrt(correctiondR[1]) << " Rescaled ErrX " << sqrt(allErrorMatrix[0](0,
+                                                                                                           0)) << " Rescaled ErrZ " <<
+      sqrt(allErrorMatrix[0](1, 1)));
+    }
+
+    finalerrormatrix = allErrorMatrix[0];
+    return true;
+  }
+
+  // Get the track parameters local position
+  const Amg::Vector2D localpos = trackPar.localPosition();
+  // Use the track parameters cov to weight distcances
+  Amg::Vector2D localerr(0.01, 0.05);
+  if (trackPar.covariance()) {
+    localerr = Amg::Vector2D(sqrt((*trackPar.covariance())(0, 0)), sqrt((*trackPar.covariance())(1, 1)));
+  }
+
+  double minDistance(1e300);
+  int index(0);
+
+  for (unsigned int i(0); i < allLocalPositions.size(); ++i) {
+    double distance =
+      square(localpos[0] - allLocalPositions[i][0]) / localerr[0]
+      + square(localpos[1] - allLocalPositions[i][1]) / localerr[1];
+
+    if (distance < minDistance) {
+      index = i;
+      minDistance = distance;
+    }
+  }
+
+  finalposition = allLocalPositions[index];
+
+  if (correctdR) {
+    allErrorMatrix[index](0, 0) *= correctiondR[0];
+    allErrorMatrix[index](1, 1) *= correctiondR[1];
+    allErrorMatrix[index](0, 1) *= correctiondR[2];
+    allErrorMatrix[index](1, 0) *= correctiondR[2];
+    ATH_MSG_DEBUG(
+      " ++++ Hit Error ++++ " << numberOfSubclusters << " Split " << pixelPrepCluster->isSplit() << " Scaling " <<
+    sqrt(correctiondR[0]) << " " << sqrt(correctiondR[1]) << " Rescaled ErrX " << sqrt(allErrorMatrix[index](0,
+                                                                                                             0)) << " Rescaled ErrZ " <<
+    sqrt(allErrorMatrix[index](1, 1)));
+  }
+
+  finalerrormatrix = allErrorMatrix[index];
+  return true;
+}
+
+double
+FTK_PixelClusterOnTrackTool::splineIBLPullX(float x, int layer) const {
+  FillFromDataBase();
+  const int fNp = m_fY[layer].size();
+  const int fKstep = 0;
+  const double fDelta = -1;
+  const auto result = std::minmax_element(std::begin(m_fX[layer]), std::end(m_fX[layer]));
+  const double fXmin = *(result.first);
+  const double fXmax = *(result.second);
+  //const double fXmin = *std::min_element(std::begin(m_fX[layer]), std::end(m_fX[layer]));
+  //const double fXmax = *std::max_element(std::begin(m_fX[layer]), std::end(m_fX[layer]));
+
+  int klow = 0;
+
+  if (x <= fXmin) {
+    klow = 0;
+  } else if (x >= fXmax) {
+    klow = fNp - 1;
+  } else {
+    if (fKstep) {
+      // Equidistant knots, use histogramming
+      klow = int((x - fXmin) / fDelta);
+      if (klow < fNp - 1) {
+        klow = fNp - 1;
+      }
+    } else {
+      int khig = fNp - 1, khalf;
+      // Non equidistant knots, binary search
+      while (khig - klow > 1) {
+        if (x > m_fX[layer][khalf = (klow + khig) / 2]) {
+          klow = khalf;
+        } else {
+          khig = khalf;
+        }
+      }
+    }
+  }
+  // Evaluate now
+  double dx = x - m_fX[layer][klow];
+  return(m_fY[layer][klow] + dx * (m_fB[layer][klow] + dx * (m_fC[layer][klow] + dx * m_fD[layer][klow])));
+}
diff --git a/Trigger/TrigFTK/FTK_RecTools/src/FTK_SCTClusterOnTrackTool.cxx b/Trigger/TrigFTK/FTK_RecTools/src/FTK_SCTClusterOnTrackTool.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..f98a727a8359e64d766ee63c992d8aa059e5aeec
--- /dev/null
+++ b/Trigger/TrigFTK/FTK_RecTools/src/FTK_SCTClusterOnTrackTool.cxx
@@ -0,0 +1,411 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+//   Implementation file for class FTK_SCTClusterOnTrackTool
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+// AlgTool used for SCT_ClusterOnTrack object production
+///////////////////////////////////////////////////////////////////
+// started 21/04/2004 I.Gavrilenko -- see ChangeLog
+///////////////////////////////////////////////////////////////////
+
+#include "FTK_RecTools/FTK_SCTClusterOnTrackTool.h"
+
+#include "TrkSurfaces/RectangleBounds.h"
+#include "TrkSurfaces/TrapezoidBounds.h"
+
+using CLHEP::micrometer;
+using CLHEP::deg;
+
+///////////////////////////////////////////////////////////////////
+// Constructor
+///////////////////////////////////////////////////////////////////
+
+FTK_SCTClusterOnTrackTool::FTK_SCTClusterOnTrackTool
+  (const std::string &t, const std::string &n, const IInterface *p) :
+  AthAlgTool(t, n, p),
+  m_errorScalingTool("Trk::RIO_OnTrackErrorScalingTool/RIO_OnTrackErrorScalingTool", this),
+  m_distortionsTool("SCT_DistortionsTool", this),
+  m_scaleSctCov(false),
+  m_option_make2dimBarrelClusters(false),
+  m_doDistortions(false),
+  m_option_errorStrategy(-1),
+  m_option_correctionStrategy(-1) {
+  // declareInterface<FTK_SCTClusterOnTrackTool>(this);
+  declareInterface<IRIO_OnTrackCreator>(this);
+
+  declareProperty("ErrorScalingTool", m_errorScalingTool,
+                  "The toolhandle for central error scaling");
+  declareProperty("MakeTwoDimBarrelClusters", m_option_make2dimBarrelClusters,
+                  "flag if strip length should be part of the measurement");
+  declareProperty("ErrorStrategy", m_option_errorStrategy,
+                  "if ErrorStrategy < 0, keep previous errors else recompute");
+  declareProperty("CorrectionStrategy", m_option_correctionStrategy,
+                  "if CorrectionStrategy >= 0, apply a correction to the cluster position");
+  declareProperty("doDistortions", m_doDistortions,
+                  "Simulation of module distortions");
+  declareProperty("SCTDistortionsTool", m_distortionsTool,
+                  "Tool to retrieve SCT distortions");
+}
+
+///////////////////////////////////////////////////////////////////
+// Destructor
+///////////////////////////////////////////////////////////////////
+
+FTK_SCTClusterOnTrackTool::~FTK_SCTClusterOnTrackTool() {
+}
+
+///////////////////////////////////////////////////////////////////
+// Initialisation
+///////////////////////////////////////////////////////////////////
+
+StatusCode
+FTK_SCTClusterOnTrackTool::initialize() {
+  StatusCode sc = AlgTool::initialize();
+
+  msg(MSG::INFO) << "A strategy to ";
+  switch (m_option_errorStrategy) {
+  case -1:  msg(MSG::INFO) << "keep the PRD errors";
+    break;
+
+  case  0:  msg(MSG::INFO) << "apply simple pitch errors";
+    break;
+
+  case  1:  msg(MSG::INFO) << "assign tuned SCT errors";
+    break;
+
+  case  2:  msg(MSG::INFO) << "assign tuned, angle-dependent SCT errors";
+    break;
+
+  default:  msg(MSG::INFO) << " -- NO, UNKNOWN. Pls check jobOptions!";
+    break;
+  }
+  msg(MSG::INFO) << " will be applied during SCT_ClusterOnTrack making" << endmsg;
+  if (m_option_correctionStrategy == 0) {
+    msg(MSG::INFO) << "SCT cluster positions will be corrected" << endmsg;
+  }
+
+  if (m_errorScalingTool.retrieve().isFailure()) {
+    msg(MSG::FATAL) << "Failed to retrieve tool " << m_errorScalingTool << endmsg;
+    return StatusCode::FAILURE;
+  } else {
+    msg(MSG::INFO) << "Retrieved tool " << m_errorScalingTool << endmsg;
+    m_scaleSctCov = m_errorScalingTool->needToScaleSct();
+    if (m_scaleSctCov) {
+      msg(MSG::DEBUG) << "Detected need for scaling SCT errors." << endmsg;
+    }
+  }
+
+  // Get ISCT_ModuleDistortionsTool
+  if (m_distortionsTool.retrieve().isFailure()) {
+    msg(MSG::FATAL) << "Could not retrieve distortions tool: " << m_distortionsTool.name() << endmsg;
+    return StatusCode::FAILURE;
+  }
+
+  return sc;
+}
+
+///////////////////////////////////////////////////////////////////
+// Finalize
+///////////////////////////////////////////////////////////////////
+
+StatusCode
+FTK_SCTClusterOnTrackTool::finalize() {
+  StatusCode sc = AlgTool::finalize();
+
+  return sc;
+}
+
+///////////////////////////////////////////////////////////////////
+// Trk::SCT_ClusterOnTrack  production
+///////////////////////////////////////////////////////////////////
+
+const InDet::SCT_ClusterOnTrack *
+FTK_SCTClusterOnTrackTool::correct
+  (const Trk::PrepRawData &rio, const Trk::TrackParameters &trackPar) const {
+  const InDet::SCT_Cluster *SC = 0;
+
+  if (!(SC = dynamic_cast<const InDet::SCT_Cluster *> (&rio))) {
+    msg(MSG::VERBOSE) << "not a InDet::SCT_Cluster, return null" <<endmsg;
+    return 0;
+  }
+
+  const InDet::SiWidth width = SC->width();
+  const Amg::Vector2D &colRow = width.colRow();
+
+  // Get pointer to detector element
+  //
+  const InDetDD::SiDetectorElement *EL = SC->detectorElement();
+  if (!EL) {
+    msg(MSG::VERBOSE) << "can't get SiDetectorElement, return null" <<endmsg;
+    return 0;
+  }
+  IdentifierHash iH = EL->identifyHash();
+
+  // Get local position of track
+  //
+  Amg::Vector2D loct = trackPar.localPosition();
+
+  // Find phi angle of track relative to Lorentz drift direction, if needed
+  //
+  double dphi(0.);
+  double sinAlpha = EL->sinStereoLocal(SC->localPosition());
+  double cosAlpha = sqrt(1 - sinAlpha * sinAlpha);
+  if (m_option_errorStrategy == 2 || m_option_correctionStrategy == 0) {
+    double pNormal = trackPar.momentum().dot(EL->normal());
+    double pPhi = trackPar.momentum().dot(Amg::AngleAxis3D(asin(-sinAlpha), Amg::Vector3D::UnitZ()) * EL->phiAxis());
+    dphi = atan(pPhi / pNormal) - atan(EL->getTanLorentzAnglePhi());
+  }
+
+  // SCT_ClusterOnTrack production
+  Amg::MatrixX oldcov = SC->localCovariance();
+  // Local position and error matrix production
+  //
+  // let's start to re-compute cluster error if errorStrategy >=0
+  if (m_option_errorStrategy > -1) {
+    Amg::MatrixX mat(2, 2);
+    mat.setZero();
+    switch (m_option_errorStrategy) {
+    case 0:
+      mat(0, 0) = pow(width.phiR(), 2) / 12;
+      mat(1, 1) = pow(width.z(), 2) / 12;
+      break;
+
+    case 1:
+      if (colRow.x() == 1) {
+        mat(0, 0) = pow(1.05 * width.phiR(), 2) / 12;
+      } else if (colRow.x() == 2) {
+        mat(0, 0) = pow(0.27 * width.phiR(), 2) / 12;
+      } else {
+        mat(0, 0) = pow(width.phiR(), 2) / 12;
+      }
+      mat(1, 1) = pow(width.z() / colRow.y(), 2) / 12;
+      break;
+
+    case 2:
+      mat(0, 0) = pow(getError(dphi, int(colRow.x())) * (EL->phiPitch() / 0.080), 2);
+      mat(1, 1) = pow(width.z() / colRow.y(), 2) / 12;
+      break;
+
+    default:
+      // don't do anything....
+      break;
+    }
+    // rotation for endcap SCT
+    if (EL->design().shape() == InDetDD::Trapezoid) {
+      double sn = EL->sinStereoLocal(SC->localPosition());
+      double sn2 = sn * sn;
+      double cs2 = 1. - sn2;
+      double w = EL->phiPitch(SC->localPosition()) / EL->phiPitch();
+      double v0 = mat(0, 0) * w * w;
+      double v1 = mat(1, 1);
+      mat(0, 0) = (cs2 * v0 + sn2 * v1);
+      mat(1, 0) = (sn * sqrt(cs2) * (v0 - v1));
+      mat(0, 1) = mat(1, 0);
+      mat(1, 1) = (sn2 * v0 + cs2 * v1);
+    }
+    oldcov = mat;
+  }
+
+  Amg::MatrixX cov(oldcov);
+  Trk::LocalParameters locpar;
+
+  if (EL->design().shape() != InDetDD::Trapezoid) {                     // barrel
+    Trk::DefinedParameter lpos1dim(SC->localPosition().x(), Trk::locX);
+    locpar = (m_option_make2dimBarrelClusters)       ?
+             Trk::LocalParameters(SC->localPosition()) :// PRDformation does 2-dim
+             Trk::LocalParameters(lpos1dim);
+    if (!m_option_make2dimBarrelClusters) {
+      cov = Amg::MatrixX(1, 1);
+      cov(0, 0) = oldcov(0, 0);
+    }
+
+    if (m_scaleSctCov) {
+      Amg::MatrixX *newCov = m_errorScalingTool->createScaledSctCovariance(cov, false, 0.0);
+      if (!newCov) {
+        ATH_MSG_WARNING("Failed to create scaled error for SCT");
+        return 0;
+      }
+      cov = *newCov;
+      delete newCov;
+    }
+  }else {                                           // endcap
+    locpar = Trk::LocalParameters(SC->localPosition());
+    if (m_scaleSctCov) {
+      Amg::MatrixX *newCov = m_errorScalingTool->createScaledSctCovariance(cov, true,
+                                                                           EL->sinStereoLocal(SC->localPosition()));
+      if (!newCov) {
+        ATH_MSG_WARNING("Failed to create scaled error for SCT");
+        return 0;
+      }
+      cov = *newCov;
+      delete newCov;
+    }
+    double Sn = EL->sinStereoLocal(SC->localPosition());
+    double Sn2 = Sn * Sn;
+    double Cs2 = (1. - Sn) * (1. + Sn);
+    double SC = Sn * sqrt(Cs2);
+    double W = EL->phiPitch(loct) / EL->phiPitch();
+    double dV0 = (Cs2 * cov(0, 0) + Sn2 * cov(1, 1) +
+                  2. * SC * cov(1, 0)) * (W * W - 1.);
+    cov(0, 0) += (Cs2 * dV0);
+    cov(1, 0) += (SC * dV0);
+    cov(0, 1) = cov(1, 0);
+    cov(1, 1) += (Sn2 * dV0);
+  }
+
+  if (m_doDistortions) {
+    if (EL->isBarrel() == 1) {// Only apply disortions to barrel modules
+      locpar[Trk::locX] -= m_distortionsTool->correctReconstruction(trackPar, *EL, locpar, loct);
+    }
+  }
+
+
+  // Apply correction for cluster position bias
+  //
+  if (m_option_correctionStrategy == 0) {
+    double correction = getCorrection(dphi, int(colRow.x())) * EL->hitDepthDirection();
+    locpar[Trk::locX] += correction;
+  }
+  bool isbroad = (m_option_errorStrategy == 0) ? true : false;
+
+  msg(MSG::VERBOSE) << "returning corrected SCT cluster-on-track with position locX= " << locpar[Trk::locX] <<endmsg;
+  
+  InDet::SCT_ClusterOnTrack* clus=nullptr; 
+
+  Amg::Vector3D localstripdir(-sinAlpha, cosAlpha, 0.);
+  Amg::Vector3D globalstripdir = trackPar.associatedSurface().transform().linear() * localstripdir;
+  double distance = (trackPar.position() - SC->globalPosition()).mag();
+  const Trk::TrapezoidBounds *tbounds =
+    dynamic_cast<const Trk::TrapezoidBounds *>(&trackPar.associatedSurface().bounds());
+  const Trk::RectangleBounds *rbounds =
+    dynamic_cast<const Trk::RectangleBounds *>(&trackPar.associatedSurface().bounds());
+  
+  if (tbounds || rbounds) {
+
+    double boundsy = rbounds ? rbounds->halflengthY() : tbounds->halflengthY();
+    if (distance * cosAlpha > boundsy) {
+      distance = boundsy / cosAlpha - 1;
+    }
+  
+
+    if (loct.y() < 0) {
+      distance = -distance;
+    }
+    Amg::Vector3D glob (SC->globalPosition() + distance * globalstripdir);
+    clus = new InDet::SCT_ClusterOnTrack(SC, locpar, cov, iH, glob, isbroad);
+  } else {
+    clus = new InDet::SCT_ClusterOnTrack(SC, locpar, cov, iH, SC->globalPosition(), isbroad);
+  }
+
+  return clus;
+}
+
+double
+FTK_SCTClusterOnTrackTool::getCorrection(double phi, int nstrip) const {
+  float corr1[30] = {
+    0.3, 0.8, 1.1, 1.5, 1.9, 1.9, 2.1, 2.4, 2.3, 2.6,
+    2.6, 2.7, 2.8, 2.7, 2.5, 2.6, 2.8, 2.6, 2.6, 2.7,
+    2.2, 1.8, 1.8, 1.6, 1.5, 0.0, 0.0, 0.0, 0.0, 0.0
+  };
+  float corr2[30] = {
+    0.0, 0.0, 0.0, 1.0, 1.5, 1.7, 1.7, 2.3, 2.1, 2.5,
+    2.5, 2.7, 2.7, 2.9, 3.0, 3.0, 3.0, 3.0, 3.4, 3.4,
+    3.0, 3.2, 2.6, 2.6, 3.0, 2.7, 2.5, 2.4, 1.7, 1.3
+  };
+
+  // Phi bins have 1 degree width, and cover 0-30 degrees
+  int phiBin = int(fabs(phi) / deg);
+
+  float correction(0.);
+
+  if (phiBin < 30) {
+    if (nstrip == 1) {
+      correction = corr1[phiBin];
+    }
+    if (nstrip == 2) {
+      correction = corr2[phiBin];
+    }
+  }
+
+  if (phi > 0.) {
+    correction *= -1.;
+  }
+
+  return correction * micrometer;
+}
+
+double
+FTK_SCTClusterOnTrackTool::getError(double phi, int nstrip) const {
+  float sigma1[60] = {
+    22.1, 21.8, 21.4, 21.0, 20.5, 20.0, 19.6, 19.1, 18.5, 18.0,
+    17.4, 17.0, 16.4, 15.8, 15.4, 14.9, 14.4, 14.1, 13.3, 13.1,
+    12.9, 12.4, 12.6, 12.2, 12.3, 12.6, 13.4, 14.2, 15.6, 19.3,
+    22.8, 29.5, 33.2, 41.8, 44.3, 48.4, 49.9, 54.0, 53.0, 56.3,
+    57.5, 56.3, 64.5, 65.7, 66.1, 69.4, 74.8, 78.3, 78.8, 79.8,
+    73.5, 73.8, 75.8, 84.3, 87.0, 99.9, 86.3, 0.0, 0.0, 0.0
+  };
+  float sigma2[60] = {
+    22.2, 20.3, 18.8, 16.0, 14.6, 13.8, 12.9, 12.9, 12.7, 12.3,
+    12.7, 12.6, 13.0, 13.3, 14.0, 14.6, 15.3, 15.9, 16.6, 17.6,
+    18.4, 19.3, 19.9, 20.5, 21.0, 21.2, 21.5, 21.4, 21.3, 21.3,
+    20.9, 20.8, 20.6, 20.7, 20.3, 20.7, 21.7, 24.4, 26.5, 29.5,
+    34.6, 41.6, 48.5, 52.3, 54.5, 58.4, 61.8, 66.7, 69.9, 72.1,
+    78.9, 79.2, 81.8, 80.9, 87.5, 99.2, 0.0, 0.0, 0.0, 0.0
+  };
+  float sigma3[60] = {
+    70.1, 73.6, 71.7, 66.9, 68.3, 66.8, 66.2, 64.8, 66.6, 63.3,
+    63.3, 60.4, 59.0, 57.1, 56.4, 54.4, 54.2, 54.4, 50.3, 48.9,
+    48.1, 41.9, 38.0, 31.8, 28.3, 23.1, 23.0, 20.3, 18.5, 17.6,
+    17.7, 16.8, 18.3, 19.3, 19.0, 20.0, 20.9, 21.6, 22.0, 22.2,
+    22.7, 22.4, 24.3, 24.8, 24.6, 27.0, 29.8, 37.0, 47.7, 49.3,
+    58.2, 60.2, 66.8, 70.8, 77.3, 80.6, 0.0, 0.0, 0.0, 0.0
+  };
+  float sigma4[60] = {
+    103.2, 100.4, 100.7, 101.2, 107.4, 100.6, 100.9, 100.4, 96.3, 98.2,
+    96.7, 94.5, 96.9, 91.7, 90.5, 89.5, 86.3, 90.6, 82.4, 89.3,
+    87.3, 77.6, 75.7, 77.2, 77.3, 84.1, 80.1, 66.9, 73.7, 72.3,
+    58.1, 65.6, 64.2, 54.7, 47.2, 44.4, 34.6, 36.4, 29.1, 25.8,
+    18.8, 21.6, 18.6, 20.3, 22.7, 23.3, 24.1, 22.4, 24.7, 24.7,
+    27.3, 30.4, 37.0, 46.4, 59.4, 62.6, 65.3, 0.0, 0.0, 0.0
+  };
+  float sigma5[60] = {
+    150.9, 139.7, 133.9, 139.8, 141.4, 134.9, 138.4, 129.3, 137.9, 128.7,
+    132.4, 130.1, 124.2, 115.8, 131.4, 115.2, 128.7, 112.8, 130.7, 129.0,
+    115.8, 101.3, 115.9, 116.1, 121.7, 109.9, 110.0, 97.2, 96.4, 107.3,
+    98.2, 80.0, 73.2, 87.0, 97.0, 88.5, 72.2, 73.9, 80.8, 75.7,
+    69.5, 67.1, 54.1, 58.9, 47.3, 50.6, 29.5, 26.6, 25.8, 20.9,
+    20.6, 21.9, 22.1, 21.1, 27.9, 41.6, 0.0, 0.0, 0.0, 0.0
+  };
+
+  // Phi bins have 1 degree width, and cover 0-60 degrees
+  int phiBin = int(fabs(phi) / deg);
+
+  float sigma(0.);
+
+  if (phiBin < 60) {
+    if (nstrip == 1) {
+      sigma = sigma1[phiBin];
+    }
+    if (nstrip == 2) {
+      sigma = sigma2[phiBin];
+    }
+    if (nstrip == 3) {
+      sigma = sigma3[phiBin];
+    }
+    if (nstrip == 4) {
+      sigma = sigma4[phiBin];
+    }
+    if (nstrip == 5) {
+      sigma = sigma5[phiBin];
+    }
+  }
+  if (sigma < 0.1) {
+    sigma = std::max(100., float(nstrip) * 80. / sqrt(12));
+  }
+
+  return sigma * micrometer;
+}
diff --git a/Trigger/TrigFTK/FTK_RecTools/src/IBL_calibration.h b/Trigger/TrigFTK/FTK_RecTools/src/IBL_calibration.h
new file mode 100644
index 0000000000000000000000000000000000000000..36a61072052d8329dc463ab646143d5061f97f54
--- /dev/null
+++ b/Trigger/TrigFTK/FTK_RecTools/src/IBL_calibration.h
@@ -0,0 +1,76 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+calphi[0] = 0.0463822;
+calerrphi[0][0] = 0.00458704;
+calerrphi[0][1] = 0.00240123;
+calerrphi[0][2] = 0.0381553;
+calphi[1] = 0.0395409;
+calerrphi[1][0] = 0.00571953;
+calerrphi[1][1] = 0.00217718;
+calerrphi[1][2] = 0.0443544;
+calphi[2] = 0.0291725;
+calerrphi[2][0] = 0.00753389;
+calerrphi[2][1] = 0.00192153;
+calerrphi[2][2] = 0.0502262;
+calphi[3] = 0.0221493;
+calerrphi[3][0] = 0.00908161;
+calerrphi[3][1] = 0.00234422;
+calerrphi[3][2] = 0.052859;
+calphi[4] = 0.0183585;
+calerrphi[4][0] = 0.009916;
+calerrphi[4][1] = 0.00307481;
+calerrphi[4][2] = 0.0560763;
+calphi[5] = 0.0228795;
+calerrphi[5][0] = 0.00886146;
+calerrphi[5][1] = 0.00260481;
+calerrphi[5][2] = 0.0516711;
+calphi[6] = 0.0296685;
+calerrphi[6][0] = 0.00746781;
+calerrphi[6][1] = 0.00197842;
+calerrphi[6][2] = 0.0497699;
+calphi[7] = 0.0395992;
+calerrphi[7][0] = 0.00557493;
+calerrphi[7][1] = 0.00213298;
+calerrphi[7][2] = 0.0454933;
+calphi[8] = 0.0497221;
+calerrphi[8][0] = 0.00461163;
+calerrphi[8][1] = 0.00251781;
+calerrphi[8][2] = 0.0309285;
+caleta[0][0] = 0;
+caleta[0][1] = 0;
+caleta[0][2] = 0.0669391;
+calerreta[0][0] = 0;
+calerreta[0][1] = 0.0614102;
+calerreta[0][2] = 0.00891571;
+caleta[1][0] = 0.0669391;
+caleta[1][1] = 0.199526;
+caleta[1][2] = 0.0642114;
+calerreta[1][0] = 0.0445204;
+calerreta[1][1] = 0.05385;
+calerreta[1][2] = 0.0104638;
+caleta[2][0] = 0.322464;
+caleta[2][1] = 0.207504;
+caleta[2][2] = 0.0699703;
+calerreta[2][0] = 0.045776;
+calerreta[2][1] = 0.0222315;
+calerreta[2][2] = 0.0106168;
+caleta[3][0] = 0.299711;
+caleta[3][1] = 0.215319;
+caleta[3][2] = 0.0653161;
+calerreta[3][0] = 0.0277008;
+calerreta[3][1] = 0.0218932;
+calerreta[3][2] = 0.0108854;
+caleta[4][0] = 0.295881;
+caleta[4][1] = 0.215595;
+caleta[4][2] = 0.0284735;
+calerreta[4][0] = 0.0281094;
+calerreta[4][1] = 0.0215104;
+calerreta[4][2] = 0.0159464;
+caleta[5][0] = 0.321041;
+caleta[5][1] = 0.216542;
+caleta[5][2] = 0.172694;
+calerreta[5][0] = 0.0312848;
+calerreta[5][1] = 0.0236938;
+calerreta[5][2] = 0.0202331;
diff --git a/Trigger/TrigFTK/FTK_RecTools/src/components/FTK_RecTools_entries.cxx b/Trigger/TrigFTK/FTK_RecTools/src/components/FTK_RecTools_entries.cxx
index 5c4c30317cd5afafce2cf4cafc893f2f8a88d0e5..f376046dab2dd39d49f034fe50f97b6bb725c999 100644
--- a/Trigger/TrigFTK/FTK_RecTools/src/components/FTK_RecTools_entries.cxx
+++ b/Trigger/TrigFTK/FTK_RecTools/src/components/FTK_RecTools_entries.cxx
@@ -1,9 +1,15 @@
 #include "GaudiKernel/DeclareFactoryEntries.h"
 
 #include "FTK_RecTools/FTK_VertexFinderTool.h"
+#include "FTK_RecTools/FTK_PixelClusterOnTrackTool.h"
+#include "FTK_RecTools/FTK_SCTClusterOnTrackTool.h"
 
 DECLARE_TOOL_FACTORY(FTK_VertexFinderTool)
+DECLARE_TOOL_FACTORY(FTK_PixelClusterOnTrackTool)
+DECLARE_TOOL_FACTORY(FTK_SCTClusterOnTrackTool)
 
 DECLARE_FACTORY_ENTRIES(FTK_RecTools) {
   DECLARE_TOOL(FTK_VertexFinderTool)
+  DECLARE_TOOL(FTK_PixelClusterOnTrackTool)
+  DECLARE_TOOL(FTK_SCTClusterOnTrackTool)
 }