diff --git a/Tracking/Acts/ActsGeometry/ActsGeometry/ActsExtrapolationTool.h b/Tracking/Acts/ActsGeometry/ActsGeometry/ActsExtrapolationTool.h
index e794e2c9fc55c4ed57ed5d5ea1c232cbafab7134..1b1b5e3a82b276b96bb451b7458bf3372cb8489a 100644
--- a/Tracking/Acts/ActsGeometry/ActsGeometry/ActsExtrapolationTool.h
+++ b/Tracking/Acts/ActsGeometry/ActsGeometry/ActsExtrapolationTool.h
@@ -68,8 +68,32 @@ private:
 public:
   virtual
   std::vector<Acts::detail::Step>
+  propagationSteps(const EventContext& ctx,
+                   const Acts::BoundParameters& startParameters,
+                   Acts::NavigationDirection navDir = Acts::forward,
+                   double pathLimit = std::numeric_limits<double>::max()) const override;
+                   
+  virtual
+  std::unique_ptr<const Acts::CurvilinearParameters>
+  propagate(const EventContext& ctx,
+            const Acts::BoundParameters& startParameters,
+            Acts::NavigationDirection navDir = Acts::forward,
+            double pathLimit = std::numeric_limits<double>::max()) const override;
+            
+  virtual
+  std::vector<Acts::detail::Step>
+  propagationSteps(const EventContext& ctx,
+                   const Acts::BoundParameters& startParameters,
+                   const Acts::Surface& target,
+                   Acts::NavigationDirection navDir = Acts::forward,
+                   double pathLimit = std::numeric_limits<double>::max()) const override;
+            
+  virtual
+  std::unique_ptr<const Acts::BoundParameters>
   propagate(const EventContext& ctx,
             const Acts::BoundParameters& startParameters,
+            const Acts::Surface& target,
+            Acts::NavigationDirection navDir = Acts::forward,
             double pathLimit = std::numeric_limits<double>::max()) const override;
 
   virtual
diff --git a/Tracking/Acts/ActsGeometry/CMakeLists.txt b/Tracking/Acts/ActsGeometry/CMakeLists.txt
index 44bf468ff03d9a5826419aa8d7acbe1cc793efc5..9bd53b33422c69c7f0fd27bc6a88ab12978c06e4 100755
--- a/Tracking/Acts/ActsGeometry/CMakeLists.txt
+++ b/Tracking/Acts/ActsGeometry/CMakeLists.txt
@@ -9,9 +9,9 @@ atlas_depends_on_subdirs( PUBLIC
                           DetectorDescription/Identifier
                           InnerDetector/InDetDetDescr/InDetIdentifier
                           InnerDetector/InDetDetDescr/InDetReadoutGeometry
-			  InnerDetector/InDetDetDescr/PixelReadoutGeometry
-			  InnerDetector/InDetDetDescr/SCT_ReadoutGeometry
-			  InnerDetector/InDetDetDescr/TRT_ReadoutGeometry
+                          InnerDetector/InDetDetDescr/PixelReadoutGeometry
+                          InnerDetector/InDetDetDescr/SCT_ReadoutGeometry
+                          InnerDetector/InDetDetDescr/TRT_ReadoutGeometry
                           Control/AthenaBaseComps
                           AthenaKernel
                           DetectorDescription/GeoModel/GeoModelUtilities
@@ -46,9 +46,9 @@ atlas_add_library( ActsGeometryLib
                    ActsInteropLib
                    ActsGeometryInterfacesLib
                    ActsCore
-		   PixelReadoutGeometry
-		   SCT_ReadoutGeometry
-		   TRT_ReadoutGeometry)
+                   PixelReadoutGeometry
+                   SCT_ReadoutGeometry
+                   TRT_ReadoutGeometry)
 
 atlas_add_component( ActsGeometry
                      src/ActsExtrapolationAlg.cxx
diff --git a/Tracking/Acts/ActsGeometry/python/ActsGeometryConfig.py b/Tracking/Acts/ActsGeometry/python/ActsGeometryConfig.py
index d838f1599ed485bed7a878e335ac6a3631bddabc..2a07d14ba361401689ca8c9d504f86a2ed974174 100644
--- a/Tracking/Acts/ActsGeometry/python/ActsGeometryConfig.py
+++ b/Tracking/Acts/ActsGeometry/python/ActsGeometryConfig.py
@@ -1,9 +1,61 @@
-from AthenaCommon.Logging import logging
-logging.getLogger().info("Importing %s", __name__)
+# Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator 
+from AthenaConfiguration.ComponentFactory import CompFactory
 
-from AthenaCommon.AthenaCommonFlags import athenaCommonFlags
-from AthenaCommon.GlobalFlags import GlobalFlags
-from AthenaCommon import CfgMgr
 
-def ActsTrackingGeometrySvc(name="ActsTrackingGeometrySvc", **kwargs):
-     return CfgMgr.ActsTrackingGeometrySvc(name, **kwargs)
+def ActsTrackingGeometrySvcCfg(configFlags, name = "ActsTrackingGeometrySvc" ) :
+  result = ComponentAccumulator()
+  
+  Acts_ActsTrackingGeometrySvc = CompFactory.ActsTrackingGeometrySvc
+  subDetectors = []
+  if configFlags.Detector.GeometryPixel:
+    subDetectors += ["Pixel"]
+  if configFlags.Detector.GeometrySCT:
+    subDetectors += ["SCT"]
+  if configFlags.Detector.GeometryTRT:
+    subDetectors += ["TRT"]
+  if configFlags.Detector.GeometryCalo:
+    subDetectors += ["Calo"]
+    
+  actsTrackingGeometrySvc = Acts_ActsTrackingGeometrySvc(name, BuildSubDetectors = subDetectors)
+  result.addService(actsTrackingGeometrySvc)
+  return result
+
+def ActsTrackingGeometryToolCfg(configFlags, name = "ActsTrackingGeometryTool" ) :
+  result = ComponentAccumulator()
+  
+  acc = ActsTrackingGeometrySvcCfg(configFlags)
+  result.merge(acc)
+  
+  Acts_ActsTrackingGeometryTool = CompFactory.ActsTrackingGeometryTool
+  actsTrackingGeometryTool = Acts_ActsTrackingGeometryTool(name)
+  result.addPublicTool(actsTrackingGeometryTool)
+  
+  return result, actsTrackingGeometryTool
+
+def NominalAlignmentCondAlgCfg(configFlags, name = "NominalAlignmentCondAlg", **kwargs) :
+  result = ComponentAccumulator()
+  
+  acc = ActsTrackingGeometrySvcCfg(configFlags)
+  result.merge(acc)
+  
+  Acts_NominalAlignmentCondAlg = CompFactory.NominalAlignmentCondAlg
+  nominalAlignmentCondAlg = Acts_NominalAlignmentCondAlg(name, **kwargs)
+  result.addCondAlgo(nominalAlignmentCondAlg)
+  
+  return result
+
+from MagFieldServices.MagFieldServicesConfig import MagneticFieldSvcCfg
+def ActsExtrapolationToolCfg(configFlags, name = "ActsExtrapolationTool" ) :
+  result=ComponentAccumulator()
+  
+  acc  = MagneticFieldSvcCfg(configFlags)
+  result.merge(acc)
+  
+  acc, actsTrackingGeometryTool = ActsTrackingGeometryToolCfg(configFlags) 
+  result.merge(acc)
+  
+  Acts_ActsExtrapolationTool = CompFactory.ActsExtrapolationTool
+  actsExtrapolationTool = Acts_ActsExtrapolationTool(name)
+  result.addPublicTool(actsExtrapolationTool, primary=True)
+  return result
diff --git a/Tracking/Acts/ActsGeometry/src/ActsExtrapolationAlg.cxx b/Tracking/Acts/ActsGeometry/src/ActsExtrapolationAlg.cxx
index c5804e38955135adbb3d617e931789c17490eb70..beb72522c2ef2eab451bf0d393948deca1267ee2 100755
--- a/Tracking/Acts/ActsGeometry/src/ActsExtrapolationAlg.cxx
+++ b/Tracking/Acts/ActsGeometry/src/ActsExtrapolationAlg.cxx
@@ -114,7 +114,7 @@ StatusCode ActsExtrapolationAlg::execute(const EventContext &ctx) const {
       auto anygctx = gctx.any();
       Acts::BoundParameters startParameters(
           anygctx, std::move(cov), std::move(pars), std::move(surface));
-      steps = m_extrapolationTool->propagate(ctx, startParameters);
+      steps = m_extrapolationTool->propagationSteps(ctx, startParameters);
       m_propStepWriterSvc->write(steps);
     }
 
diff --git a/Tracking/Acts/ActsGeometry/src/ActsExtrapolationTool.cxx b/Tracking/Acts/ActsGeometry/src/ActsExtrapolationTool.cxx
index 6f518b3f150622fc00a14fd5d11bcb70a741bac0..328085f7bd849af49f67b8db3faac313522e473c 100644
--- a/Tracking/Acts/ActsGeometry/src/ActsExtrapolationTool.cxx
+++ b/Tracking/Acts/ActsGeometry/src/ActsExtrapolationTool.cxx
@@ -109,9 +109,10 @@ ActsExtrapolationTool::initialize()
 
 
 std::vector<Acts::detail::Step>
-ActsExtrapolationTool::propagate(const EventContext& ctx,
-                                 const Acts::BoundParameters& startParameters,
-                                 double pathLimit /*= std::numeric_limits<double>::max()*/) const
+ActsExtrapolationTool::propagationSteps(const EventContext& ctx,
+                                        const Acts::BoundParameters& startParameters,
+                                        Acts::NavigationDirection navDir /*= Acts::forward*/,
+                                        double pathLimit /*= std::numeric_limits<double>::max()*/) const
 {
   using namespace Acts::UnitLiterals;
   ATH_MSG_VERBOSE(name() << "::" << __FUNCTION__ << " begin");
@@ -137,6 +138,7 @@ ActsExtrapolationTool::propagate(const EventContext& ctx,
     = (Acts::VectorHelpers::perp(startParameters.momentum())
        < m_ptLoopers * 1_MeV);
   options.maxStepSize = m_maxStepSize * 1_m;
+  options.direction = navDir;
 
   std::vector<Acts::detail::Step> steps;
   DebugOutput::result_type debugOutput;
@@ -170,3 +172,164 @@ ActsExtrapolationTool::propagate(const EventContext& ctx,
 
   return steps;
 }
+
+
+std::unique_ptr<const Acts::CurvilinearParameters>
+ActsExtrapolationTool::propagate(const EventContext& ctx,
+                                 const Acts::BoundParameters& startParameters,
+                                 Acts::NavigationDirection navDir /*= Acts::forward*/,
+                                 double pathLimit /*= std::numeric_limits<double>::max()*/) const
+{
+  using namespace Acts::UnitLiterals;
+  ATH_MSG_VERBOSE(name() << "::" << __FUNCTION__ << " begin");
+
+  Acts::MagneticFieldContext mctx;
+  const ActsGeometryContext& gctx
+    = m_trackingGeometryTool->getGeometryContext(ctx);
+
+  auto anygctx = gctx.any();
+
+  // Action list and abort list
+  using ActionList = Acts::ActionList<DebugOutput>;
+  using AbortConditions = Acts::AbortList<EndOfWorld>;
+  using Options = Acts::PropagatorOptions<ActionList, AbortConditions>;
+
+  Options options(anygctx, mctx);
+  options.pathLimit = pathLimit;
+  bool debug = msg().level() == MSG::VERBOSE;
+  options.debug = debug;
+
+  options.loopProtection
+    = (Acts::VectorHelpers::perp(startParameters.momentum())
+       < m_ptLoopers * 1_MeV);
+  options.maxStepSize = m_maxStepSize * 1_m;
+  options.direction = navDir;
+
+  std::vector<Acts::detail::Step> steps;
+  DebugOutput::result_type debugOutput;
+
+  auto parameters = boost::apply_visitor([&](const auto& propagator) -> std::unique_ptr<const Acts::CurvilinearParameters> {
+      auto result = propagator.propagate(startParameters, options);
+      if (!result.ok()) {
+        ATH_MSG_ERROR("Got error during propagation:" << result.error()
+        << ". Returning empty parameters.");
+        return nullptr;
+      }
+      return std::move(result.value().endParameters);
+    }, *m_varProp);
+  
+  return parameters;
+}
+            
+std::vector<Acts::detail::Step>
+ActsExtrapolationTool::propagationSteps(const EventContext& ctx,
+                                        const Acts::BoundParameters& startParameters,
+                                        const Acts::Surface& target,
+                                        Acts::NavigationDirection navDir /*= Acts::forward*/,
+                                        double pathLimit /*= std::numeric_limits<double>::max()*/) const 
+{
+  using namespace Acts::UnitLiterals;
+  ATH_MSG_VERBOSE(name() << "::" << __FUNCTION__ << " begin");
+
+  Acts::MagneticFieldContext mctx;
+  const ActsGeometryContext& gctx
+    = m_trackingGeometryTool->getGeometryContext(ctx);
+
+  auto anygctx = gctx.any();
+
+  // Action list and abort list
+  using ActionList = Acts::ActionList<SteppingLogger, DebugOutput>;
+  using AbortConditions = Acts::AbortList<EndOfWorld>;
+  using Options = Acts::PropagatorOptions<ActionList, AbortConditions>;
+
+  Options options(anygctx, mctx);
+  options.pathLimit = pathLimit;
+  bool debug = msg().level() == MSG::VERBOSE;
+  options.debug = debug;
+
+  options.loopProtection
+    = (Acts::VectorHelpers::perp(startParameters.momentum())
+       < m_ptLoopers * 1_MeV);
+  options.maxStepSize = m_maxStepSize * 1_m;
+  options.direction = navDir;
+
+  std::vector<Acts::detail::Step> steps;
+  DebugOutput::result_type debugOutput;
+
+  auto res = boost::apply_visitor([&](const auto& propagator) -> ResultType {
+      auto result = propagator.propagate(startParameters, target, options);
+      if (!result.ok()) {
+        return result.error();
+      }
+      auto& propRes = *result;
+
+      auto steppingResults = propRes.template get<SteppingLogger::result_type>();
+      auto debugOutput = propRes.template get<DebugOutput::result_type>();
+      // try to force return value optimization, not sure this is necessary
+      return std::make_pair(std::move(steppingResults.steps), std::move(debugOutput));
+    }, *m_varProp);
+
+  if (!res.ok()) {
+    ATH_MSG_ERROR("Got error during propagation:" << res.error()
+                  << ". Returning empty step vector.");
+    return {};
+  }
+  std::tie(steps, debugOutput) = std::move(*res);
+
+  if(debug) {
+    ATH_MSG_VERBOSE(debugOutput.debugString);
+  }
+
+  ATH_MSG_VERBOSE("Collected " << steps.size() << " steps");
+  ATH_MSG_VERBOSE(name() << "::" << __FUNCTION__ << " end");
+
+  return steps;  
+}
+            
+std::unique_ptr<const Acts::BoundParameters>
+ActsExtrapolationTool::propagate(const EventContext& ctx,
+                                 const Acts::BoundParameters& startParameters,
+                                 const Acts::Surface& target,
+                                 Acts::NavigationDirection navDir /*= Acts::forward*/,
+                                 double pathLimit /*= std::numeric_limits<double>::max()*/) const 
+{
+  using namespace Acts::UnitLiterals;
+  ATH_MSG_VERBOSE(name() << "::" << __FUNCTION__ << " begin");
+
+  Acts::MagneticFieldContext mctx;
+  const ActsGeometryContext& gctx
+    = m_trackingGeometryTool->getGeometryContext(ctx);
+
+  auto anygctx = gctx.any();
+
+  // Action list and abort list
+  using ActionList = Acts::ActionList<DebugOutput>;
+  using AbortConditions = Acts::AbortList<EndOfWorld>;
+  using Options = Acts::PropagatorOptions<ActionList, AbortConditions>;
+  
+  Options options(anygctx, mctx);
+  options.pathLimit = pathLimit;
+  bool debug = msg().level() == MSG::VERBOSE;
+  options.debug = debug;
+  
+  options.loopProtection
+    = (Acts::VectorHelpers::perp(startParameters.momentum())
+       < m_ptLoopers * 1_MeV);
+  options.maxStepSize = m_maxStepSize * 1_m;
+  options.direction = navDir;
+
+  std::vector<Acts::detail::Step> steps;
+  DebugOutput::result_type debugOutput;
+
+  auto parameters = boost::apply_visitor([&](const auto& propagator) -> std::unique_ptr<const Acts::BoundParameters> {
+      auto result = propagator.propagate(startParameters, target, options);
+      if (!result.ok()) {
+        ATH_MSG_ERROR("Got error during propagation: " << result.error()
+        << ". Returning empty parameters.");
+        return nullptr;
+      }
+      return std::move(result.value().endParameters);
+    }, *m_varProp);
+  
+  return parameters;  
+}
diff --git a/Tracking/Acts/ActsGeometryInterfaces/ActsGeometryInterfaces/IActsExtrapolationTool.h b/Tracking/Acts/ActsGeometryInterfaces/ActsGeometryInterfaces/IActsExtrapolationTool.h
index 7b3c790f162444e9c1670a70c428f6aeff837a67..03ecfe769983bd51d4b3327db61b98c2b92661a2 100644
--- a/Tracking/Acts/ActsGeometryInterfaces/ActsGeometryInterfaces/IActsExtrapolationTool.h
+++ b/Tracking/Acts/ActsGeometryInterfaces/ActsGeometryInterfaces/IActsExtrapolationTool.h
@@ -28,8 +28,32 @@ class IActsExtrapolationTool : virtual public IAlgTool {
 
   virtual
   std::vector<Acts::detail::Step>
+  propagationSteps(const EventContext& ctx,
+                   const Acts::BoundParameters& startParameters,
+                   Acts::NavigationDirection navDir = Acts::forward,
+                   double pathLimit = std::numeric_limits<double>::max()) const = 0;
+                   
+  virtual
+  std::unique_ptr<const Acts::CurvilinearParameters>
+  propagate(const EventContext& ctx,
+            const Acts::BoundParameters& startParameters,
+            Acts::NavigationDirection navDir = Acts::forward,
+            double pathLimit = std::numeric_limits<double>::max()) const = 0;
+            
+  virtual
+  std::vector<Acts::detail::Step>
+  propagationSteps(const EventContext& ctx,
+                   const Acts::BoundParameters& startParameters,
+                   const Acts::Surface& target,
+                   Acts::NavigationDirection navDir = Acts::forward,
+                   double pathLimit = std::numeric_limits<double>::max()) const = 0;
+            
+  virtual
+  std::unique_ptr<const Acts::BoundParameters>
   propagate(const EventContext& ctx,
             const Acts::BoundParameters& startParameters,
+            const Acts::Surface& target,
+            Acts::NavigationDirection navDir = Acts::forward,
             double pathLimit = std::numeric_limits<double>::max()) const = 0;
 
   virtual
diff --git a/Tracking/TrkExtrapolation/TrkExAlgs/CMakeLists.txt b/Tracking/TrkExtrapolation/TrkExAlgs/CMakeLists.txt
index 7b2e37026a48651565105d5234225a783e7482aa..d93a99657fb0dd0309d67258a9a549e052c5eb2d 100644
--- a/Tracking/TrkExtrapolation/TrkExAlgs/CMakeLists.txt
+++ b/Tracking/TrkExtrapolation/TrkExAlgs/CMakeLists.txt
@@ -22,18 +22,25 @@ atlas_depends_on_subdirs( PUBLIC
                           Tracking/TrkEvent/TrkEventPrimitives
                           Tracking/TrkEvent/TrkTrack
                           Tracking/TrkExtrapolation/TrkExInterfaces
-                          Tracking/TrkExtrapolation/TrkExUtils )
+                          Tracking/TrkExtrapolation/TrkExUtils
+                          ActsGeometryInterfaces
+                          ActsGeometry
+                          ActsInterop)
 
 # External dependencies:
 find_package( Eigen )
 find_package( ROOT COMPONENTS Core Tree MathCore Hist RIO pthread )
+find_package( Acts COMPONENTS Core )
+
 
 # Component(s) in the package:
 atlas_add_component( TrkExAlgs
                      src/*.cxx
                      src/components/*.cxx
                      INCLUDE_DIRS ${ROOT_INCLUDE_DIRS} ${EIGEN_INCLUDE_DIRS}
-                     LINK_LIBRARIES ${ROOT_LIBRARIES} ${EIGEN_LIBRARIES} AthenaBaseComps AthContainers GeoPrimitives EventPrimitives GaudiKernel MagFieldInterfaces TrkSurfaces TrkParameters StoreGateLib SGtests TrkGeometry TrkVolumes TrkEventPrimitives TrkTrack TrkExInterfaces TrkExUtils )
+                     LINK_LIBRARIES ${ROOT_LIBRARIES} ${EIGEN_LIBRARIES} AthenaBaseComps AthContainers GeoPrimitives EventPrimitives GaudiKernel MagFieldInterfaces TrkSurfaces TrkParameters StoreGateLib SGtests TrkGeometry TrkVolumes TrkEventPrimitives TrkTrack TrkExInterfaces TrkExUtils ActsGeometryInterfacesLib ActsInteropLib ActsGeometryLib ActsCore)
+
+atlas_install_python_modules( python/*.py )
 
 # Install files from the package:
 atlas_install_headers( TrkExAlgs )
diff --git a/Tracking/TrkExtrapolation/TrkExAlgs/TrkExAlgs/ExtrapolatorComparisonTest.h b/Tracking/TrkExtrapolation/TrkExAlgs/TrkExAlgs/ExtrapolatorComparisonTest.h
new file mode 100644
index 0000000000000000000000000000000000000000..aa969d304ab7560608f5adf3ba6dad5e0698ada4
--- /dev/null
+++ b/Tracking/TrkExtrapolation/TrkExAlgs/TrkExAlgs/ExtrapolatorComparisonTest.h
@@ -0,0 +1,130 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// ExtrapolatorComparisonTest.h, (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#ifndef TRKEXALGS_TRKEXTRAPOLATORCOMPARISONTEST_H
+#define TRKEXALGS_TRKEXTRAPOLATORCOMPARISONTEST_H
+
+// Gaudi includes
+#include "AthenaBaseComps/AthReentrantAlgorithm.h"
+#include "GaudiKernel/MsgStream.h"
+
+// ATHENA
+#include "GaudiKernel/ServiceHandle.h"
+#include "GaudiKernel/Property.h"  /*no forward decl: typedef*/
+#include "GaudiKernel/ISvcLocator.h"
+#include "GaudiKernel/EventContext.h"
+#include "GaudiKernel/RndmGenerators.h"
+#include "TrkExInterfaces/IExtrapolator.h"
+// ACTS
+#include "ActsGeometryInterfaces/IActsExtrapolationTool.h"
+#include "ActsGeometry/ActsGeometryContext.h"
+#include "TrkExAlgs/PropResultRootWriterSvc.h"
+// STL
+#include <memory>
+#include <vector>
+#include <fstream>
+#include <mutex>
+
+namespace Acts {
+  class TrackingGeometry;
+  
+  namespace detail {
+    class Step;
+  }
+}
+
+struct perigeeParameters {
+ double m_d0    ;
+ double m_z0    ;
+ double m_phi   ;
+ double m_eta   ;
+ double m_pt    ;
+ double m_charge;
+ perigeeParameters(double d0, double z0, double phi, double eta, double pt, double charge):
+ m_d0(d0), m_z0(z0), m_phi(phi), m_eta(eta), m_pt(pt), m_charge(charge) {}
+};
+
+namespace Trk 
+{
+  /** @class ExtrapolatorComparisonTest
+
+     The ExtrapolatorComparisonTest Algorithm runs a number of n test extrapolations
+     from randomly distributed Track Parameters to reference surfcas within
+    
+     - a) the Inner Detector if DetFlags.ID_On()
+     - b) the Calorimeter if DetFlags.Calo_On()
+     - c) the Muon System if DetFlags.Muon_On()
+
+     It uses and compares the output obtaining using 
+     the ATLAS Extrapolator and the ACTS Extrapolation
+
+  */  
+
+  class ExtrapolatorComparisonTest : public AthReentrantAlgorithm
+    {
+    public:
+
+       /** Standard Athena-Algorithm Constructor */
+       ExtrapolatorComparisonTest(const std::string& name, ISvcLocator* pSvcLocator);
+       /** Default Destructor */
+       ~ExtrapolatorComparisonTest();
+
+       /** standard Athena-Algorithm method */
+       StatusCode          initialize() override;
+       /** standard Athena-Algorithm method */
+       StatusCode          execute(const EventContext& ctx) const override;
+       /** standard Athena-Algorithm method */
+       StatusCode          finalize() override;
+       
+    private:
+      
+      void generatePerigee(std::vector<perigeeParameters>& parameters);
+
+      /** The ACTS ExtrapolationTool to be retrieved */
+      ToolHandle<IActsExtrapolationTool> m_extrapolationTool{this, "ExtrapolationTool", "ActsExtrapolationTool"};
+      
+      /** The ATLAS Extrapolator to be retrieved */
+      ToolHandle<Trk::IExtrapolator> m_atlasExtrapolator {this, "Extrapolator", "Trk::Extrapolator/AtlasExtrapolator"};
+
+
+      /** Random Number setup */
+      Rndm::Numbers*                    m_gaussDist;
+      Rndm::Numbers*                    m_flatDist;
+      
+      double                            m_sigmaD0;                    //!< Sigma of distribution for D0
+      double                            m_sigmaZ0;                    //!< Sigma of distribution for Z0
+      double                            m_minPhi;                     //!< Minimal phi value
+      double                            m_maxPhi;                     //!< Maximal phi value
+      double                            m_minEta;                     //!< Minimal eta value
+      double                            m_maxEta;                     //!< Maximal eta value
+      double                            m_minPt;                      //!< Minimal p value 
+      double                            m_maxPt;                      //!< Maximal p value
+                                        
+      int                               m_particleType;               //!< the particle typre for the extrap.
+
+      /** member variables for algorithm properties: */
+      unsigned int                                     m_referenceSurfaces;
+
+      std::vector<double>                              m_referenceSurfaceRadius;
+      std::vector<double>                              m_referenceSurfaceHalflength;
+      
+      std::vector<double>                              m_referenceSurfaceNegativeBoundary;
+      std::vector<double>                              m_referenceSurfacePositiveBoundary;
+      
+      std::vector< std::vector<const Trk::Surface*> >  m_atlasReferenceSurfaceTriples;
+      std::vector< std::vector< std::shared_ptr<const Acts::Surface> > > m_actsReferenceSurfaceTriples;
+      
+      int m_eventsPerExecute;
+      
+      ServiceHandle<PropResultRootWriterSvc> m_atlasPropResultWriterSvc;
+      ServiceHandle<PropResultRootWriterSvc> m_actsPropResultWriterSvc;
+      
+    }; 
+} // end of namespace
+
+#endif
diff --git a/Tracking/TrkExtrapolation/TrkExAlgs/TrkExAlgs/PropResultRootWriterSvc.h b/Tracking/TrkExtrapolation/TrkExAlgs/TrkExAlgs/PropResultRootWriterSvc.h
new file mode 100644
index 0000000000000000000000000000000000000000..edbc78a276b0c752198a7ab0148f3a813f046828
--- /dev/null
+++ b/Tracking/TrkExtrapolation/TrkExAlgs/TrkExAlgs/PropResultRootWriterSvc.h
@@ -0,0 +1,211 @@
+ 
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TRKEXALGS_PROPRESULTROOTWRITERSVC_H
+#define TRKEXALGS_PROPRESULTROOTWRITERSVC_H
+
+#include "GaudiKernel/IInterface.h"
+#include "GaudiKernel/Property.h"  /*no forward decl: typedef*/
+#include "GaudiKernel/ITHistSvc.h"
+#include "AthenaBaseComps/AthService.h"
+
+#include "TTree.h"
+
+#include <mutex>
+
+class TFile;
+
+namespace Trk {
+  
+class PropResultRootWriterSvc : public AthService {
+  public:
+    /// constructor
+    PropResultRootWriterSvc(const std::string& name, ISvcLocator* svcloc);
+    /// destructor
+    virtual ~PropResultRootWriterSvc();
+    
+    /// Retrieve interface ID
+    static const InterfaceID& interfaceID() {
+      /// Declaration of the interface ID ( interface id, major version, minor version)
+      static const InterfaceID IID_PropResultRootWriterSvc("PropResultRootWriterSvc", 1, 0);
+      return IID_PropResultRootWriterSvc;    
+    }
+    
+    virtual StatusCode queryInterface(const InterfaceID& riid, void** ppvInterface) {
+      ATH_MSG_DEBUG("in queryInterface()");    
+      if (PropResultRootWriterSvc::interfaceID().versionMatch(riid)) {
+        ATH_MSG_DEBUG("matched PropResultRootWriterSvc");
+        *ppvInterface=(PropResultRootWriterSvc*)this;
+      } else {
+        ATH_MSG_DEBUG("Default to Service interface");
+        return AthService::queryInterface(riid,ppvInterface);
+      }
+      return StatusCode::SUCCESS;
+    }
+      
+    virtual StatusCode initialize() override;
+    virtual StatusCode finalize() override;
+    
+    template <typename T>
+    void write(const T* initialPerigee, 
+               const T* fwdParameters=nullptr, double fwdtime=std::numeric_limits<float>::quiet_NaN(), 
+               const T* bkwParameters=nullptr, double bkwtime=std::numeric_limits<float>::quiet_NaN() );  
+      
+private:
+  std::mutex m_writeMutex;
+  
+  // jobOptions properties
+  ServiceHandle<ITHistSvc> m_thistSvc;
+  TTree* m_tree;
+  Gaudi::Property<std::string> m_ntupleDirName{this, "DirName", "/ExtrapolationStudies/", ""};
+  Gaudi::Property<std::string> m_treeName{this, "TreeName", "ATLAS", ""};
+
+  int m_eventNum;
+  
+  float m_start_d0              ;
+  float m_start_z0              ;
+  float m_start_phi             ;
+  float m_start_theta           ;
+  float m_start_qop             ;
+                                
+  float m_fwd_success           ;
+  float m_fwd_time              ;
+  float m_fwd_final_l0          ;
+  float m_fwd_final_l1          ;
+  float m_fwd_final_x           ;
+  float m_fwd_final_y           ;
+  float m_fwd_final_z           ;
+  float m_fwd_final_phi         ;
+  float m_fwd_final_theta       ;
+  float m_fwd_final_qop         ;
+  float m_fwd_final_sigma_l0    ;
+  float m_fwd_final_sigma_l1    ;
+  float m_fwd_final_sigma_phi   ;
+  float m_fwd_final_sigma_theta ;
+  float m_fwd_final_sigma_qop   ;
+                                
+  float m_bkw_success           ;
+  float m_bkw_time              ;
+  float m_bkw_final_d0          ;
+  float m_bkw_final_z0          ;
+  float m_bkw_final_phi         ;
+  float m_bkw_final_theta       ;
+  float m_bkw_final_qop         ;
+  float m_bkw_final_sigma_d0    ;
+  float m_bkw_final_sigma_z0    ;
+  float m_bkw_final_sigma_phi   ;
+  float m_bkw_final_sigma_theta ;
+  float m_bkw_final_sigma_qop   ;
+  
+  };
+  
+  template <typename  T>
+  void PropResultRootWriterSvc::write(const T* initialPerigee, 
+                                      const T* fwdParameters, double fwdtime, 
+                                      const T* bkwParameters, double bkwtime ) {
+  
+    auto ctx = Gaudi::Hive::currentContext();
+  
+    m_eventNum = ctx.eventID().event_number();
+    
+    if (initialPerigee) {
+      m_start_d0   = initialPerigee->parameters()[0];
+      m_start_z0   = initialPerigee->parameters()[1];
+      m_start_phi  = initialPerigee->parameters()[2];
+      m_start_theta= initialPerigee->parameters()[3];
+      m_start_qop  = initialPerigee->parameters()[4];
+    } else {
+      m_start_d0   = std::numeric_limits<float>::quiet_NaN();
+      m_start_z0   = std::numeric_limits<float>::quiet_NaN();
+      m_start_phi  = std::numeric_limits<float>::quiet_NaN();
+      m_start_theta= std::numeric_limits<float>::quiet_NaN();
+      m_start_qop  = std::numeric_limits<float>::quiet_NaN();
+    }
+
+    if (fwdParameters) {
+      m_fwd_success     = 1;   
+      m_fwd_time        = fwdtime;
+      m_fwd_final_l0    = fwdParameters->parameters()[0];
+      m_fwd_final_l1    = fwdParameters->parameters()[1];
+      m_fwd_final_phi   = fwdParameters->parameters()[2];
+      m_fwd_final_theta = fwdParameters->parameters()[3];
+      m_fwd_final_qop   = fwdParameters->parameters()[4];
+      m_fwd_final_x     = fwdParameters->position()[0];
+      m_fwd_final_y     = fwdParameters->position()[1];
+      m_fwd_final_z     = fwdParameters->position()[2];
+      if (fwdParameters->covariance()) {
+        m_fwd_final_sigma_l0    = (*fwdParameters->covariance())(0,0);
+        m_fwd_final_sigma_l1    = (*fwdParameters->covariance())(1,1);
+        m_fwd_final_sigma_phi   = (*fwdParameters->covariance())(2,2);
+        m_fwd_final_sigma_theta = (*fwdParameters->covariance())(3,3);
+        m_fwd_final_sigma_qop   = (*fwdParameters->covariance())(4,4);
+      } else {        
+        m_fwd_final_sigma_l0    = std::numeric_limits<float>::quiet_NaN();
+        m_fwd_final_sigma_l1    = std::numeric_limits<float>::quiet_NaN();
+        m_fwd_final_sigma_phi   = std::numeric_limits<float>::quiet_NaN();
+        m_fwd_final_sigma_theta = std::numeric_limits<float>::quiet_NaN();
+        m_fwd_final_sigma_qop   = std::numeric_limits<float>::quiet_NaN();
+      }
+    } else {
+      m_fwd_success           = std::numeric_limits<float>::quiet_NaN();
+      m_fwd_time              = std::numeric_limits<float>::quiet_NaN();
+      m_fwd_final_l0          = std::numeric_limits<float>::quiet_NaN();
+      m_fwd_final_l1          = std::numeric_limits<float>::quiet_NaN();
+      m_fwd_final_phi         = std::numeric_limits<float>::quiet_NaN();
+      m_fwd_final_theta       = std::numeric_limits<float>::quiet_NaN();
+      m_fwd_final_qop         = std::numeric_limits<float>::quiet_NaN();
+      m_fwd_final_x           = std::numeric_limits<float>::quiet_NaN();
+      m_fwd_final_y           = std::numeric_limits<float>::quiet_NaN();
+      m_fwd_final_z           = std::numeric_limits<float>::quiet_NaN();
+      m_fwd_final_sigma_l0    = std::numeric_limits<float>::quiet_NaN();
+      m_fwd_final_sigma_l1    = std::numeric_limits<float>::quiet_NaN();
+      m_fwd_final_sigma_phi   = std::numeric_limits<float>::quiet_NaN();
+      m_fwd_final_sigma_theta = std::numeric_limits<float>::quiet_NaN();
+      m_fwd_final_sigma_qop   = std::numeric_limits<float>::quiet_NaN();
+    }
+    
+    if (bkwParameters) {
+      m_bkw_success     = 1;   
+      m_bkw_time        = bkwtime;
+      m_bkw_final_d0    = bkwParameters->parameters()[0];
+      m_bkw_final_z0    = bkwParameters->parameters()[1];
+      m_bkw_final_phi   = bkwParameters->parameters()[2];
+      m_bkw_final_theta = bkwParameters->parameters()[3];
+      m_bkw_final_qop   = bkwParameters->parameters()[4];
+      if (bkwParameters->covariance()) {
+        m_bkw_final_sigma_d0    = (*bkwParameters->covariance())(0,0);
+        m_bkw_final_sigma_z0    = (*bkwParameters->covariance())(1,1);
+        m_bkw_final_sigma_phi   = (*bkwParameters->covariance())(2,2);
+        m_bkw_final_sigma_theta = (*bkwParameters->covariance())(3,3);
+        m_bkw_final_sigma_qop   = (*bkwParameters->covariance())(4,4);
+      } else {        
+        m_bkw_final_sigma_d0    = std::numeric_limits<float>::quiet_NaN();
+        m_bkw_final_sigma_z0    = std::numeric_limits<float>::quiet_NaN();
+        m_bkw_final_sigma_phi   = std::numeric_limits<float>::quiet_NaN();
+        m_bkw_final_sigma_theta = std::numeric_limits<float>::quiet_NaN();
+        m_bkw_final_sigma_qop   = std::numeric_limits<float>::quiet_NaN();
+      }
+    } else {
+      m_bkw_success            = std::numeric_limits<float>::quiet_NaN();
+      m_bkw_time               = std::numeric_limits<float>::quiet_NaN();
+      m_bkw_final_d0           = std::numeric_limits<float>::quiet_NaN();
+      m_bkw_final_z0           = std::numeric_limits<float>::quiet_NaN();
+      m_bkw_final_phi          = std::numeric_limits<float>::quiet_NaN();
+      m_bkw_final_theta        = std::numeric_limits<float>::quiet_NaN();
+      m_bkw_final_qop          = std::numeric_limits<float>::quiet_NaN();
+      m_bkw_final_sigma_d0     = std::numeric_limits<float>::quiet_NaN();
+      m_bkw_final_sigma_z0     = std::numeric_limits<float>::quiet_NaN();
+      m_bkw_final_sigma_phi    = std::numeric_limits<float>::quiet_NaN();
+      m_bkw_final_sigma_theta  = std::numeric_limits<float>::quiet_NaN();
+      m_bkw_final_sigma_qop    = std::numeric_limits<float>::quiet_NaN();
+    }
+    m_tree->Fill();
+  }
+  
+  
+
+}
+
+#endif 
diff --git a/Tracking/TrkExtrapolation/TrkExAlgs/python/TrkExAlgsConfig.py b/Tracking/TrkExtrapolation/TrkExAlgs/python/TrkExAlgsConfig.py
new file mode 100644
index 0000000000000000000000000000000000000000..390f038c8eb32d9d404c90dd3136befdaa6012c1
--- /dev/null
+++ b/Tracking/TrkExtrapolation/TrkExAlgs/python/TrkExAlgsConfig.py
@@ -0,0 +1,123 @@
+# Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator 
+from AthenaConfiguration.ComponentFactory import CompFactory
+
+from ActsGeometry.ActsGeometryConfig import ActsExtrapolationToolCfg
+from ActsGeometry.ActsGeometryConfig import NominalAlignmentCondAlgCfg
+from TrkConfig.AtlasExtrapolatorConfig import AtlasExtrapolatorCfg
+
+def PropResultRootWriterSvcCfg(configFlags, name="PropResultRootWriterSvc", **kwargs) :
+  result = ComponentAccumulator()
+
+  Trk__PropResultRootWriterSvc = CompFactory.Trk.PropResultRootWriterSvc
+  propResultRootWriterSvc = Trk__PropResultRootWriterSvc(name, **kwargs)
+  result.addService(propResultRootWriterSvc)
+  
+  return result, propResultRootWriterSvc
+
+
+def ExtrapolatorComparisonTestCfg(configFlags, name = "ExtrapolatorComparisonTest", **kwargs ) :
+  result=ComponentAccumulator()  
+  
+  if "Extrapolator" not in kwargs:
+    kwargs["Extrapolator"] = result.popToolsAndMerge(AtlasExtrapolatorCfg(configFlags, 'AtlasExtrapolator'))
+  
+  if "ExtrapolationTool" not in kwargs:
+    actsextrapolation = ActsExtrapolationToolCfg(configFlags)
+    kwargs["ExtrapolationTool"] = actsextrapolation.getPrimary()
+    result.merge(actsextrapolation)
+  
+  Trk__ExtrapolatorComparisonTest = CompFactory.Trk.ExtrapolatorComparisonTest
+  extrapolationTest = Trk__ExtrapolatorComparisonTest(name, **kwargs)
+  result.addEventAlgo(extrapolationTest)
+  
+  return result
+
+if __name__=="__main__":
+    from AthenaCommon.Configurable import Configurable
+    from AthenaCommon.Logging import log
+    from AthenaCommon.Constants import VERBOSE
+    from AthenaConfiguration.AllConfigFlags import ConfigFlags
+    from AthenaConfiguration.MainServicesConfig import MainServicesThreadedCfg    
+    
+    #log.setLevel(VERBOSE)
+    
+    Configurable.configurableRun3Behavior = True
+    
+    ## Just enable ID for the moment.
+    ConfigFlags.Input.isMC             = True
+    ConfigFlags.Beam.Type = ''
+    ConfigFlags.GeoModel.AtlasVersion  = "ATLAS-R2-2016-01-00-01"
+    ConfigFlags.IOVDb.GlobalTag        = "OFLCOND-SIM-00-00-00"
+    ConfigFlags.Detector.SimulateBpipe = True
+    ConfigFlags.Detector.SimulateID    = True    
+    ConfigFlags.Detector.GeometryBpipe = True
+    ConfigFlags.Detector.GeometryID    = True
+    ConfigFlags.Detector.GeometryPixel = True
+    ConfigFlags.Detector.GeometrySCT   = True
+    ConfigFlags.Detector.GeometryCalo  = False
+    ConfigFlags.Detector.GeometryMuon  = False
+    #ConfigFlags.Detector.GeometryTRT   = True
+    ConfigFlags.TrackingGeometry.MaterialSource = "Input"
+    
+    # This should run serially for the moment.
+    ConfigFlags.Concurrency.NumThreads = 1
+    ConfigFlags.Concurrency.NumConcurrentEvents = 1
+    
+    log.debug('Lock config flags now.')
+    ConfigFlags.lock()
+    
+    ConfigFlags.dump()
+
+    cfg=MainServicesThreadedCfg(ConfigFlags)
+
+    from AtlasGeoModel.InDetGMConfig import InDetGeometryCfg     
+    cfg.merge(InDetGeometryCfg(ConfigFlags))
+    
+    from BeamPipeGeoModel.BeamPipeGMConfig import BeamPipeGeometryCfg
+    cfg.merge(BeamPipeGeometryCfg(ConfigFlags))
+    
+    nominalAlignmentCondAlg = NominalAlignmentCondAlgCfg(ConfigFlags, OutputLevel=VERBOSE)
+    cfg.merge(nominalAlignmentCondAlg)
+    
+    histSvc = CompFactory.THistSvc(Output = ["ExtrapolationStudies DATAFILE='ExtrapolationStudies.root' OPT='RECREATE'"])
+    histSvc.OutputLevel=VERBOSE
+    cfg.addService( histSvc )
+    
+    accAtlasPropResult, atlasPropResultRootWriterSvc = PropResultRootWriterSvcCfg(ConfigFlags, 
+                                                                                  name="ATLASPropResultRootWriterSvc",
+                                                                                  TreeName="ATLAS")
+    cfg.merge(accAtlasPropResult)
+  
+    accActsPropResult, actsPropResultRootWriterSvc = PropResultRootWriterSvcCfg(ConfigFlags, 
+                                                                                name="ACTSPropResultRootWriterSvc",
+                                                                                TreeName="ACTS")
+    cfg.merge(accActsPropResult)
+    
+    topoAcc=ExtrapolatorComparisonTestCfg(ConfigFlags,
+                                          EventsPerExecute = 1000,
+                                          StartPerigeeMinPt   = 10000,
+                                          StartPerigeeMaxPt   = 10000,
+                                          ReferenceSurfaceRadius = [80],
+                                          ReferenceSurfaceHalfZ  = [500],
+                                          ATLASPropResultRootWriter = atlasPropResultRootWriterSvc, 
+                                          ACTSPropResultRootWriter = actsPropResultRootWriterSvc)
+    cfg.merge(topoAcc)
+    
+    cfg.printConfig()
+    
+    #cfg.getPublicTool("InDetLayerArrayCreator").OutputLevel=VERBOSE
+    #cfg.getPublicTool("InDetTrackingVolumeArrayCreator").OutputLevel=VERBOSE
+    #cfg.getPublicTool("InDetCylinderVolumeCreator").OutputLevel=VERBOSE
+    cfg.getPublicTool("InDetCylinderVolumeCreator").LayerArrayCreator=cfg.getPublicTool("InDetLayerArrayCreator")
+    #cfg.getPublicTool("InDetTrackingGeometryBuilder").OutputLevel=VERBOSE
+    #cfg.getService("AtlasTrackingGeometrySvc").OutputLevel=VERBOSE
+    
+    ## Building TRT straws
+    #cfg.getPublicTool("InDetTrackingGeometryBuilder").LayerBinningType = [2, 2, 2]
+    #cfg.getPublicTool("TRT_LayerBuilder").ModelLayersOnly = False    
+
+    cfg.run(10)
+    f=open("ExtrapolatorComparisonTestConfig.pkl","w")
+    cfg.store(f)
+    f.close()
diff --git a/Tracking/TrkExtrapolation/TrkExAlgs/src/ExtrapolatorComparisonTest.cxx b/Tracking/TrkExtrapolation/TrkExAlgs/src/ExtrapolatorComparisonTest.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..692a3da6dbe6ba8ccdfcdd2649bcb0e0d301bed6
--- /dev/null
+++ b/Tracking/TrkExtrapolation/TrkExAlgs/src/ExtrapolatorComparisonTest.cxx
@@ -0,0 +1,358 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// ExtrapolatorComparisonTest.cxx, (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#include "TrkExAlgs/ExtrapolatorComparisonTest.h"
+
+// Tracking
+#include "TrkSurfaces/PerigeeSurface.h"
+#include "TrkSurfaces/CylinderSurface.h"
+#include "TrkSurfaces/DiscSurface.h"
+#include "TrkEventPrimitives/ParticleHypothesis.h"
+#include "TrkParametersBase/ParametersT.h"
+#include "EventPrimitives/EventPrimitives.h"
+#include "MagFieldInterfaces/IMagFieldSvc.h"
+
+#include "GaudiKernel/SystemOfUnits.h"
+#include "GaudiKernel/ISvcLocator.h"
+#include "AthenaKernel/RNGWrapper.h"
+
+// ACTS
+#include "Acts/EventData/TrackParameters.hpp"
+#include "Acts/Surfaces/Surface.hpp"
+#include "Acts/Surfaces/PerigeeSurface.hpp"
+#include "Acts/Surfaces/DiscSurface.hpp"
+#include "Acts/Surfaces/CylinderSurface.hpp"
+#include "Acts/Utilities/Helpers.hpp"
+#include "Acts/Utilities/Logger.hpp"
+#include "ActsInterop/Logger.h"
+#include "Acts/Propagator/detail/SteppingLogger.hpp"
+#include "ActsGeometry/ActsGeometryContext.h"
+#include "ActsGeometryInterfaces/IActsTrackingGeometryTool.h"
+#include "Acts/Geometry/GeometryContext.hpp"
+#include "Acts/Utilities/Definitions.hpp"
+#include "Acts/Utilities/ParameterDefinitions.hpp"
+#include "Acts/Propagator/detail/SteppingLogger.hpp"
+
+// OTHER
+#include "CLHEP/Random/RandomEngine.h"
+
+// STL
+#include <string>
+#include <fstream>
+#include <chrono>
+#include <cmath>
+
+using xclock = std::chrono::steady_clock;
+
+//================ Constructor =================================================
+
+Trk::ExtrapolatorComparisonTest::ExtrapolatorComparisonTest(const std::string& name, ISvcLocator* pSvcLocator)
+  :
+  AthReentrantAlgorithm(name,pSvcLocator),
+  m_gaussDist(0),
+  m_flatDist(0),
+  m_sigmaD0(17.*Gaudi::Units::micrometer),                   
+  m_sigmaZ0(50.*Gaudi::Units::millimeter),
+  m_minPhi(-M_PI),                    
+  m_maxPhi(M_PI),                    
+  m_minEta(-3.),                    
+  m_maxEta(3.),                    
+  m_minPt(0.5*Gaudi::Units::GeV),                      
+  m_maxPt(50000.*Gaudi::Units::GeV),
+  m_particleType(2),
+  m_referenceSurfaces(0),
+  m_eventsPerExecute(1),
+  m_atlasPropResultWriterSvc("ATLASPropResultRootWriterSvc", name),
+  m_actsPropResultWriterSvc("ACTSPropResultRootWriterSvc", name)
+{
+  // algorithm steering
+  declareProperty("StartPerigeeSigmaD0"       , m_sigmaD0                   );
+  declareProperty("StartPerigeeSigmaZ0"       , m_sigmaZ0                   );
+  declareProperty("StartPerigeeMinPhi"        , m_minPhi                    );
+  declareProperty("StartPerigeeMaxPhi"        , m_maxPhi                    );
+  declareProperty("StartPerigeeMinEta"        , m_minEta                    );
+  declareProperty("StartPerigeeMaxEta"        , m_maxEta                    );
+  declareProperty("StartPerigeeMinPt"         , m_minPt                     );
+  declareProperty("StartPerigeeMaxPt"         , m_maxPt                     );
+  declareProperty("ParticleType"              , m_particleType              );
+  declareProperty("ReferenceSurfaceRadius"    , m_referenceSurfaceRadius    );
+  declareProperty("ReferenceSurfaceHalfZ"     , m_referenceSurfaceHalflength);
+  declareProperty("EventsPerExecute"          , m_eventsPerExecute          );
+  declareProperty("ATLASPropResultRootWriter" , m_atlasPropResultWriterSvc  );
+  declareProperty("ACTSPropResultRootWriter"  , m_actsPropResultWriterSvc   );
+}
+
+//================ Destructor =================================================
+
+Trk::ExtrapolatorComparisonTest::~ExtrapolatorComparisonTest()
+{
+  delete m_gaussDist;
+  delete m_flatDist;
+  
+  // cleanup of the Trk::Surfaces
+  std::vector< std::vector< const Trk::Surface* > >::const_iterator atlasSurfaceTripleIter    = m_atlasReferenceSurfaceTriples.begin();
+  std::vector< std::vector< const Trk::Surface* > >::const_iterator atlasSurfaceTripleIterEnd = m_atlasReferenceSurfaceTriples.end();
+  for ( ; atlasSurfaceTripleIter != atlasSurfaceTripleIterEnd; ++atlasSurfaceTripleIter) {
+    std::vector<const Trk::Surface*>::const_iterator surfIter = (*atlasSurfaceTripleIter).begin();
+    std::vector<const Trk::Surface*>::const_iterator surfIterEnd = (*atlasSurfaceTripleIter).end();
+    for ( ; surfIter != surfIterEnd; delete (*surfIter), ++surfIter);
+  }    
+}
+
+
+//================ Initialisation =================================================
+
+StatusCode Trk::ExtrapolatorComparisonTest::initialize()
+{
+  // Code entered here will be executed once at program start.
+  
+  ATH_MSG_INFO(" initialize()");
+  
+  ATH_CHECK( m_extrapolationTool.retrieve() );
+  ATH_CHECK( m_atlasExtrapolator.retrieve() );
+
+  // Create the destination surfaces for extrapolation
+  // --> you need the Trk::Surfaces and the Acts::Surfaces
+  if (m_referenceSurfaceRadius.size() == m_referenceSurfaceHalflength.size()) {
+     // assign the size
+     m_referenceSurfaces = m_referenceSurfaceRadius.size();
+     // loop over it and create the 
+     for (unsigned int surface = 0; surface < m_referenceSurfaces; surface++) {
+       
+       double radius = m_referenceSurfaceRadius.at(surface);
+       double halfZ  = m_referenceSurfaceHalflength.at(surface);
+       
+       // create the Surface triplet
+       std::vector< const Trk::Surface*> trkSurfaceTriplet;
+       trkSurfaceTriplet.push_back(new Trk::DiscSurface    (new Amg::Transform3D(Amg::Translation3D(0.,0., halfZ)),    0.,radius));
+       trkSurfaceTriplet.push_back(new Trk::CylinderSurface(new Amg::Transform3D(Amg::Translation3D(0.,0.,    0.)),radius, halfZ));
+       trkSurfaceTriplet.push_back(new Trk::DiscSurface    (new Amg::Transform3D(Amg::Translation3D(0.,0.,-halfZ)),    0.,radius));
+       ATH_MSG_INFO("Creating Trk::Surface at: R " << radius << " Z " << halfZ);
+       m_atlasReferenceSurfaceTriples.push_back(trkSurfaceTriplet);
+       
+       // create the Surface triplet
+       std::vector<std::shared_ptr<const Acts::Surface>> actsSurfaceTriplet;
+       
+       const Acts::Transform3D * posTransf = new Acts::Transform3D(Acts::Transform3D::Identity()*Acts::Translation3D(Acts::Vector3D(0.,0., halfZ)));
+       const Acts::Transform3D *   cTransf = new Acts::Transform3D(Acts::Transform3D::Identity()*Acts::Translation3D(Acts::Vector3D(0.,0.,    0.)));
+       const Acts::Transform3D * negTransf = new Acts::Transform3D(Acts::Transform3D::Identity()*Acts::Translation3D(Acts::Vector3D(0.,0.,-halfZ)));
+       
+       auto posSurface = Acts::Surface::makeShared<Acts::DiscSurface>    (std::shared_ptr<const Acts::Transform3D>(posTransf),    0.,radius);
+       auto cSurface   = Acts::Surface::makeShared<Acts::CylinderSurface>(std::shared_ptr<const Acts::Transform3D>(  cTransf),radius, halfZ);
+       auto negSurface = Acts::Surface::makeShared<Acts::DiscSurface>    (std::shared_ptr<const Acts::Transform3D>(negTransf),    0.,radius);
+       
+       actsSurfaceTriplet.push_back(posSurface);
+       actsSurfaceTriplet.push_back(cSurface  );
+       actsSurfaceTriplet.push_back(negSurface);
+       ATH_MSG_INFO("Creating Acts::Surface at: R " << radius << " Z " << halfZ);
+       m_actsReferenceSurfaceTriples.push_back(actsSurfaceTriplet);
+       
+       m_referenceSurfaceNegativeBoundary.push_back(atan2(radius,-halfZ));
+       m_referenceSurfacePositiveBoundary.push_back(atan2(radius, halfZ));
+     }
+  } else { 
+    ATH_MSG_WARNING("Not compatible size of ReferenceSurfaceRadius and ReferenceSurfaceHalfZ!! Returning FAILURE!");
+    return StatusCode::FAILURE;
+  }
+
+  m_gaussDist = new Rndm::Numbers(randSvc(), Rndm::Gauss(0.,1.));
+  m_flatDist  = new Rndm::Numbers(randSvc(), Rndm::Flat(0.,1.));
+  
+  ATH_CHECK( m_atlasPropResultWriterSvc.retrieve() );
+  ATH_CHECK( m_actsPropResultWriterSvc.retrieve() );
+  
+  ATH_MSG_INFO("initialize() successful!!");
+
+  return StatusCode::SUCCESS;
+}
+
+//================ Finalisation =================================================
+
+StatusCode Trk::ExtrapolatorComparisonTest::finalize()
+{
+  // Code entered here will be executed once at the end of the program run.
+  return StatusCode::SUCCESS;
+}
+
+//================ Execution ====================================================
+
+StatusCode Trk::ExtrapolatorComparisonTest::execute(const EventContext& ctx) const {
+  
+  float milliseconds_to_seconds = 1000.;
+  
+  // generate perigees with random number generator 
+  
+  std::vector<perigeeParameters> parameters = {};
+  for (int ext = 0; ext<m_eventsPerExecute; ext++) {
+    // generate with random number generator
+    double d0 = m_gaussDist->shoot() * m_sigmaD0;
+    double z0 = m_gaussDist->shoot() * m_sigmaZ0;
+    double phi = m_minPhi + (m_maxPhi-m_minPhi)* m_flatDist->shoot();
+    double eta = m_minEta + m_flatDist->shoot()*(m_maxEta-m_minEta);
+    double pt = m_minPt + m_flatDist->shoot()*(m_maxPt-m_minPt);
+    double charge = (m_flatDist->shoot() > 0.5 ) ? -1. : 1.;
+    parameters.push_back(perigeeParameters(d0, z0, phi, eta, pt, charge));
+  }
+  
+  int n_extraps = 0;  
+  auto start = xclock::now();
+  for (auto& perigee : parameters) {
+    
+    Acts::Vector3D momentum(perigee.m_pt * std::cos(perigee.m_phi), perigee.m_pt * std::sin(perigee.m_phi), perigee.m_pt * std::sinh(perigee.m_eta));
+    double theta = Acts::VectorHelpers::theta(momentum);
+    double qOverP = perigee.m_charge / momentum.norm();
+    
+    const Trk::PerigeeSurface atlPerigeeSurface;
+    const Trk::Perigee * atlPerigee = new const Trk::Perigee(perigee.m_d0, perigee.m_z0, perigee.m_phi, theta, qOverP, atlPerigeeSurface);
+    
+    for (unsigned int surface = 0; surface < m_atlasReferenceSurfaceTriples.size(); surface++) {
+      n_extraps++;
+
+      double negRef = m_referenceSurfaceNegativeBoundary.at(surface);
+      double posRef = m_referenceSurfacePositiveBoundary.at(surface);
+    
+      // decide which reference surface to take
+      int refSurface = theta < posRef ? 2 : 1;
+      refSurface     = theta > negRef ? 0 : 1;
+      
+      const Trk::Surface* destinationSurface = m_atlasReferenceSurfaceTriples.at(surface).at(refSurface);
+      
+      ATH_MSG_VERBOSE("Starting extrapolation " << n_extraps << " from : "       << *atlPerigee << " to : " << *destinationSurface);
+      
+      auto start_fwd = xclock::now();
+      const Trk::TrackParameters* destParameters = m_atlasExtrapolator->extrapolate(*atlPerigee,
+                                                                                    *destinationSurface, 
+                                                                                    Trk::alongMomentum,
+                                                                                    true,
+                                                                                    (Trk::ParticleHypothesis)m_particleType);
+      auto end_fwd = xclock::now();
+      float ms_fwd = std::chrono::duration_cast<std::chrono::milliseconds>(end_fwd-start_fwd).count();
+      
+      if (destParameters) {
+        ATH_MSG_VERBOSE(" ATLAS Extrapolator succeded!! --> Forward" );           
+        ATH_MSG_VERBOSE(" [ intersection ] with surface at (x,y,z) = " << destParameters->position().x() << ", " << destParameters->position().y() << ", " << destParameters->position().z() );   
+        ATH_MSG_VERBOSE(" [ intersection ] parameters: " << destParameters->parameters() );   
+        ATH_MSG_VERBOSE(" [ intersection ] cov matrix: " << destParameters->covariance() );
+        
+        // now try backward extrapolation
+        auto start_bkw = xclock::now();
+        const Trk::TrackParameters* finalperigee = m_atlasExtrapolator->extrapolate(*destParameters,
+                                                                                    atlPerigee->associatedSurface(), 
+                                                                                    Trk::oppositeMomentum,
+                                                                                    true,
+                                                                                    (Trk::ParticleHypothesis)m_particleType);
+        auto end_bkw = xclock::now();
+        float ms_bkw = std::chrono::duration_cast<std::chrono::milliseconds>(end_bkw-start_bkw).count();
+        
+         if (finalperigee) {
+           ATH_MSG_VERBOSE(" ATLAS Extrapolator succeded!! --> Backward" );           
+           ATH_MSG_VERBOSE(" [extrapolation to perigee]      input: " << atlPerigee->parameters() );   
+           ATH_MSG_VERBOSE(" [extrapolation to perigee]     output: " << finalperigee->parameters() );   
+           ATH_MSG_VERBOSE(" [extrapolation to perigee] cov matrix: " << finalperigee->covariance() );
+           
+         } else if (!finalperigee) {
+           ATH_MSG_DEBUG(" ATLAS Extrapolation to perigee failed for input parameters: " << destParameters->parameters());
+         }
+         
+         m_atlasPropResultWriterSvc->write<Trk::TrackParameters>(atlPerigee, destParameters, ms_fwd, finalperigee, ms_bkw);
+         delete finalperigee;
+      } else if (!destParameters) {
+        ATH_MSG_DEBUG(" ATLAS Extrapolation not successful! " );
+        m_atlasPropResultWriterSvc->write<Trk::TrackParameters>(atlPerigee);
+      }
+      delete destParameters;
+    }    
+    delete atlPerigee;
+  }
+  auto end = xclock::now();   
+  auto secs = std::chrono::duration_cast<std::chrono::milliseconds>(end-start).count() / milliseconds_to_seconds;
+  double secs_per_ex = secs / n_extraps;
+  
+  ATH_MSG_INFO("ATLAS : Time for " << n_extraps << " iterations: " << secs << "s (" << secs_per_ex << "s per extrapolation)");
+  
+  n_extraps = 0;  
+  start = xclock::now();
+  for (auto& perigee : parameters) {
+    Acts::Vector3D momentum(perigee.m_pt * std::cos(perigee.m_phi), perigee.m_pt * std::sin(perigee.m_phi), perigee.m_pt * std::sinh(perigee.m_eta));
+    double theta = Acts::VectorHelpers::theta(momentum);
+    double qOverP = perigee.m_charge / momentum.norm();
+    
+    std::shared_ptr<Acts::PerigeeSurface> actsPerigeeSurface = Acts::Surface::makeShared<Acts::PerigeeSurface>(Acts::Vector3D(0, 0, 0));
+    double t = 0.;
+    Acts::BoundVector pars;
+    pars << perigee.m_d0, perigee.m_z0, perigee.m_phi, theta, qOverP, t;
+    std::optional<Acts::BoundSymMatrix> cov = std::nullopt;
+    
+    // Perigee, no alignment -> default geo context
+    ActsGeometryContext gctx = m_extrapolationTool->trackingGeometryTool()->getNominalGeometryContext();
+    auto anygctx = gctx.any();
+    const Acts::BoundParameters* startParameters = new const Acts::BoundParameters(anygctx, std::move(cov), std::move(pars), std::move(actsPerigeeSurface));
+    
+    for (unsigned int surface = 0; surface < m_actsReferenceSurfaceTriples.size(); surface++) {
+      n_extraps++;
+      
+      double negRef = m_referenceSurfaceNegativeBoundary.at(surface);
+      double posRef = m_referenceSurfacePositiveBoundary.at(surface);
+    
+      // decide which reference surface to take
+      int refSurface = theta < posRef ? 2 : 1;
+      refSurface     = theta > negRef ? 0 : 1;
+      
+      auto destinationSurface = m_actsReferenceSurfaceTriples.at(surface).at(refSurface);
+      
+     ATH_MSG_VERBOSE("Starting extrapolation " << n_extraps << " from : "       << pars << " to : " << destinationSurface);
+      
+      auto start_fwd = xclock::now();
+      auto destParameters = m_extrapolationTool->propagate(ctx, *startParameters, *destinationSurface, Acts::forward);
+      auto end_fwd = xclock::now();
+      float ms_fwd = std::chrono::duration_cast<std::chrono::milliseconds>(end_fwd-start_fwd).count();
+      
+      if (destParameters) {
+        ATH_MSG_VERBOSE(" ACTS Extrapolator succeded!! --> Forward" );           
+        ATH_MSG_VERBOSE(" [ intersection ] with surface at (x,y,z) = " << destParameters->position().x() << ", " << destParameters->position().y() << ", " << destParameters->position().z() );   
+        ATH_MSG_VERBOSE(" [ intersection ] parameters: " << destParameters->parameters() );   
+        ATH_MSG_VERBOSE(" [ intersection ] cov matrix: " << *destParameters->covariance() );
+        
+        // now try backward extrapolation
+        auto start_bkw = xclock::now();
+        auto finalperigee = m_extrapolationTool->propagate(ctx, *destParameters, startParameters->referenceSurface(), Acts::backward);
+        auto end_bkw = xclock::now();
+        float ms_bkw = std::chrono::duration_cast<std::chrono::milliseconds>(end_bkw-start_bkw).count();
+        
+        if (finalperigee) {
+           ATH_MSG_VERBOSE(" ACTS Extrapolator succeded!! --> Backward" );           
+           ATH_MSG_VERBOSE(" [extrapolation to perigee]      input: " << startParameters->parameters() );   
+           ATH_MSG_VERBOSE(" [extrapolation to perigee]     output: " << finalperigee->parameters() );   
+           ATH_MSG_VERBOSE(" [extrapolation to perigee] cov matrix: " << *finalperigee->covariance() );
+           
+         } else if (!finalperigee) {
+           ATH_MSG_DEBUG(" ACTS Extrapolation to perigee failed for input parameters: " << destParameters->parameters());
+         }
+         
+         m_actsPropResultWriterSvc->write<Acts::BoundParameters>(startParameters, destParameters.release(), ms_fwd, finalperigee.release(), ms_bkw);
+      } else if (!destParameters) {
+        ATH_MSG_DEBUG(" ACTS Extrapolation not successful! " );
+        m_actsPropResultWriterSvc->write<Acts::BoundParameters>(startParameters);
+      }
+    }
+    delete startParameters;
+  }
+  
+  end = xclock::now();   
+  secs = std::chrono::duration_cast<std::chrono::milliseconds>(end-start).count() / milliseconds_to_seconds;
+  secs_per_ex = secs / n_extraps;
+  
+  ATH_MSG_INFO("ACTS : Time for " << n_extraps << " iterations: " << secs << "s (" << secs_per_ex << "s per extrapolation)");
+  
+  return StatusCode::SUCCESS;
+}
+
+//============================================================================================
+
+
+ 
diff --git a/Tracking/TrkExtrapolation/TrkExAlgs/src/PropResultRootWriterSvc.cxx b/Tracking/TrkExtrapolation/TrkExAlgs/src/PropResultRootWriterSvc.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..a9905d4a8f90cac4332ec40dbd4d8bdad4f67b3b
--- /dev/null
+++ b/Tracking/TrkExtrapolation/TrkExAlgs/src/PropResultRootWriterSvc.cxx
@@ -0,0 +1,84 @@
+ 
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "TrkExAlgs/PropResultRootWriterSvc.h"
+
+#include <vector>
+#include <deque>
+#include <mutex>
+#include <thread>
+
+#include "TFile.h"
+
+Trk::PropResultRootWriterSvc::PropResultRootWriterSvc( const std::string& name, ISvcLocator* svc )
+: AthService(name, svc),
+  m_thistSvc("THistSvc", name),
+  m_tree(0) {
+}
+
+Trk::PropResultRootWriterSvc::~PropResultRootWriterSvc() {}
+
+StatusCode Trk::PropResultRootWriterSvc::initialize()
+{
+  ATH_CHECK( AthService::initialize() );
+
+  CHECK(m_thistSvc.retrieve());
+  
+  const std::string treeName = m_treeName;  
+  m_tree = new TTree(treeName.data(), "MyStudies");
+  
+  std::string fullNtupleName = m_ntupleDirName + m_treeName;
+  CHECK(m_thistSvc->regTree(fullNtupleName, m_tree));
+
+  if(m_tree == nullptr) {
+    ATH_MSG_ERROR("Unable to create TTree");
+    return StatusCode::FAILURE;
+  }
+
+  m_tree->Branch("event_nr"   , &m_eventNum   );
+  
+  m_tree->Branch("start_d0"   , &m_start_d0   );
+  m_tree->Branch("start_z0"   , &m_start_z0   );
+  m_tree->Branch("start_phi"  , &m_start_phi  );
+  m_tree->Branch("start_theta", &m_start_theta);
+  m_tree->Branch("start_qop"  , &m_start_qop  );
+  
+  m_tree->Branch("fwd_success"    , &m_fwd_success    );
+  m_tree->Branch("fwd_time"       , &m_fwd_time       );
+  m_tree->Branch("fwd_final_l0"   , &m_fwd_final_l0   );
+  m_tree->Branch("fwd_final_l1"   , &m_fwd_final_l1   );
+  m_tree->Branch("fwd_final_x"    , &m_fwd_final_x    );
+  m_tree->Branch("fwd_final_y"    , &m_fwd_final_y    );
+  m_tree->Branch("fwd_final_z"    , &m_fwd_final_z    );
+  m_tree->Branch("fwd_final_phi"  , &m_fwd_final_phi  );
+  m_tree->Branch("fwd_final_theta", &m_fwd_final_theta);
+  m_tree->Branch("fwd_final_qop"  , &m_fwd_final_qop  );
+  m_tree->Branch("fwd_final_sigma_l0"   , &m_fwd_final_sigma_l0   );
+  m_tree->Branch("fwd_final_sigma_l1"   , &m_fwd_final_sigma_l1   );
+  m_tree->Branch("fwd_final_sigma_phi"  , &m_fwd_final_sigma_phi  );
+  m_tree->Branch("fwd_final_sigma_theta", &m_fwd_final_sigma_theta);
+  m_tree->Branch("fwd_final_sigma_qop"  , &m_fwd_final_sigma_qop  );
+  
+  m_tree->Branch("bkw_success"    , &m_bkw_success    );
+  m_tree->Branch("bkw_time"       , &m_bkw_time       );
+  m_tree->Branch("bkw_final_d0"   , &m_bkw_final_d0   );
+  m_tree->Branch("bkw_final_z0"   , &m_bkw_final_z0   );
+  m_tree->Branch("bkw_final_phi"  , &m_bkw_final_phi  );
+  m_tree->Branch("bkw_final_theta", &m_bkw_final_theta);
+  m_tree->Branch("bkw_final_qop"  , &m_bkw_final_qop  );
+  m_tree->Branch("bkw_final_sigma_d0"   , &m_bkw_final_sigma_d0   );
+  m_tree->Branch("bkw_final_sigma_z0"   , &m_bkw_final_sigma_z0   );
+  m_tree->Branch("bkw_final_sigma_phi"  , &m_bkw_final_sigma_phi  );
+  m_tree->Branch("bkw_final_sigma_theta", &m_bkw_final_sigma_theta);
+  m_tree->Branch("bkw_final_sigma_qop"  , &m_bkw_final_sigma_qop  );
+  
+  return StatusCode::SUCCESS;
+}
+  
+StatusCode Trk::PropResultRootWriterSvc::finalize()
+{
+  return StatusCode::SUCCESS;
+}
+
diff --git a/Tracking/TrkExtrapolation/TrkExAlgs/src/components/TrkExAlgs_entries.cxx b/Tracking/TrkExtrapolation/TrkExAlgs/src/components/TrkExAlgs_entries.cxx
index ee87e754693843c217a3ff82e1c8ece6df873da0..b87faee0acdd8b826f816beacf05717907e13487 100644
--- a/Tracking/TrkExtrapolation/TrkExAlgs/src/components/TrkExAlgs_entries.cxx
+++ b/Tracking/TrkExtrapolation/TrkExAlgs/src/components/TrkExAlgs_entries.cxx
@@ -1,16 +1,20 @@
 #include "TrkExAlgs/ExtrapolatorTest.h"
+#include "TrkExAlgs/ExtrapolatorComparisonTest.h"
 #include "TrkExAlgs/CombinedExtrapolatorTest.h"
 #include "TrkExAlgs/CETmaterial.h"
 #include "TrkExAlgs/ExtrapolationValidation.h"
 #include "TrkExAlgs/EnergyLossExtrapolationValidation.h"
 #include "TrkExAlgs/RiddersAlgorithm.h"
+#include "TrkExAlgs/PropResultRootWriterSvc.h"
+
 
 using namespace Trk;
 
 DECLARE_COMPONENT( RiddersAlgorithm )
 DECLARE_COMPONENT( ExtrapolatorTest )
+DECLARE_COMPONENT( ExtrapolatorComparisonTest )
 DECLARE_COMPONENT( ExtrapolationValidation )
 DECLARE_COMPONENT( EnergyLossExtrapolationValidation )
 DECLARE_COMPONENT( CombinedExtrapolatorTest )
 DECLARE_COMPONENT( CETmaterial )
-
+DECLARE_COMPONENT( PropResultRootWriterSvc )