diff --git a/.gitignore b/.gitignore
index 84bc868d107179b702448f6a7f0ca094b86a07ee..555a2beb5b9b82f76bf2dabd227cb5e2e9af266a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -20,3 +20,5 @@
 *.lib
 *.root
 tmp.*
+.idea/**
+cmake-debug-build/**
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 7fe8c1fa0e248c98fdcfbbd65a0aa79738292674..4c9843953aedfea314e7996b98c26f44531b52e1 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -27,7 +27,7 @@ build_image:
     - set +e && source ${ATLAS_LOCAL_ROOT_BASE}/user/atlasLocalSetup.sh; set -e
     - set +e && asetup --input=../../calypso/asetup.faser master,latest,Athena; set -e
     - cmake ../../calypso
-    - make -j
+    - make -j 3
   artifacts:
     paths:
     - build/
diff --git a/DetectorDescription/GeoModel/GeoModelInterfaces/GeoModelInterfaces/IGeoModelTool.h b/DetectorDescription/GeoModel/GeoModelInterfaces/GeoModelInterfaces/IGeoModelTool.h
index 307d858b20dba55a69db3a041515800832a52530..1b0e98652db1907d64fc91434f599e8116e499de 100644
--- a/DetectorDescription/GeoModel/GeoModelInterfaces/GeoModelInterfaces/IGeoModelTool.h
+++ b/DetectorDescription/GeoModel/GeoModelInterfaces/GeoModelInterfaces/IGeoModelTool.h
@@ -7,6 +7,7 @@
 
 #include "GaudiKernel/IAlgTool.h"
 #include "AthenaKernel/IOVSvcDefs.h"
+#include "CxxUtils/checker_macros.h"
 
 static const InterfaceID IID_IGeoModelTool( "IGeoModelTool", 1, 0 );
 
@@ -25,7 +26,7 @@ public:
     virtual StatusCode clear() = 0;
 
     // Register callback function on ConDB object
-    virtual StatusCode registerCallback() = 0;
+    virtual StatusCode registerCallback ATLAS_NOT_THREAD_SAFE () = 0;
 
     // Callback function itself
     virtual StatusCode align(IOVSVC_CALLBACK_ARGS) = 0;
diff --git a/Scintillator/ScintDetDescr/PreshowerGeoModel/PreshowerGeoModel/PreshowerDetectorTool.h b/Scintillator/ScintDetDescr/PreshowerGeoModel/PreshowerGeoModel/PreshowerDetectorTool.h
index 634f702e9fec22a4585ee4ea708fefb6ae9be924..818dd7ce590b7ca03c059b3698b76a82061efa18 100644
--- a/Scintillator/ScintDetDescr/PreshowerGeoModel/PreshowerGeoModel/PreshowerDetectorTool.h
+++ b/Scintillator/ScintDetDescr/PreshowerGeoModel/PreshowerGeoModel/PreshowerDetectorTool.h
@@ -33,7 +33,7 @@ public:
   virtual StatusCode clear() override final;
 
   // Register callback function on ConDB object
-  virtual StatusCode registerCallback() override final;
+  virtual StatusCode registerCallback ATLAS_NOT_THREAD_SAFE () override final;
 
   // Callback function itself
   virtual StatusCode align(IOVSVC_CALLBACK_ARGS) override;
diff --git a/Scintillator/ScintDetDescr/TriggerGeoModel/TriggerGeoModel/TriggerDetectorTool.h b/Scintillator/ScintDetDescr/TriggerGeoModel/TriggerGeoModel/TriggerDetectorTool.h
index f947787e92e34459b0f2e0ae9d600331d54277ee..1cc12211f0eaf6b14096c4df634a954d874ad2d6 100644
--- a/Scintillator/ScintDetDescr/TriggerGeoModel/TriggerGeoModel/TriggerDetectorTool.h
+++ b/Scintillator/ScintDetDescr/TriggerGeoModel/TriggerGeoModel/TriggerDetectorTool.h
@@ -33,7 +33,7 @@ public:
   virtual StatusCode clear() override final;
 
   // Register callback function on ConDB object
-  virtual StatusCode registerCallback() override final;
+  virtual StatusCode registerCallback ATLAS_NOT_THREAD_SAFE () override final;
 
   // Callback function itself
   virtual StatusCode align(IOVSVC_CALLBACK_ARGS) override;
diff --git a/Scintillator/ScintDetDescr/VetoGeoModel/VetoGeoModel/VetoDetectorTool.h b/Scintillator/ScintDetDescr/VetoGeoModel/VetoGeoModel/VetoDetectorTool.h
index bad48487d32f1c098ac23d430aafd753314c289d..6e8895e1db59e74820cff9a91bedff1c824cbc8c 100644
--- a/Scintillator/ScintDetDescr/VetoGeoModel/VetoGeoModel/VetoDetectorTool.h
+++ b/Scintillator/ScintDetDescr/VetoGeoModel/VetoGeoModel/VetoDetectorTool.h
@@ -33,7 +33,7 @@ public:
   virtual StatusCode clear() override final;
 
   // Register callback function on ConDB object
-  virtual StatusCode registerCallback() override final;
+  virtual StatusCode registerCallback ATLAS_NOT_THREAD_SAFE () override final;
 
   // Callback function itself
   virtual StatusCode align(IOVSVC_CALLBACK_ARGS) override;
diff --git a/Scintillator/ScintEventCnv/ScintEventAthenaPool/src/ScintWaveformCnv_p0.cxx b/Scintillator/ScintEventCnv/ScintEventAthenaPool/src/ScintWaveformCnv_p0.cxx
index ffc6f0d8df91fe68a4433b33c4784d2238a7c555..477849763c6bd19b5ce9cbf82b36c14b9f7303d7 100644
--- a/Scintillator/ScintEventCnv/ScintEventAthenaPool/src/ScintWaveformCnv_p0.cxx
+++ b/Scintillator/ScintEventCnv/ScintEventAthenaPool/src/ScintWaveformCnv_p0.cxx
@@ -5,7 +5,7 @@
 #include "ScintWaveformCnv_p0.h"
 
 void
-ScintWaveformCnv_p0::persToTrans(const ScintWaveform_p0* persObj, ScintWaveform* transObj, MsgStream& log) {
+ScintWaveformCnv_p0::persToTrans(const ScintWaveform_p0* persObj, ScintWaveform* transObj, MsgStream& /*log*/) {
 
   // Just fill available data here
   // Rest of it patched up in ScintWaveformContainerCnv_p0
@@ -16,7 +16,7 @@ ScintWaveformCnv_p0::persToTrans(const ScintWaveform_p0* persObj, ScintWaveform*
 }
 
 void
-ScintWaveformCnv_p0::transToPers(const ScintWaveform* transObj, ScintWaveform_p0* persObj, MsgStream& log) {
+ScintWaveformCnv_p0::transToPers(const ScintWaveform* transObj, ScintWaveform_p0* persObj, MsgStream& /*log*/) {
 
   // log << MSG::DEBUG << "ScintWaveformCnv_p0::transToPers called" << endmsg;
   // log << MSG::DEBUG << "Transient waveform:" << endmsg;
diff --git a/Simulation/G4Utilities/Geo2G4/src/Geo2G4OpticalSurfaceFactory.cxx b/Simulation/G4Utilities/Geo2G4/src/Geo2G4OpticalSurfaceFactory.cxx
index 3af74f855bbd89eeaabbb4cc48dad4e3e14d285d..5440a1dca7039ab9af0d8a8a9e2d5072877656f1 100644
--- a/Simulation/G4Utilities/Geo2G4/src/Geo2G4OpticalSurfaceFactory.cxx
+++ b/Simulation/G4Utilities/Geo2G4/src/Geo2G4OpticalSurfaceFactory.cxx
@@ -115,7 +115,7 @@ G4OpticalSurface* Geo2G4OpticalSurfaceFactory::Build(const GeoOpticalSurface* ge
 
   // Create material properties table
   Geo2G4MatPropTableFactory* tFactory = Geo2G4MatPropTableFactory::instance();
-  GeoMaterialPropertiesTable* geoPropTable = geoOpticalSurface->GetMaterialPropertiesTable();
+  const GeoMaterialPropertiesTable* geoPropTable = geoOpticalSurface->GetMaterialPropertiesTable();
 
   if(geoPropTable){
     G4MaterialPropertiesTable* g4PropTable = tFactory->Build(geoPropTable);
diff --git a/Tracker/TrackerDetDescr/FaserSCT_GeoModel/FaserSCT_GeoModel/FaserSCT_DetectorTool.h b/Tracker/TrackerDetDescr/FaserSCT_GeoModel/FaserSCT_GeoModel/FaserSCT_DetectorTool.h
index c4cc0f8eb6e753ac51d20377110d1fcedd1ce498..45011c9bbbcd565c8cad2ca482e34f5698f00bae 100644
--- a/Tracker/TrackerDetDescr/FaserSCT_GeoModel/FaserSCT_GeoModel/FaserSCT_DetectorTool.h
+++ b/Tracker/TrackerDetDescr/FaserSCT_GeoModel/FaserSCT_GeoModel/FaserSCT_DetectorTool.h
@@ -30,7 +30,7 @@ public:
   virtual StatusCode clear() override final;
 
   // Register callback function on ConDB object
-  virtual StatusCode registerCallback() override final;
+  virtual StatusCode registerCallback ATLAS_NOT_THREAD_SAFE () override final;
 
   // Callback function itself
   virtual StatusCode align(IOVSVC_CALLBACK_ARGS) override;
diff --git a/Tracker/TrackerRecAlgs/TruthSeededTrackFinder/python/TruthSeededTrackFinderConfig.py b/Tracker/TrackerRecAlgs/TruthSeededTrackFinder/python/TruthSeededTrackFinderConfig.py
index 671f16ffd7cc43b38dcb1ed1f35bf3cb0d0da685..25ea502023aa075b792f5962280a60ca161a8e86 100644
--- a/Tracker/TrackerRecAlgs/TruthSeededTrackFinder/python/TruthSeededTrackFinderConfig.py
+++ b/Tracker/TrackerRecAlgs/TruthSeededTrackFinder/python/TruthSeededTrackFinderConfig.py
@@ -4,17 +4,20 @@ Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
 """
 from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator
 from AthenaConfiguration.ComponentFactory import CompFactory
+
 Tracker__TruthSeededTrackFinder, THistSvc=CompFactory.getComps("Tracker::TruthSeededTrackFinder", "THistSvc")
 
 from OutputStreamAthenaPool.OutputStreamConfig import OutputStreamCfg
 
 
+
 def TruthSeededTrackFinderBasicCfg(flags, **kwargs):
     """Return ComponentAccumulator for TruthSeededTrackFinder"""
     acc = ComponentAccumulator()
     kwargs.setdefault("SpacePointsSCTName", "SCT_SpacePointContainer")
-    kwargs.setdefault("SpacePointsSeedsName", "Seeds_SpacePointContainer")
+    kwargs.setdefault("FaserSpacePointsSeedsName", "Seeds_SpacePointContainer")
     acc.addEventAlgo(Tracker__TruthSeededTrackFinder(**kwargs))
+   # attach ToolHandles
     return acc
 
 def TruthSeededTrackFinder_OutputCfg(flags):
diff --git a/Tracker/TrackerRecAlgs/TruthSeededTrackFinder/src/TruthSeededTrackFinder.cxx b/Tracker/TrackerRecAlgs/TruthSeededTrackFinder/src/TruthSeededTrackFinder.cxx
index 7c63367f8b313f2c4b6615cb016c3d45fbd847a7..7464461b9799451564a567c73fefeb92d4834047 100755
--- a/Tracker/TrackerRecAlgs/TruthSeededTrackFinder/src/TruthSeededTrackFinder.cxx
+++ b/Tracker/TrackerRecAlgs/TruthSeededTrackFinder/src/TruthSeededTrackFinder.cxx
@@ -19,7 +19,6 @@
 
 // Space point Classes,
 #include "TrkSpacePoint/SpacePointCollection.h"
-// #include "TrkSpacePoint/SpacePointCLASS_DEF.h"
 #include "TrackerIdentifier/FaserSCT_ID.h"
 
 
@@ -30,346 +29,581 @@
 
 #include "AthenaMonitoringKernel/Monitored.h"
 
+//!!!!!!!!!!!!!!!!!!!!!!!!
+//#include "Acts/EventData/TrackParameters.hpp"
+#include "TrackerReadoutGeometry/SCT_DetectorManager.h"
+#include "Acts/Utilities/detail/periodic.hpp"
+#include "Acts/Utilities/Definitions.hpp"
+#include "Acts/Utilities/Units.hpp"
+using namespace Acts::UnitLiterals;
+//!!!!!!!!!!!!!!!!!!!!!!!!
 namespace Tracker
 {
 
-//------------------------------------------------------------------------
-TruthSeededTrackFinder::TruthSeededTrackFinder(const std::string& name,
-    ISvcLocator* pSvcLocator)
-  : AthReentrantAlgorithm(name, pSvcLocator)
-  , m_hist_n(0)
-  , m_hist_x(0)
-  , m_hist_y(0)
-  , m_hist_z(0)
-  , m_hist_r(0)
-  , m_hist_phi(0)
-  , m_hist_eta(0)
-  , m_hist_layer(0)
-  , m_hist_strip(0)
-  , m_hist_station(0)
-  , m_hist_x_y_plane0(0)
-  , m_hist_x_y_plane1(0)
-  , m_hist_x_y_plane2(0)
-  , m_hist_x_y_plane3(0)
-  , m_hist_x_y_plane4(0)
-  , m_hist_x_y_plane5(0)
-  , m_hist_x_y_plane6(0)
-  , m_hist_x_y_plane7(0)
-  , m_hist_x_y_plane8(0)
-  , m_hist_x_z(0)
-  , m_hist_y_z(0)
-  , m_hist_sp_sensor(0)
-  , m_hist_sp_module (0)
-  , m_hist_sp_row (0)
-  , m_hist_sp_plane (0)
-  , m_hist_sp_layer (0)
-  , m_hist_sp_station (0)
-
-  , m_thistSvc("THistSvc", name)
-{ 
-}
+  //------------------------------------------------------------------------
+  TruthSeededTrackFinder::TruthSeededTrackFinder(const std::string& name,
+      ISvcLocator* pSvcLocator)
+    : AthReentrantAlgorithm(name, pSvcLocator)
+      , m_hist_n(0)
+      , m_hist_x(0)
+      , m_hist_y(0)
+      , m_hist_z(0)
+      , m_hist_r(0)
+      , m_hist_phi(0)
+      , m_hist_eta(0)
+      , m_hist_layer(0)
+      , m_hist_strip(0)
+      , m_hist_station(0)
+      , m_hist_x_y_plane0(0)
+      , m_hist_x_y_plane1(0)
+      , m_hist_x_y_plane2(0)
+      , m_hist_x_y_plane3(0)
+      , m_hist_x_y_plane4(0)
+      , m_hist_x_y_plane5(0)
+      , m_hist_x_y_plane6(0)
+      , m_hist_x_y_plane7(0)
+      , m_hist_x_y_plane8(0)
+      , m_hist_x_z(0)
+      , m_hist_y_z(0)
+      , m_hist_sp_sensor(0)
+      , m_hist_sp_module (0)
+      , m_hist_sp_row (0)
+      , m_hist_sp_plane (0)
+      , m_hist_sp_layer (0)
+      , m_hist_sp_station (0)
+	//!!!!!!!!!!!!!!!!!!!!
+      , m_hist_InitReso_px (0)
+      , m_hist_InitReso_py (0)
+      , m_hist_InitReso_pz (0)
+	//!!!!!!!!!!!!!!!!!!!!
+
+      , m_thistSvc("THistSvc", name)
+      { 
+      }
 
-//-----------------------------------------------------------------------
-StatusCode TruthSeededTrackFinder::initialize()
-{
-  //
-  ATH_MSG_DEBUG( "TruthTrackSeeds::initialize()" );
+  //-----------------------------------------------------------------------
+  StatusCode TruthSeededTrackFinder::initialize()
+  {
+    //
+    ATH_MSG_DEBUG( "TruthTrackSeeds::initialize()" );
+
+    CHECK(m_thistSvc.retrieve());
+    // Check that clusters, space points and ids have names
+    if ( m_Sct_spcontainerKey.key().empty()){
+      ATH_MSG_FATAL( "SCTs selected and no name set for SCT clusters");
+      return StatusCode::FAILURE;
+    }
+    ATH_CHECK( m_Sct_spcontainerKey.initialize() );
 
-  CHECK(m_thistSvc.retrieve());
-  // Check that clusters, space points and ids have names
-  if ( m_Sct_spcontainerKey.key().empty()){
-    ATH_MSG_FATAL( "SCTs selected and no name set for SCT clusters");
-    return StatusCode::FAILURE;
-  }
-  ATH_CHECK( m_Sct_spcontainerKey.initialize() );
+    // create containers (requires the Identifier Helpers)
+    ATH_CHECK(detStore()->retrieve(m_idHelper,"FaserSCT_ID"));
+
+    // Initialize the key of input SiElementPropertiesTable and SiDetectorElementCollection for SCT
+    ATH_CHECK(m_SCTDetEleCollKey.initialize());
 
-  if ( m_seed_spcontainerKey.key().empty()){
-    ATH_MSG_FATAL( "No name set for output seeds space points");
-    return StatusCode::FAILURE;
+    if ( m_seed_spcontainerKey.key().empty()){
+      ATH_MSG_FATAL( "No name set for output seeds space points");
+      return StatusCode::FAILURE;
+    }
+
+    ATH_CHECK( m_seed_spcontainerKey.initialize() );
+
+    ATH_CHECK( m_mcEventKey.initialize() );
+    ATH_CHECK( m_faserSiHitKey.initialize() );
+    ATH_CHECK( m_faserRdoKey.initialize());
+    ATH_CHECK( m_sctMap.initialize());
+    ATH_MSG_INFO( "Using GenEvent collection with key " << m_mcEventKey.key());
+    ATH_MSG_INFO( "Using Faser SiHit collection with key " << m_faserSiHitKey.key());
+    ATH_MSG_INFO( "Using FaserSCT RDO Container with key " << m_faserRdoKey.key());
+    ATH_MSG_INFO( "Using SCT_SDO_Map with key "<< m_sctMap.key());
+
+    m_hist_n=new TH1D("sp_n","sp_n",20,0,20);
+    m_hist_x=new TH1D("sp_x","sp_x",100,-200,200);
+    m_hist_y=new TH1D("sp_y","sp_y",100,-200,200);
+    m_hist_z=new TH1D("sp_z","sp_z",3500,0,3500);
+    m_hist_r=new TH1D("sp_r","sp_r",100,0,200);
+    m_hist_eta=new TH1D("sp_eta","sp_eta",100,0,5);
+    m_hist_phi=new TH1D("sp_phi","sp_phi",100,-3.2,3.2);
+    m_hist_strip=new TH1D("sp_strip","sp_strip",1000,0,1000);
+    m_hist_layer=new TH1D("sp_layer","sp_layer",100,-10,10);
+    m_hist_station=new TH1D("sp_station","sp_station",100,-10,10);
+    m_hist_sp_station=new TH1D("sp_all_station","sp_station",100,-10,10);
+    m_hist_sp_row=new TH1D("sp_all_row","sp_station",100,-10,10);
+    m_hist_sp_module=new TH1D("sp_all_module","sp_station",100,-10,10);
+    m_hist_sp_sensor=new TH1D("sp_all_sensor","sp_station",100,-10,10);
+    m_hist_sp_plane=new TH1D("sp_all_plane","sp_station",100,-10,10);
+    m_hist_sp_layer=new TH1D("sp_all_layer","sp_station",100,-10,10);
+    m_hist_x_z=new TH2D("sp_x_z","sp_x_z",100,-200,200,3500,0,3500);
+    m_hist_y_z=new TH2D("sp_y_z","sp_y_z",100,-200,200,3500,0,3500);
+    m_hist_x_y_plane0=new TH2D("sp_x_y_plane0","sp_x_y_plane0",100,-200,200,100,-200,200);
+    m_hist_x_y_plane1=new TH2D("sp_x_y_plane1","sp_x_y_plane1",100,-200,200,100,-200,200);
+    m_hist_x_y_plane2=new TH2D("sp_x_y_plane2","sp_x_y_plane2",100,-200,200,100,-200,200);
+    m_hist_x_y_plane3=new TH2D("sp_x_y_plane3","sp_x_y_plane3",100,-200,200,100,-200,200);
+    m_hist_x_y_plane4=new TH2D("sp_x_y_plane4","sp_x_y_plane4",100,-200,200,100,-200,200);
+    m_hist_x_y_plane5=new TH2D("sp_x_y_plane5","sp_x_y_plane5",100,-200,200,100,-200,200);
+    m_hist_x_y_plane6=new TH2D("sp_x_y_plane6","sp_x_y_plane6",100,-200,200,100,-200,200);
+    m_hist_x_y_plane7=new TH2D("sp_x_y_plane7","sp_x_y_plane7",100,-200,200,100,-200,200);
+    m_hist_x_y_plane8=new TH2D("sp_x_y_plane8","sp_x_y_plane8",100,-200,200,100,-200,200);
+    CHECK(m_thistSvc->regHist("/TruthTrackSeeds/sp/sp_n",m_hist_n));
+    CHECK(m_thistSvc->regHist("/TruthTrackSeeds/sp/sp_x",m_hist_x));
+    CHECK(m_thistSvc->regHist("/TruthTrackSeeds/sp/sp_y",m_hist_y));
+    CHECK(m_thistSvc->regHist("/TruthTrackSeeds/sp/sp_z",m_hist_z));
+    CHECK(m_thistSvc->regHist("/TruthTrackSeeds/sp/sp_r",m_hist_r));
+    CHECK(m_thistSvc->regHist("/TruthTrackSeeds/sp/sp_eta",m_hist_eta));
+    CHECK(m_thistSvc->regHist("/TruthTrackSeeds/sp/sp_phi",m_hist_phi));
+    CHECK(m_thistSvc->regHist("/TruthTrackSeeds/sp/sp_strip",m_hist_strip));
+    CHECK(m_thistSvc->regHist("/TruthTrackSeeds/sp/sp_layer",m_hist_layer));
+    CHECK(m_thistSvc->regHist("/TruthTrackSeeds/sp/sp_station",m_hist_station));
+    CHECK(m_thistSvc->regHist("/TruthTrackSeeds/sp/sp_all_station",m_hist_sp_station));
+    CHECK(m_thistSvc->regHist("/TruthTrackSeeds/sp/sp_all_layer",m_hist_sp_layer));
+    CHECK(m_thistSvc->regHist("/TruthTrackSeeds/sp/sp_all_module",m_hist_sp_module));
+    CHECK(m_thistSvc->regHist("/TruthTrackSeeds/sp/sp_all_plane",m_hist_sp_plane));
+    CHECK(m_thistSvc->regHist("/TruthTrackSeeds/sp/sp_all_row",m_hist_sp_row));
+    CHECK(m_thistSvc->regHist("/TruthTrackSeeds/sp/sp_all_sensor",m_hist_sp_sensor));
+    CHECK(m_thistSvc->regHist("/TruthTrackSeeds/sp/sp_x_z",m_hist_x_z));
+    CHECK(m_thistSvc->regHist("/TruthTrackSeeds/sp/sp_y_z",m_hist_y_z));
+    CHECK(m_thistSvc->regHist("/TruthTrackSeeds/sp/sp_x_y_plane0",m_hist_x_y_plane0));
+    CHECK(m_thistSvc->regHist("/TruthTrackSeeds/sp/sp_x_y_plane1",m_hist_x_y_plane1));
+    CHECK(m_thistSvc->regHist("/TruthTrackSeeds/sp/sp_x_y_plane2",m_hist_x_y_plane2));
+    CHECK(m_thistSvc->regHist("/TruthTrackSeeds/sp/sp_x_y_plane3",m_hist_x_y_plane3));
+    CHECK(m_thistSvc->regHist("/TruthTrackSeeds/sp/sp_x_y_plane4",m_hist_x_y_plane4));
+    CHECK(m_thistSvc->regHist("/TruthTrackSeeds/sp/sp_x_y_plane5",m_hist_x_y_plane5));
+    CHECK(m_thistSvc->regHist("/TruthTrackSeeds/sp/sp_x_y_plane6",m_hist_x_y_plane6));
+    CHECK(m_thistSvc->regHist("/TruthTrackSeeds/sp/sp_x_y_plane7",m_hist_x_y_plane7));
+    CHECK(m_thistSvc->regHist("/TruthTrackSeeds/sp/sp_x_y_plane8",m_hist_x_y_plane8));
+	//!!!!!!!!!!!!!!!!!!!!
+    m_hist_InitReso_px=new TH1D("InitReso_px","InitReso_px",200,-10,10);
+    m_hist_InitReso_py=new TH1D("InitReso_py","InitReso_py",200,-10,10);
+    m_hist_InitReso_pz=new TH1D("InitReso_pz","InitReso_pz",200,-10,10);
+    CHECK(m_thistSvc->regHist("/TruthTrackSeeds/sp/InitReso_px",m_hist_InitReso_px));
+    CHECK(m_thistSvc->regHist("/TruthTrackSeeds/sp/InitReso_py",m_hist_InitReso_py));
+    CHECK(m_thistSvc->regHist("/TruthTrackSeeds/sp/InitReso_pz",m_hist_InitReso_pz));
+	//!!!!!!!!!!!!!!!!!!!!
+    ATH_MSG_INFO( "TruthTrackSeeds::initialized for package version " << PACKAGE_VERSION );
+    return StatusCode::SUCCESS;
   }
 
-  ATH_CHECK( m_seed_spcontainerKey.initialize() );
-
-  // create containers (requires the Identifier Helpers)
-  ATH_CHECK(detStore()->retrieve(m_idHelper,"FaserSCT_ID"));
-
-  // Initialize the key of input SiElementPropertiesTable and SiDetectorElementCollection for SCT
-  ATH_CHECK(m_SCTDetEleCollKey.initialize());
-
-  ATH_CHECK( m_mcEventKey.initialize() );
-  ATH_CHECK( m_faserSiHitKey.initialize() );
-  ATH_CHECK( m_faserRdoKey.initialize());
-  ATH_CHECK( m_sctMap.initialize());
-  ATH_MSG_INFO( "Using GenEvent collection with key " << m_mcEventKey.key());
-  ATH_MSG_INFO( "Using Faser SiHit collection with key " << m_faserSiHitKey.key());
-  ATH_MSG_INFO( "Using FaserSCT RDO Container with key " << m_faserRdoKey.key());
-  ATH_MSG_INFO( "Using SCT_SDO_Map with key "<< m_sctMap.key());
-
-  m_hist_n=new TH1D("sp_n","sp_n",20,0,20);
-  m_hist_x=new TH1D("sp_x","sp_x",100,-200,200);
-  m_hist_y=new TH1D("sp_y","sp_y",100,-200,200);
-  m_hist_z=new TH1D("sp_z","sp_z",3500,0,3500);
-  m_hist_r=new TH1D("sp_r","sp_r",100,0,200);
-  m_hist_eta=new TH1D("sp_eta","sp_eta",100,0,5);
-  m_hist_phi=new TH1D("sp_phi","sp_phi",100,-3.2,3.2);
-  m_hist_strip=new TH1D("sp_strip","sp_strip",1000,0,1000);
-  m_hist_layer=new TH1D("sp_layer","sp_layer",100,-10,10);
-  m_hist_station=new TH1D("sp_station","sp_station",100,-10,10);
-  m_hist_sp_station=new TH1D("sp_all_station","sp_station",100,-10,10);
-  m_hist_sp_row=new TH1D("sp_all_row","sp_station",100,-10,10);
-  m_hist_sp_module=new TH1D("sp_all_module","sp_station",100,-10,10);
-  m_hist_sp_sensor=new TH1D("sp_all_sensor","sp_station",100,-10,10);
-  m_hist_sp_plane=new TH1D("sp_all_plane","sp_station",100,-10,10);
-  m_hist_sp_layer=new TH1D("sp_all_layer","sp_station",100,-10,10);
-  m_hist_x_z=new TH2D("sp_x_z","sp_x_z",100,-200,200,3500,0,3500);
-  m_hist_y_z=new TH2D("sp_y_z","sp_y_z",100,-200,200,3500,0,3500);
-  m_hist_x_y_plane0=new TH2D("sp_x_y_plane0","sp_x_y_plane0",100,-200,200,100,-200,200);
-  m_hist_x_y_plane1=new TH2D("sp_x_y_plane1","sp_x_y_plane1",100,-200,200,100,-200,200);
-  m_hist_x_y_plane2=new TH2D("sp_x_y_plane2","sp_x_y_plane2",100,-200,200,100,-200,200);
-  m_hist_x_y_plane3=new TH2D("sp_x_y_plane3","sp_x_y_plane3",100,-200,200,100,-200,200);
-  m_hist_x_y_plane4=new TH2D("sp_x_y_plane4","sp_x_y_plane4",100,-200,200,100,-200,200);
-  m_hist_x_y_plane5=new TH2D("sp_x_y_plane5","sp_x_y_plane5",100,-200,200,100,-200,200);
-  m_hist_x_y_plane6=new TH2D("sp_x_y_plane6","sp_x_y_plane6",100,-200,200,100,-200,200);
-  m_hist_x_y_plane7=new TH2D("sp_x_y_plane7","sp_x_y_plane7",100,-200,200,100,-200,200);
-  m_hist_x_y_plane8=new TH2D("sp_x_y_plane8","sp_x_y_plane8",100,-200,200,100,-200,200);
-  CHECK(m_thistSvc->regHist("/TruthTrackSeeds/sp/sp_n",m_hist_n));
-  CHECK(m_thistSvc->regHist("/TruthTrackSeeds/sp/sp_x",m_hist_x));
-  CHECK(m_thistSvc->regHist("/TruthTrackSeeds/sp/sp_y",m_hist_y));
-  CHECK(m_thistSvc->regHist("/TruthTrackSeeds/sp/sp_z",m_hist_z));
-  CHECK(m_thistSvc->regHist("/TruthTrackSeeds/sp/sp_r",m_hist_r));
-  CHECK(m_thistSvc->regHist("/TruthTrackSeeds/sp/sp_eta",m_hist_eta));
-  CHECK(m_thistSvc->regHist("/TruthTrackSeeds/sp/sp_phi",m_hist_phi));
-  CHECK(m_thistSvc->regHist("/TruthTrackSeeds/sp/sp_strip",m_hist_strip));
-  CHECK(m_thistSvc->regHist("/TruthTrackSeeds/sp/sp_layer",m_hist_layer));
-  CHECK(m_thistSvc->regHist("/TruthTrackSeeds/sp/sp_station",m_hist_station));
-  CHECK(m_thistSvc->regHist("/TruthTrackSeeds/sp/sp_all_station",m_hist_sp_station));
-  CHECK(m_thistSvc->regHist("/TruthTrackSeeds/sp/sp_all_layer",m_hist_sp_layer));
-  CHECK(m_thistSvc->regHist("/TruthTrackSeeds/sp/sp_all_module",m_hist_sp_module));
-  CHECK(m_thistSvc->regHist("/TruthTrackSeeds/sp/sp_all_plane",m_hist_sp_plane));
-  CHECK(m_thistSvc->regHist("/TruthTrackSeeds/sp/sp_all_row",m_hist_sp_row));
-  CHECK(m_thistSvc->regHist("/TruthTrackSeeds/sp/sp_all_sensor",m_hist_sp_sensor));
-  CHECK(m_thistSvc->regHist("/TruthTrackSeeds/sp/sp_x_z",m_hist_x_z));
-  CHECK(m_thistSvc->regHist("/TruthTrackSeeds/sp/sp_y_z",m_hist_y_z));
-  CHECK(m_thistSvc->regHist("/TruthTrackSeeds/sp/sp_x_y_plane0",m_hist_x_y_plane0));
-  CHECK(m_thistSvc->regHist("/TruthTrackSeeds/sp/sp_x_y_plane1",m_hist_x_y_plane1));
-  CHECK(m_thistSvc->regHist("/TruthTrackSeeds/sp/sp_x_y_plane2",m_hist_x_y_plane2));
-  CHECK(m_thistSvc->regHist("/TruthTrackSeeds/sp/sp_x_y_plane3",m_hist_x_y_plane3));
-  CHECK(m_thistSvc->regHist("/TruthTrackSeeds/sp/sp_x_y_plane4",m_hist_x_y_plane4));
-  CHECK(m_thistSvc->regHist("/TruthTrackSeeds/sp/sp_x_y_plane5",m_hist_x_y_plane5));
-  CHECK(m_thistSvc->regHist("/TruthTrackSeeds/sp/sp_x_y_plane6",m_hist_x_y_plane6));
-  CHECK(m_thistSvc->regHist("/TruthTrackSeeds/sp/sp_x_y_plane7",m_hist_x_y_plane7));
-  CHECK(m_thistSvc->regHist("/TruthTrackSeeds/sp/sp_x_y_plane8",m_hist_x_y_plane8));
-  ATH_MSG_INFO( "TruthTrackSeeds::initialized for package version " << PACKAGE_VERSION );
-  return StatusCode::SUCCESS;
-}
+  //-------------------------------------------------------------------------
 
-//-------------------------------------------------------------------------
+  StatusCode TruthSeededTrackFinder::execute (const EventContext& ctx) const
+  {
 
-StatusCode TruthSeededTrackFinder::execute (const EventContext& ctx) const
-{
 
+    ++m_numberOfEvents;
 
-  ++m_numberOfEvents;
+    // Handles created from handle keys behave like pointers to the corresponding container
+    SG::ReadHandle<McEventCollection> h_mcEvents(m_mcEventKey, ctx);
+    ATH_MSG_INFO("Read McEventContainer with " << h_mcEvents->size() << " events");
+    if (h_mcEvents->size() == 0) return StatusCode::FAILURE;
 
-  // Handles created from handle keys behave like pointers to the corresponding container
-  SG::ReadHandle<McEventCollection> h_mcEvents(m_mcEventKey, ctx);
-  ATH_MSG_INFO("Read McEventContainer with " << h_mcEvents->size() << " events");
-  if (h_mcEvents->size() == 0) return StatusCode::FAILURE;
+    SG::ReadHandle<FaserSiHitCollection> h_siHits(m_faserSiHitKey, ctx);
+    ATH_MSG_INFO("Read FaserSiHitCollection with " << h_siHits->size() << " hits");
 
-  SG::ReadHandle<FaserSiHitCollection> h_siHits(m_faserSiHitKey, ctx);
-  ATH_MSG_INFO("Read FaserSiHitCollection with " << h_siHits->size() << " hits");
+    SG::ReadHandle<FaserSCT_RDO_Container> h_sctRDO(m_faserRdoKey, ctx);
 
-  SG::ReadHandle<FaserSCT_RDO_Container> h_sctRDO(m_faserRdoKey, ctx);
 
+    SG::WriteHandle<SpacePointForSeedCollection> seedContainer_SCT(m_seed_spcontainerKey, ctx );
 
-  SG::WriteHandle<SpacePointContainer> seedContainer_SCT(m_seed_spcontainerKey, ctx );
+    ATH_CHECK( seedContainer_SCT.record( std::make_unique<SpacePointForSeedCollection>() ) );
+    ATH_MSG_INFO("Created SpacePointContainer " << m_seed_spcontainerKey.key() << " N= " << m_idHelper->wafer_hash_max());
 
-  ATH_CHECK( seedContainer_SCT.record( std::make_unique<SpacePointContainer>(m_idHelper->wafer_hash_max()) ) );
-  ATH_MSG_DEBUG("Created SpacePointContainer " << m_seed_spcontainerKey.key() << " N= " << m_idHelper->wafer_hash_max());
 
+    const TrackerDD::SiDetectorElementCollection* elements = nullptr;
+    SG::ReadCondHandle<TrackerDD::SiDetectorElementCollection> sctDetEle(m_SCTDetEleCollKey, ctx);
+    elements = sctDetEle.retrieve();
+    if (elements==nullptr) {
+      ATH_MSG_FATAL("Pointer of SiDetectorElementCollection (" << m_SCTDetEleCollKey.fullKey() << ") could not be retrieved");
+      return StatusCode::SUCCESS;
+    }
 
-  const TrackerDD::SiDetectorElementCollection* elements = nullptr;
-  SG::ReadCondHandle<TrackerDD::SiDetectorElementCollection> sctDetEle(m_SCTDetEleCollKey, ctx);
-  elements = sctDetEle.retrieve();
-  if (elements==nullptr) {
-    ATH_MSG_FATAL("Pointer of SiDetectorElementCollection (" << m_SCTDetEleCollKey.fullKey() << ") could not be retrieved");
-    return StatusCode::SUCCESS;
-  }
 
-  // register the IdentifiableContainer into StoreGate
+    // retrieve SCT cluster container
+    SG::ReadHandle<SpacePointContainer> sct_spcontainer( m_Sct_spcontainerKey, ctx );
+    if (!sct_spcontainer.isValid()){
+      msg(MSG:: FATAL) << "Could not find the data object "<< sct_spcontainer.name() << " !" << endmsg;
+      return StatusCode::RECOVERABLE;
+    }
 
+	//!!!!!!!!!!!!!!!!!!!!
+    static const TrackerDD::SCT_DetectorManager     *s_sct;
+    if(detStore()->retrieve(s_sct,"SCT").isFailure()) s_sct = 0;
+	int N_1_0=0, N_1_1=0, N_1_2=0, N_2_0=0, N_2_1=0, N_2_2=0;
+	int match_N_1_0=0, match_N_1_1=0, match_N_1_2=0, match_N_2_0=0, match_N_2_1=0, match_N_2_2=0;
+        HepMC::FourVector truthmom;
+	//!!!!!!!!!!!!!!!!!!!!
+
+    ATH_MSG_DEBUG( "SCT spacepoint container found: " << sct_spcontainer->size() << " collections" );
+    SpacePointContainer::const_iterator it = sct_spcontainer->begin();
+    SpacePointContainer::const_iterator itend = sct_spcontainer->end();
+
+    int nTruthSP=0;
+    ATH_MSG_DEBUG( "Start iteration of spacepoint collections"  );
+    for (; it != itend; ++it){
+      ++m_numberOfSPCollection;
+      const SpacePointCollection *colNext=&(**it);
+      int nReceivedSPSCT = colNext->size();
+
+      // Create SpacePointCollection
+      IdentifierHash idHash = colNext->identifyHash();
+      Identifier elementID = colNext->identify();
+
+
+      ATH_MSG_DEBUG( "Spacepoint collection in iteraction: size =  " <<nReceivedSPSCT <<", IDHash = "<<idHash<<", ID = "<<elementID );
+      if (nReceivedSPSCT== 0){
+	ATH_MSG_VERBOSE( "Algorithm found no space points" );
+	++m_numberOfEmptySPCollection;
+      } else {
+	SpacePointCollection::const_iterator sp_begin= colNext->begin();
+	SpacePointCollection::const_iterator sp_end= colNext->end();
+
+	ATH_MSG_DEBUG( "Iterate the spacepoint in collection "  );
+	for (; sp_begin != sp_end; ++sp_begin){
+	  ++m_numberOfSP;
+	  const Trk::SpacePoint* sp=&(**sp_begin);
+	  bool match=false;
+	  //get truth hit
+	  const auto identifier = sp->clusterList().first->identify();
+	  int station = m_idHelper->station(identifier);
+	  int plane = m_idHelper->layer(identifier);
+	  int row = m_idHelper->phi_module(identifier);
+	  int module = m_idHelper->eta_module(identifier);
+	  int sensor = m_idHelper->side(identifier);
+	  m_hist_sp_station->Fill(station);
+	  m_hist_sp_plane->Fill(plane);
+	  m_hist_sp_layer->Fill((station-1)*3+plane);
+	  m_hist_sp_row->Fill(row);
+	  m_hist_sp_module->Fill(module);
+	  m_hist_sp_sensor->Fill(sensor);
+	//!!!!!!!!!!!!!!!!!!!!
+	if (station==1 && plane==0) N_1_0++;
+	if (station==1 && plane==1) N_1_1++;
+	if (station==1 && plane==2) N_1_2++;
+	if (station==2 && plane==0) N_2_0++;
+	if (station==2 && plane==1) N_2_1++;
+	if (station==2 && plane==2) N_2_2++;
+	//!!!!!!!!!!!!!!!!!!!!
+
+	  ATH_MSG_DEBUG( "Spacepoint :"<<identifier  );
+	  SG::ReadHandle<TrackerSimDataCollection> h_collectionMap(m_sctMap, ctx);
+	  ATH_MSG_DEBUG("map size "<<h_collectionMap->size());
+	//!!!!!!!!!!!!!!!!!!!!
+		  std::cout<<"!!!!!!!!!  cluster: "<<sp->clusterList().first<<std::endl;
+		  ATH_MSG_DEBUG("!!!!!!!!!  cluster: "<<sp->clusterList().first->rdoList() );
+	//!!!!!!!!!!!!!!!!!!!!
+	  if( h_collectionMap->count(identifier) == 0)
+	  {
+	    ATH_MSG_INFO("no map found w/identifier "<<identifier);
+	    ++m_numberOfNoMap;
+	    continue;
+	  }
 
-  // retrieve SCT cluster container
-  SG::ReadHandle<SpacePointContainer> sct_spcontainer( m_Sct_spcontainerKey, ctx );
-  if (!sct_spcontainer.isValid()){
-    msg(MSG:: FATAL) << "Could not find the data object "<< sct_spcontainer.name() << " !" << endmsg;
-    return StatusCode::RECOVERABLE;
-  }
+	  //Collection map takes identifier and returns simulation data
+	  const auto& simdata = h_collectionMap->find(identifier)->second;
+	  const auto& deposits = simdata.getdeposits();
 
+	  //loop through deposits to find one w/ highest energy & get barcode
+	  float highestDep = 0;
+	  int barcode = 0;
+	  HepMcParticleLink primary{};
+	  for( const auto& depositPair : deposits)
+	  {
+	      //!!!!!!!!!!!!!!!!!!!!!!!!
+	      depositPair.first->print(std::cout);
+	        std::cout<<"!!!!!!!!!!!  pdg id =  "<<depositPair.first->pdg_id()<<std::endl;
+		if (depositPair.first->pdg_id() == -13) {
+		HepMC::FourVector pv = depositPair.first->production_vertex()->position();
+		HepMC::FourVector ev = depositPair.first->end_vertex()->position ();
+	        truthmom = depositPair.first->momentum();
+	        std::cout<<"!!!!!!!!!!!  production_vertex: ( "<<pv.x()<<",  "<<pv.y()<<",  "<<pv.z()<<" )  "<<std::endl;
+	        std::cout<<"!!!!!!!!!!!  end_vertex: ( "<<ev.x()<<",  "<<ev.y()<<",  "<<ev.z()<<" )  "<<std::endl;
+		}
+	      //!!!!!!!!!!!!!!!!!!!!!!!!
+	    if( depositPair.second > highestDep)
+	    {
+	      highestDep = depositPair.second;
+	      barcode = depositPair.first->barcode();
+	      primary = depositPair.first;
+	      //!!!!depositPair.first->print(std::cout);
+	      ATH_MSG_DEBUG("pdg id "<<depositPair.first->pdg_id());
+	    }
+	  }
+
+	  ATH_MSG_DEBUG("final barcode of: "<<barcode);
+	  if(barcode%1000000 != 10001) continue;
+
+	  //!!!!!!!!!!!!!!!!!!!!!!!!
+	  if (primary->end_vertex() != nullptr)
+	   {
+	      for (auto daughter : primary->particles_out())
+		{
+		  // TODO: Check that daughter->production_vertex() and daughter->end_vertex() exist, and bracket the point you're interested in
+	          if (daughter->barcode() % 1000000 == primary->barcode()) {
+		     ATH_MSG_INFO("    daughter barcode: " << daughter->barcode() << " with energy " << daughter->momentum().e() << "  px = " << daughter->momentum().px() << "  py = " << daughter->momentum().py() << "  pz = " << daughter->momentum().pz() );
+		 if (daughter->production_vertex() != nullptr && daughter->end_vertex() != nullptr) { 
+		HepMC::FourVector pv = daughter->production_vertex()->position();
+		HepMC::FourVector ev = daughter->end_vertex()->position ();
+	        std::cout<<"!!!!!!!!!!!  production_vertex: ( "<<pv.x()<<",  "<<pv.y()<<",  "<<pv.z()<<" )  "<<std::endl;
+	        std::cout<<"!!!!!!!!!!!  end_vertex: ( "<<ev.x()<<",  "<<ev.y()<<",  "<<ev.z()<<" )  "<<std::endl;
+		 }
+		  }
+		}
+	   }
+	   //!!!!!!!!!!!!!!!!!!!!!!!!
+
+	  //Helper function to get hit location information from RDO identifier
+	  ATH_MSG_DEBUG("trying to match hit to stat/plane/row/mod/sens: "<<station<<" "<<plane<<" "<<row<<" "<<module<<" "<<sensor);
+	  for (const FaserSiHit& hit : *h_siHits)
+	  {
+	    ++m_numberOfHits;
+	    ATH_MSG_DEBUG("hit w/vals "<<hit.getStation()<<" "<<hit.getPlane()<<" "<<hit.getRow()<<" "<<hit.getModule()<<" "<<hit.getSensor()<<" barcode: "<<hit.trackNumber());
+	    //set of conditions to confirm looking at same particle in same place for SiHit as RDO
+	    if(hit.getStation() == station 
+		&& hit.getPlane() == plane
+		&& hit.getRow() == row
+		&& hit.getModule() == module
+		&& hit.getSensor() == sensor
+		&& hit.trackNumber() == barcode)
+	    {
+	      ++m_numberOfMatchSP;
+	      ATH_MSG_DEBUG("matched particle and plotting w/ barcode "<<barcode);
+	      match=true;
+	    }
+	      //!!!!!!!!!!!!!!!!!!!!!!!!
+	const TrackerDD::SiDetectorElement *geoelement=NULL;
+	Identifier  id = m_idHelper->wafer_id(hit.getStation(),
+			    		 hit.getPlane(),
+					 hit.getRow(),
+					 hit.getModule(),
+					 hit.getSensor() );
+
+	geoelement = s_sct->getDetectorElement(id);
+	if (geoelement) {
+	double m_ran_pos=(double)(std::rand())/RAND_MAX;
+	HepGeom::Point3D<double> m_lp_start,m_lp_end;
+	HepGeom::Point3D<double> m_new_pos;
+	//start and end position
+	m_lp_start=hit.localStartPosition();
+	m_lp_end=hit.localEndPosition();
+	m_new_pos=m_lp_start+(m_lp_end-m_lp_start)*m_ran_pos;
+	//muPos=Amg::EigenTransformToCLHEP(geoelement->transformHit()) * HepGeom::Point3D<double>(m_new_pos);
+	std::cout<<"!!!!!!!!!!!  hit start pos: "<<Amg::EigenTransformToCLHEP(geoelement->transformHit()) * HepGeom::Point3D<double>(m_lp_start)<<std::endl;
+	std::cout<<"!!!!!!!!!!!  hit end pos: "<<Amg::EigenTransformToCLHEP(geoelement->transformHit()) * HepGeom::Point3D<double>(m_lp_end)<<std::endl;
+	}
+	      //!!!!!!!!!!!!!!!!!!!!!!!!
+	  }
+	  //
+	  if(!match)
+	    continue;
+	  ++m_numberOfFills;
+	  ++nTruthSP;
+
+	  SpacePointForSeed* spseed=new SpacePointForSeed(sp);
+	  seedContainer_SCT->push_back(spseed);
+	  m_hist_r->Fill(sp->r());
+	  m_hist_eta->Fill(sp->eta());
+	  m_hist_phi->Fill(sp->phi());
+	  Amg::Vector3D gloPos=sp->globalPosition();
+	  m_hist_x->Fill(gloPos.x());
+	  m_hist_y->Fill(gloPos.y());
+	  m_hist_z->Fill(gloPos.z());
+	  m_hist_strip->Fill(m_idHelper->strip(elementID));
+	  m_hist_station->Fill(m_idHelper->station(elementID));
+	  m_hist_layer->Fill(m_idHelper->layer(elementID));
+	  m_hist_x_z->Fill(gloPos.x(),gloPos.z());
+	  m_hist_y_z->Fill(gloPos.y(),gloPos.z());
+	  int ilayer=m_idHelper->layer(elementID);
+	  int istation=m_idHelper->station(elementID);
+	  if ( ((istation-1)*3+ilayer) == 0 ) m_hist_x_y_plane0->Fill(gloPos.x(),gloPos.y());
+	  if ( ((istation-1)*3+ilayer) == 1 ) m_hist_x_y_plane1->Fill(gloPos.x(),gloPos.y());
+	  if ( ((istation-1)*3+ilayer) == 2 ) m_hist_x_y_plane2->Fill(gloPos.x(),gloPos.y());
+	  if ( ((istation-1)*3+ilayer) == 3 ) m_hist_x_y_plane3->Fill(gloPos.x(),gloPos.y());
+	  if ( ((istation-1)*3+ilayer) == 4 ) m_hist_x_y_plane4->Fill(gloPos.x(),gloPos.y());
+	  if ( ((istation-1)*3+ilayer) == 5 ) m_hist_x_y_plane5->Fill(gloPos.x(),gloPos.y());
+	  if ( ((istation-1)*3+ilayer) == 6 ) m_hist_x_y_plane6->Fill(gloPos.x(),gloPos.y());
+	  if ( ((istation-1)*3+ilayer) == 7 ) m_hist_x_y_plane7->Fill(gloPos.x(),gloPos.y());
+	  if ( ((istation-1)*3+ilayer) == 8 ) m_hist_x_y_plane8->Fill(gloPos.x(),gloPos.y());
+	//!!!!!!!!!!!!!!!!!!!!
+	if (istation==1 && ilayer==0) { match_N_1_0++; }
+	if (istation==1 && ilayer==1) { match_N_1_1++; }
+	if (istation==1 && ilayer==2) { match_N_1_2++; }
+	if (istation==2 && ilayer==0) { match_N_2_0++; }
+	if (istation==2 && ilayer==1) { match_N_2_1++; }
+	if (istation==2 && ilayer==2) { match_N_2_2++; }
+	std::cout<<"!!!!!!!!!!! (station, layer) = ("<<istation<<", "<<ilayer<<")     positopn = ("<<gloPos.x()<<", "<<gloPos.y()<<", "<<gloPos.z()<<") "<<std::endl;
+       if (std::fabs(gloPos.x())>100) std::cout<<"!!!!!!!!!!! badXXX "<<std::endl;
+	//!!!!!!!!!!!!!!!!!!!!
+	}
+	ATH_MSG_VERBOSE( nReceivedSPSCT << " SpacePoints successfully added to Container !" );
+      }
+    }
+
+    m_hist_n->Fill(nTruthSP);
+
+    //!!!!!!!!!!!!!!!!!!!!!!!!
+ std::cout<<"!!!!!!!!!!!  N_1_0 = "<<N_1_0<<",  N_1_1 = "<<N_1_1<<",  N_1_2 = "<<N_1_2<<",  N_2_0 = "<<N_2_0<<",  N_2_1 = "<<N_2_1<<",  N_2_2 = "<<N_2_2<<std::endl;
+ std::cout<<"!!!!!!!!!!!  match_N_1_0 = "<<match_N_1_0<<",  match_N_1_1 = "<<match_N_1_1<<",  match_N_1_2 = "<<match_N_1_2<<",  match_N_2_0 = "<<match_N_2_0<<",  match_N_2_1 = "<<match_N_2_1<<",  match_N_2_2 = "<<match_N_2_2<<std::endl;
+  if ( (N_1_0==1 && match_N_1_0==1) && (N_1_1==1 && match_N_1_1==1) && (N_1_2==1 && match_N_1_2==1) && (N_2_0==1 && match_N_2_0==1) && (N_2_1==1 && match_N_2_1==1) && (N_2_2==1 && match_N_2_2==1)) {
+  Acts::Vector3D pos1_0(0., 0., 0.);
+  Acts::Vector3D pos1_1(0., 0., 0.);
+  Acts::Vector3D pos1_2(0., 0., 0.);
+  Acts::Vector3D pos2_0(0., 0., 0.);
+  Acts::Vector3D pos2_1(0., 0., 0.);
+  Acts::Vector3D pos2_2(0., 0., 0.);
 
-  ATH_MSG_DEBUG( "SCT spacepoint container found: " << sct_spcontainer->size() << " collections" );
   SpacePointContainer::const_iterator it = sct_spcontainer->begin();
   SpacePointContainer::const_iterator itend = sct_spcontainer->end();
 
-  //use 0 as the hash
-  IdentifierHash idHash(0);
-  Identifier id(0);
-  auto spCollection = std::make_unique<SpacePointCollection>(idHash);
-  spCollection->setIdentifier(id);
-  spCollection->reserve(100);
-  SpacePointContainer::IDC_WriteHandle lock = seedContainer_SCT->getWriteHandle(idHash);
-
-  int nTruthSP=0;
-  ATH_MSG_DEBUG( "Start iteration of spacepoint collections"  );
   for (; it != itend; ++it){
-    ++m_numberOfSPCollection;
     const SpacePointCollection *colNext=&(**it);
-    int nReceivedSPSCT = colNext->size();
 
     // Create SpacePointCollection
     IdentifierHash idHash = colNext->identifyHash();
     Identifier elementID = colNext->identify();
+    int istation = m_idHelper->station(elementID);
+    int ilayer = m_idHelper->layer(elementID);
     size_t size = colNext->size();
-    ATH_MSG_DEBUG( "Spacepoint collection in iteraction: size =  " <<nReceivedSPSCT <<", IDHash = "<<idHash<<", ID = "<<elementID );
     if (size == 0){
-      ATH_MSG_VERBOSE( "Algorithm found no space points" );
-      ++m_numberOfEmptySPCollection;
+      ATH_MSG_VERBOSE( "StatisticsAlg algorithm found no space points" );
     } else {
       //In a MT environment the cache maybe filled by another thread in which case this will delete the duplicate
       SpacePointCollection::const_iterator sp_begin= colNext->begin();
       SpacePointCollection::const_iterator sp_end= colNext->end();
-      ATH_MSG_DEBUG( "Iterate the spacepoint in collection "  );
       for (; sp_begin != sp_end; ++sp_begin){
-	++m_numberOfSP;
 	const Trk::SpacePoint* sp=&(**sp_begin);
-	bool match=false;
-	//get truth hit
-	const auto identifier = sp->clusterList().first->identify();
-	int station = m_idHelper->station(identifier);
-	int plane = m_idHelper->layer(identifier);
-	int row = m_idHelper->phi_module(identifier);
-	int module = m_idHelper->eta_module(identifier);
-	int sensor = m_idHelper->side(identifier);
-	m_hist_sp_station->Fill(station);
-	m_hist_sp_plane->Fill(plane);
-	m_hist_sp_layer->Fill((station-1)*3+plane);
-	m_hist_sp_row->Fill(row);
-	m_hist_sp_module->Fill(module);
-	m_hist_sp_sensor->Fill(sensor);
-
-	ATH_MSG_DEBUG( "Spacepoint :"<<identifier  );
-        SG::ReadHandle<TrackerSimDataCollection> h_collectionMap(m_sctMap, ctx);
-	ATH_MSG_DEBUG("map size "<<h_collectionMap->size());
-	if( h_collectionMap->count(identifier) == 0)
-	{
-	  ATH_MSG_INFO("no map found w/identifier "<<identifier);
-	  ++m_numberOfNoMap;
-	  continue;
-	}
-
-	//Collection map takes identifier and returns simulation data
-	const auto& simdata = h_collectionMap->find(identifier)->second;
-	const auto& deposits = simdata.getdeposits();
-
-	//loop through deposits to find one w/ highest energy & get barcode
-	float highestDep = 0;
-	int barcode = 0;
-	for( const auto& depositPair : deposits)
-	{
-	  if( depositPair.second > highestDep)
-	  {
-	    highestDep = depositPair.second;
-	    barcode = depositPair.first->barcode();
-	    depositPair.first->print(std::cout);
-	    ATH_MSG_INFO("pdg id "<<depositPair.first->pdg_id());
-	  }
-	}
-	ATH_MSG_INFO("final barcode of: "<<barcode);
-	if(barcode%1000000 != 10001)
-	  continue;
-
-	//Helper function to get hit location information from RDO identifier
-	ATH_MSG_INFO("trying to match hit to stat/plane/row/mod/sens: "<<station<<" "<<plane<<" "<<row<<" "<<module<<" "<<sensor);
-	for (const FaserSiHit& hit : *h_siHits)
-	{
-	  ++m_numberOfHits;
-	  ATH_MSG_INFO("hit w/vals "<<hit.getStation()<<" "<<hit.getPlane()<<" "<<hit.getRow()<<" "<<hit.getModule()<<" "<<hit.getSensor()<<" barcode: "<<hit.trackNumber());
-	  //set of conditions to confirm looking at same particle in same place for SiHit as RDO
-	  if(hit.getStation() == station 
-	      && hit.getPlane() == plane
-	      && hit.getRow() == row
-	      && hit.getModule() == module
-	      && hit.getSensor() == sensor
-	      && hit.trackNumber() == barcode)
-	  {
-	    ++m_numberOfMatchSP;
-	    ATH_MSG_INFO("matched particle and plotting w/ barcode "<<barcode);
-	    match=true;
-	  }
-	}
-//	//
-//
-	if(!match)
-	  continue;
-//
-	++m_numberOfFills;
-	++nTruthSP;
-// fails, don't know why
-//	spCollection->push_back(const_cast<TrackerSpacePoint*>(sp));
-
-	m_hist_r->Fill(sp->r());
-	m_hist_eta->Fill(sp->eta());
-	m_hist_phi->Fill(sp->phi());
 	Amg::Vector3D gloPos=sp->globalPosition();
-	m_hist_x->Fill(gloPos.x());
-	m_hist_y->Fill(gloPos.y());
-	m_hist_z->Fill(gloPos.z());
-	m_hist_strip->Fill(m_idHelper->strip(elementID));
-	m_hist_station->Fill(m_idHelper->station(elementID));
-	m_hist_layer->Fill(m_idHelper->layer(elementID));
-	m_hist_x_z->Fill(gloPos.x(),gloPos.z());
-	m_hist_y_z->Fill(gloPos.y(),gloPos.z());
-	int ilayer=m_idHelper->layer(elementID);
-	int istation=m_idHelper->station(elementID);
-	if ( ((istation-1)*3+ilayer) == 0 ) m_hist_x_y_plane0->Fill(gloPos.x(),gloPos.y());
-	if ( ((istation-1)*3+ilayer) == 1 ) m_hist_x_y_plane1->Fill(gloPos.x(),gloPos.y());
-	if ( ((istation-1)*3+ilayer) == 2 ) m_hist_x_y_plane2->Fill(gloPos.x(),gloPos.y());
-	if ( ((istation-1)*3+ilayer) == 3 ) m_hist_x_y_plane3->Fill(gloPos.x(),gloPos.y());
-	if ( ((istation-1)*3+ilayer) == 4 ) m_hist_x_y_plane4->Fill(gloPos.x(),gloPos.y());
-	if ( ((istation-1)*3+ilayer) == 5 ) m_hist_x_y_plane5->Fill(gloPos.x(),gloPos.y());
-	if ( ((istation-1)*3+ilayer) == 6 ) m_hist_x_y_plane6->Fill(gloPos.x(),gloPos.y());
-	if ( ((istation-1)*3+ilayer) == 7 ) m_hist_x_y_plane7->Fill(gloPos.x(),gloPos.y());
-	if ( ((istation-1)*3+ilayer) == 8 ) m_hist_x_y_plane8->Fill(gloPos.x(),gloPos.y());
+	if ( ((istation-1)*3+ilayer) == 0 ) pos1_0 = Acts::Vector3D(gloPos.x(), gloPos.y(), gloPos.z());
+	if ( ((istation-1)*3+ilayer) == 1 ) pos1_1 = Acts::Vector3D(gloPos.x(), gloPos.y(), gloPos.z());
+	if ( ((istation-1)*3+ilayer) == 2 ) pos1_2 = Acts::Vector3D(gloPos.x(), gloPos.y(), gloPos.z());
+	if ( ((istation-1)*3+ilayer) == 3 ) pos2_0 = Acts::Vector3D(gloPos.x(), gloPos.y(), gloPos.z());
+	if ( ((istation-1)*3+ilayer) == 4 ) pos2_1 = Acts::Vector3D(gloPos.x(), gloPos.y(), gloPos.z());
+	if ( ((istation-1)*3+ilayer) == 5 ) pos2_2 = Acts::Vector3D(gloPos.x(), gloPos.y(), gloPos.z());
       }
-      ATH_MSG_VERBOSE( size << " SpacePoints successfully added to Container !" );
     }
   }
+	
+  std::cout<<"!!!!!!!!!!!  pos1_0 = ("<<pos1_0.x()<<", "<<pos1_0.y()<<", "<<pos1_0.z()<<") "<<std::endl; 
+  std::cout<<"!!!!!!!!!!!  pos1_1 = ("<<pos1_1.x()<<", "<<pos1_1.y()<<", "<<pos1_1.z()<<") "<<std::endl;
+  std::cout<<"!!!!!!!!!!!  pos1_2 = ("<<pos1_2.x()<<", "<<pos1_2.y()<<", "<<pos1_2.z()<<") "<<std::endl;
+  std::cout<<"!!!!!!!!!!!  pos2_0 = ("<<pos2_0.x()<<", "<<pos2_0.y()<<", "<<pos2_0.z()<<") "<<std::endl; 
+  std::cout<<"!!!!!!!!!!!  pos2_1 = ("<<pos2_1.x()<<", "<<pos2_1.y()<<", "<<pos2_1.z()<<") "<<std::endl;
+  std::cout<<"!!!!!!!!!!!  pos2_2 = ("<<pos2_2.x()<<", "<<pos2_2.y()<<", "<<pos2_2.z()<<") "<<std::endl;
+
+  double charge = 1;
+  double B = 0.57;
+  // const Acts::Vector3D pos = pos1_0;
+  /*
+  Acts::Vector3D d1 = pos1_2 - pos1_0;
+  Acts::Vector3D d2 = pos2_2 - pos2_0;
+  */
+
+  // the least square of three space pionts
+  // Note: when z2 = (z1 + z3)/2 , the slope is the same as (pos1_2 - pos1_0)
+  // calculate the averages
+  double Ax1 = (pos1_0.x() + pos1_1.x() +pos1_2.x()) / 3;
+  double Ay1 = (pos1_0.y() + pos1_1.y() +pos1_2.y()) / 3;
+  double Az1 = (pos1_0.z() + pos1_1.z() +pos1_2.z()) / 3;
+  // calculate the sums
+  double Sxz1 = pos1_0.x()*pos1_0.z() + pos1_1.x()*pos1_1.z() + pos1_2.x()*pos1_2.z();
+  double Syz1 = pos1_0.y()*pos1_0.z() + pos1_1.y()*pos1_1.z() + pos1_2.y()*pos1_2.z();
+  double Szz1 = pos1_0.z()*pos1_0.z() + pos1_1.z()*pos1_1.z() + pos1_2.z()*pos1_2.z();
+  // calculate the slope
+  double kxz1 = (Sxz1 - 3*Ax1*Az1) / (Szz1 - 3*Az1*Az1);
+  double kyz1 = (Syz1 - 3*Ay1*Az1) / (Szz1 - 3*Az1*Az1);
+  Acts::Vector3D d1( kxz1, kyz1, 1.0);
+  // calculate the averages
+  double Ax2 = (pos2_0.x() + pos2_1.x() +pos2_2.x()) / 3;
+  double Ay2 = (pos2_0.y() + pos2_1.y() +pos2_2.y()) / 3;
+  double Az2 = (pos2_0.z() + pos2_1.z() +pos2_2.z()) / 3;
+  // calculate the sums
+  double Sxz2 = pos2_0.x()*pos2_0.z() + pos2_1.x()*pos2_1.z() + pos2_2.x()*pos2_2.z();
+  double Syz2 = pos2_0.y()*pos2_0.z() + pos2_1.y()*pos2_1.z() + pos2_2.y()*pos2_2.z();
+  double Szz2 = pos2_0.z()*pos2_0.z() + pos2_1.z()*pos2_1.z() + pos2_2.z()*pos2_2.z();
+  // calculate the slope
+  double kxz2 = (Sxz2 - 3*Ax2*Az2) / (Szz2 - 3*Az2*Az2);
+  double kyz2 = (Syz2 - 3*Ay2*Az2) / (Szz2 - 3*Az2*Az2);
+  Acts::Vector3D d2( kxz2, kyz2, 1.0);
+  //
 
-	m_hist_n->Fill(nTruthSP);
-  StatusCode sc= lock.addOrDelete( std::move(spCollection) );
-  if (sc.isFailure()){
-    ATH_MSG_ERROR( "Failed to add SpacePoints to container" );
-    return StatusCode::RECOVERABLE;
+  // the direction of momentum in the first station
+  Acts::Vector3D direct1 = d1.normalized();
+  std::cout<<"!!!!!!!!!!!  direct1 = ("<<direct1.x()<<", "<<direct1.y()<<", "<<direct1.z()<<") "<<std::endl; 
+  // the direction of momentum in the second station
+  Acts::Vector3D direct2 = d2.normalized();
+  std::cout<<"!!!!!!!!!!!  direct2 = ("<<direct2.x()<<", "<<direct2.y()<<", "<<direct2.z()<<") "<<std::endl; 
+  // the vector pointing from the center of circle to the particle at layer 2 in Y-Z plane
+  double R1_z = charge * direct1.y() / std::sqrt(direct1.y()*direct1.y() + direct1.z()*direct1.z());
+  double R1_y = -charge * direct1.z() / std::sqrt(direct1.y()*direct1.y() + direct1.z()*direct1.z());
+  std::cout<<"!!!!!!!!!!!  (R1_y, R1_z) = ("<<R1_y<<", "<<R1_z<<") "<<std::endl; 
+  // the vector pointing from the center of circle to the particle at layer 3 in Y-Z plane
+  double R2_z = charge * direct2.y() / std::sqrt(direct2.y()*direct2.y() + direct2.z()*direct2.z());
+  double R2_y = -charge * direct2.z() / std::sqrt(direct2.y()*direct2.y() + direct2.z()*direct2.z());
+  std::cout<<"!!!!!!!!!!!  (R2_y, R2_z) = ("<<R2_y<<", "<<R2_z<<") "<<std::endl; 
+  // the norm of radius
+  double R = (pos2_0.z() - pos1_2.z()) / (R2_z - R1_z);
+  std::cout<<"!!!!!!!!!!!  R = "<<R<<std::endl; 
+  // the norm of momentum in Y-Z plane
+  double p_yz = 0.3*B*R / 1000.0;  // R(mm), p(GeV), B(T)
+  double p_z = p_yz * direct1.z() / std::sqrt(direct1.y()*direct1.y() + direct1.z()*direct1.z());
+  double p_y = p_yz * direct1.y() / std::sqrt(direct1.y()*direct1.y() + direct1.z()*direct1.z());
+  double p_x = direct1.x() * p_z / direct1.z();
+  // total momentum at the layer 0
+  const Acts::Vector3D mom(p_x, p_y, p_z);
+  double p = mom.norm();
+  std::cout<<"!!!!!!!!!!!  InitTrack momentum on layer 0: ( "<<mom.x()*1000<<",  "<<mom.y()*1000<<",  "<<mom.z()*1000<<",  "<<p*1000<<")  "<<std::endl;
+  std::cout<<"!!!!!!!!!!!  truth momentum: ( "<<truthmom.px()<<",  "<<truthmom.py()<<",  "<<truthmom.pz()<<",  "<<truthmom.m()<<" )  "<<std::endl;
+
+  if ((p_x*1000 - truthmom.px()) / std::fabs(truthmom.px()) < -10) m_hist_InitReso_px->Fill( -9.5 );
+    else if ((p_x*1000 - truthmom.px()) / std::fabs(truthmom.px()) > 10) m_hist_InitReso_px->Fill( 9.5 );
+    else m_hist_InitReso_px->Fill( (p_x*1000 - truthmom.px()) / std::fabs(truthmom.px())  );
+
+  if ((p_y*1000 - truthmom.py()) / std::fabs(truthmom.py()) < -10) m_hist_InitReso_py->Fill( -9.5 );
+    else if ((p_y*1000 - truthmom.py()) / std::fabs(truthmom.py()) > 10) m_hist_InitReso_py->Fill( 9.5 );
+    else m_hist_InitReso_py->Fill( (p_y*1000 - truthmom.py()) / std::fabs(truthmom.py())  );
+
+  if ((p_z*1000 - truthmom.pz()) / std::fabs(truthmom.pz()) < -10) m_hist_InitReso_pz->Fill( -9.5 );
+    else if ((p_z*1000 - truthmom.pz()) / std::fabs(truthmom.pz())>10) m_hist_InitReso_pz->Fill( 9.5 );
+    else m_hist_InitReso_pz->Fill( (p_z*1000 - truthmom.pz()) / std::fabs(truthmom.pz())  );
+
+ /*
+  // build the track covariance matrix using the smearing sigmas
+  double sigmaU = 20_um;
+  double sigmaV = 20_um;
+  double sigmaPhi = 1_degree;
+  double sigmaTheta = 1_degree;
+  double sigmaQOverP = 0.01*p / (p*p);
+  double sigmaT0 = 1_ns;
+  Acts::BoundSymMatrix cov = Acts::BoundSymMatrix::Zero();
+  cov(Acts::eLOC_0, Acts::eLOC_0) = sigmaU * sigmaU;
+  cov(Acts::eLOC_1, Acts::eLOC_1) = sigmaV * sigmaV;
+  cov(Acts::ePHI, Acts::ePHI) = sigmaPhi * sigmaPhi;
+  cov(Acts::eTHETA, Acts::eTHETA) = sigmaTheta * sigmaTheta;
+  cov(Acts::eQOP, Acts::eQOP) = sigmaQOverP * sigmaQOverP;
+  cov(Acts::eT, Acts::eT) = sigmaT0 * sigmaT0;
+
+  double time =0;
+  Acts::CurvilinearParameters InitTrackParam(std::make_optional(std::move(cov)), pos, mom, charge, time);
+  */
+  }
+    //!!!!!!!!!!!!!!!!!!!!!!
+    
+    return StatusCode::SUCCESS;
   }
 
-  return StatusCode::SUCCESS;
-}
-
-//---------------------------------------------------------------------------
-StatusCode TruthSeededTrackFinder::finalize()
-{
-  ATH_MSG_INFO( "Finalizing" );
-  ATH_MSG_INFO( m_numberOfEvents << " events processed" );
-  ATH_MSG_INFO( m_numberOfSPCollection << " spacepoint collections processed" );
-  ATH_MSG_INFO( m_numberOfEmptySPCollection<< " spacepoint collections empty" );
-  ATH_MSG_INFO( m_numberOfSP<< " sct SP collections processed" );
-  ATH_MSG_INFO( m_numberOfNoMap<< " not maped spacepoint" );
-  ATH_MSG_INFO( m_numberOfHits<< " sim hits" );
-  ATH_MSG_INFO( m_numberOfMatchSP<< " matched spacepoint" );
-  ATH_MSG_INFO( m_numberOfFills<< " spacepoint saved" );
-  return StatusCode::SUCCESS;
-}
+  //---------------------------------------------------------------------------
+  StatusCode TruthSeededTrackFinder::finalize()
+  {
+    ATH_MSG_INFO( "Finalizing" );
+    ATH_MSG_INFO( m_numberOfEvents << " events processed" );
+    ATH_MSG_INFO( m_numberOfSPCollection << " spacepoint collections processed" );
+    ATH_MSG_INFO( m_numberOfEmptySPCollection<< " spacepoint collections empty" );
+    ATH_MSG_INFO( m_numberOfSP<< " sct SP collections processed" );
+    ATH_MSG_INFO( m_numberOfNoMap<< " not maped spacepoint" );
+    ATH_MSG_INFO( m_numberOfHits<< " sim hits" );
+    ATH_MSG_INFO( m_numberOfMatchSP<< " matched spacepoint" );
+    ATH_MSG_INFO( m_numberOfFills<< " spacepoint saved" );
+    return StatusCode::SUCCESS;
+  }
 
-//--------------------------------------------------------------------------
+  //--------------------------------------------------------------------------
 
 }
diff --git a/Tracker/TrackerRecAlgs/TruthSeededTrackFinder/src/TruthSeededTrackFinder.h b/Tracker/TrackerRecAlgs/TruthSeededTrackFinder/src/TruthSeededTrackFinder.h
index f115049cff7c963a43d3150faaa45c17819b74aa..1e91539955a063585de8b823a30a5d28081acee4 100755
--- a/Tracker/TrackerRecAlgs/TruthSeededTrackFinder/src/TruthSeededTrackFinder.h
+++ b/Tracker/TrackerRecAlgs/TruthSeededTrackFinder/src/TruthSeededTrackFinder.h
@@ -18,6 +18,7 @@
 #include "TrackerReadoutGeometry/SiDetectorElementCollection.h"
 #include "TrkSpacePoint/SpacePoint.h"
 #include "TrkSpacePoint/SpacePointContainer.h"
+#include "TrackerSpacePoint/SpacePointForSeedCollection.h"
 #include "TrkSpacePoint/SpacePointOverlapCollection.h"
 #include "TrackerSimEvent/FaserSiHitCollection.h"
 #include "TrackerRawData/FaserSCT_RDO_Container.h"
@@ -26,6 +27,7 @@
 
 #include "GaudiKernel/ServiceHandle.h"
 #include "GaudiKernel/ITHistSvc.h"
+#include "GaudiKernel/ToolHandle.h"
 
 #include <string>
 #include <vector>
@@ -63,7 +65,7 @@ class TruthSeededTrackFinder:public AthReentrantAlgorithm {
     TruthSeededTrackFinder &operator=(const TruthSeededTrackFinder&) = delete;
     SG::ReadHandleKey<SpacePointContainer>  m_Sct_spcontainerKey{this, "SpacePointsSCTName", "SCT spContainer"};
 
-    SG::WriteHandleKey<SpacePointContainer>  m_seed_spcontainerKey{this, "SpacePointsSeedsName", "TrackerSpacePointContainer", "output seeds"};
+    SG::WriteHandleKey<SpacePointForSeedCollection>  m_seed_spcontainerKey{this, "FaserSpacePointsSeedsName", "SpacePointForSeedCollection", "SpacePointForSeedCollection"};
 
     SG::ReadCondHandleKey<TrackerDD::SiDetectorElementCollection> m_SCTDetEleCollKey{this, "SCTDetEleCollKey", "SCT_DetectorElementCollection", "Key of SiDetectorElementCollection for SCT"};
 
@@ -109,9 +111,13 @@ class TruthSeededTrackFinder:public AthReentrantAlgorithm {
     TH1* m_hist_sp_plane;
     TH1* m_hist_sp_layer;
     TH1* m_hist_sp_station;
+    //!!!!!!!!!!!!!!!!!!!!!
+    TH1* m_hist_InitReso_px;
+    TH1* m_hist_InitReso_py;
+    TH1* m_hist_InitReso_pz;
+    //!!!!!!!!!!!!!!!!!!!!!
     ServiceHandle<ITHistSvc>  m_thistSvc;
 
-
 };
 
 }
diff --git a/Tracker/TrackerRecAlgs/TruthSeededTrackFinder/src/components/TruthSeededTrackFinder_entries.cxx b/Tracker/TrackerRecAlgs/TruthSeededTrackFinder/src/components/TruthSeededTrackFinder_entries.cxx
index de277e191deea1a934510c7f795cd66458ae0bb5..1dc261b788e2324993347798265ecc4a28471db2 100644
--- a/Tracker/TrackerRecAlgs/TruthSeededTrackFinder/src/components/TruthSeededTrackFinder_entries.cxx
+++ b/Tracker/TrackerRecAlgs/TruthSeededTrackFinder/src/components/TruthSeededTrackFinder_entries.cxx
@@ -1,4 +1,3 @@
 #include "../TruthSeededTrackFinder.h"
 
 DECLARE_COMPONENT( Tracker::TruthSeededTrackFinder )
-
diff --git a/Tracker/TrackerRecAlgs/TruthSeededTrackFinder/test/TruthSeededTrackFinderDbg.py b/Tracker/TrackerRecAlgs/TruthSeededTrackFinder/test/TruthSeededTrackFinderDbg.py
index 7e96fca34691af58f9406d5ee8319684dd1c7f11..eab4d204cdca384e1bb4e757fde40228f6c8b067 100644
--- a/Tracker/TrackerRecAlgs/TruthSeededTrackFinder/test/TruthSeededTrackFinderDbg.py
+++ b/Tracker/TrackerRecAlgs/TruthSeededTrackFinder/test/TruthSeededTrackFinderDbg.py
@@ -28,6 +28,7 @@ ConfigFlags.Input.Files = ['my.RDO.pool.root']
 ConfigFlags.Output.ESDFileName = "mySeeds.ESD.pool.root"
 ConfigFlags.IOVDb.GlobalTag = "OFLCOND-XXXX-XXX-XX"
 ConfigFlags.GeoModel.Align.Dynamic = False
+#ConfigFlags.Concurrency.NumThreads = 1
 ConfigFlags.Beam.NumberOfCollisions = 0.
 
 ConfigFlags.lock()
@@ -48,15 +49,15 @@ acc.merge(TruthSeededTrackFinderCfg(ConfigFlags))
 #acc.merge(MergeRecoTimingObjCfg(ConfigFlags))
 
 # Dump config
-# logging.getLogger('forcomps').setLevel(VERBOSE)
-# acc.foreach_component("*").OutputLevel = VERBOSE
-# acc.foreach_component("*ClassID*").OutputLevel = INFO
+logging.getLogger('forcomps').setLevel(VERBOSE)
+acc.foreach_component("*").OutputLevel = VERBOSE
+acc.foreach_component("*ClassID*").OutputLevel = INFO
 # acc.getCondAlgo("FaserSCT_AlignCondAlg").OutputLevel = VERBOSE
 # acc.getCondAlgo("FaserSCT_DetectorElementCondAlg").OutputLevel = VERBOSE
-# acc.getService("StoreGateSvc").Dump = True
-# acc.getService("ConditionStore").Dump = True
-# acc.printConfig(withDetails=True)
-# ConfigFlags.dump()
+acc.getService("StoreGateSvc").Dump = True
+acc.getService("ConditionStore").Dump = True
+acc.printConfig(withDetails=True)
+ConfigFlags.dump()
 
 # Execute and finish
 sc = acc.run(maxEvents=-1)
diff --git a/Tracker/TrackerRecEvent/TrackerSpacePoint/TrackerSpacePoint/SpacePointForSeed.h b/Tracker/TrackerRecEvent/TrackerSpacePoint/TrackerSpacePoint/SpacePointForSeed.h
new file mode 100644
index 0000000000000000000000000000000000000000..9b3f7fcf67b830190245546fe0923e19b08e4b61
--- /dev/null
+++ b/Tracker/TrackerRecEvent/TrackerSpacePoint/TrackerSpacePoint/SpacePointForSeed.h
@@ -0,0 +1,24 @@
+#ifndef SpacePointForSeed_h
+#define SpacePointForSeed_h
+
+#include "TrkSpacePoint/SpacePoint.h"
+
+namespace Trk{
+  class SpacePoint;
+}
+
+class  SpacePointForSeed{
+  public:
+    SpacePointForSeed() = delete;
+    SpacePointForSeed(const Trk::SpacePoint* sp) : m_spacepoint(sp) {};
+    ~SpacePointForSeed() = default;
+    const Trk::SpacePoint* SpacePoint() const {
+      return m_spacepoint;
+    }
+
+  private:
+    const Trk::SpacePoint * m_spacepoint;
+};
+
+#endif
+
diff --git a/Tracker/TrackerRecEvent/TrackerSpacePoint/TrackerSpacePoint/SpacePointForSeedCollection.h b/Tracker/TrackerRecEvent/TrackerSpacePoint/TrackerSpacePoint/SpacePointForSeedCollection.h
new file mode 100755
index 0000000000000000000000000000000000000000..625b700ab5a9ed22a74f15c880ed1f7bc3035bb9
--- /dev/null
+++ b/Tracker/TrackerRecEvent/TrackerSpacePoint/TrackerSpacePoint/SpacePointForSeedCollection.h
@@ -0,0 +1,18 @@
+
+#ifndef SPACEPOINTFORSEED_SPACEPOINTCOLLECTION_H
+#define SPACEPOINTFORSEED_SPACEPOINTCOLLECTION_H
+
+// Base classes
+#include "AthContainers/DataVector.h"
+#include "GaudiKernel/DataObject.h"
+//class SpacePoint;
+#include "TrackerSpacePoint/SpacePointForSeed.h"
+
+
+
+typedef DataVector<SpacePointForSeed> SpacePointForSeedCollection;
+
+#include "AthenaKernel/CLASS_DEF.h"
+CLASS_DEF(SpacePointForSeedCollection,1123314789,1)
+
+#endif // TRKSPACEPOINT_SPACEPOINTCOLLECTION_H
diff --git a/Tracker/TrackerRecEvent/TrackerSpacePoint/src/SpacePointForSeed.cxx b/Tracker/TrackerRecEvent/TrackerSpacePoint/src/SpacePointForSeed.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..0dee96b188712436c3247af1be051e20fe7836da
--- /dev/null
+++ b/Tracker/TrackerRecEvent/TrackerSpacePoint/src/SpacePointForSeed.cxx
@@ -0,0 +1,6 @@
+//#include "TrackerSpacePoint/SpacePointForSeed.h"
+//SpacePointForSeed::SpacePointForSeed(const Trk::SpacePoint* sp): m_spacepoint( sp) {}
+//SpacePointForSeed::~SpacePointForSeed() {}
+//const Trk::SpacePoint* SpacePointForSeed::SpacePoint() const {
+//    return m_spacepoint;
+//}
\ No newline at end of file
diff --git a/Tracker/TrackerRecTools/TruthSeededTrackFinderTool/CMakeLists.txt b/Tracker/TrackerRecTools/TruthSeededTrackFinderTool/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..6b02af22a8306bfe2605c1c4edc49cd0ac536abc
--- /dev/null
+++ b/Tracker/TrackerRecTools/TruthSeededTrackFinderTool/CMakeLists.txt
@@ -0,0 +1,37 @@
+################################################################################
+# Package: FaserSiSpacePointTool
+################################################################################
+
+# Declare the package name:
+atlas_subdir( TruthSeededTrackFinderTool)
+
+# Declare the package's dependencies:
+atlas_depends_on_subdirs( PUBLIC
+                          Control/AthenaBaseComps
+                          Control/AthenaKernel
+                          DetectorDescription/GeoPrimitives
+			              Tracker/TrackerRecEvent/TrackerPrepRawData
+                          DetectorDescription/Identifier
+                          PRIVATE
+                          GaudiKernel
+			              Tracker/TrackerDetDescr/TrackerReadoutGeometry
+			              Tracker/TrackerDetDescr/TrackerIdentifier
+                          Tracker/TrackerRecEvent/TrackerSpacePoint
+                        )
+
+# External dependencies:
+find_package( Eigen )
+
+# Component(s) in the package:
+atlas_add_library( TruthSeededTrackFinderToolLib
+                   TruthSeededTrackFinderTool/*.h src/*.cxx src/*.h
+		   PUBLIC_HEADERS TruthSeededTrackFinderTool
+                   INCLUDE_DIRS ${EIGEN_INCLUDE_DIRS}
+                   LINK_LIBRARIES ${EIGEN_LIBRARIES} AthenaBaseComps AthenaKernel GeoPrimitives TrackerPrepRawData
+                   PRIVATE_LINK_LIBRARIES GaudiKernel TrackerIdentifier TrackerReadoutGeometry TrackerSpacePoint )
+
+atlas_add_component( TruthSeededTrackFinderTool
+                     src/components/*.cxx 
+                     INCLUDE_DIRS ${EIGEN_INCLUDE_DIRS}
+		     LINK_LIBRARIES ${EIGEN_LIBRARIES} AthenaBaseComps AthenaKernel GeoPrimitives TrackerPrepRawData GaudiKernel TrackerIdentifier TrackerReadoutGeometry TrackerSpacePoint TruthSeededTrackFinderToolLib )
+
diff --git a/Tracker/TrackerRecTools/TruthSeededTrackFinderTool/TruthSeededTrackFinderTool/TruthSeededTrackFinderTool.h b/Tracker/TrackerRecTools/TruthSeededTrackFinderTool/TruthSeededTrackFinderTool/TruthSeededTrackFinderTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..e08e5b1fa429f3bc2018ed7f10bc17db3e222934
--- /dev/null
+++ b/Tracker/TrackerRecTools/TruthSeededTrackFinderTool/TruthSeededTrackFinderTool/TruthSeededTrackFinderTool.h
@@ -0,0 +1,57 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TruthSeededTrackFinderTool_H
+#define TruthSeededTrackFinderTool_H
+
+#include "AthenaBaseComps/AthAlgTool.h"
+
+#include "AthenaKernel/SlotSpecificObj.h"
+#include "GeoPrimitives/GeoPrimitives.h"
+#include "TrackerPrepRawData/FaserSCT_ClusterCollection.h"
+#include "TrkSpacePoint/SpacePoint.h"
+
+#include <mutex>
+#include <string>
+
+class SpacePointCollection;
+class SpacePointOverlapCollection;
+namespace Tracker { 
+  class TrackerCluster;
+}
+
+
+namespace Tracker
+{
+
+  class TruthSeededTrackFinderTool : public AthAlgTool {
+
+  public:
+    /// Constructor 
+    TruthSeededTrackFinderTool(const std::string& type, const std::string& name, const IInterface* parent);
+
+    /// Default destructor
+    virtual ~TruthSeededTrackFinderTool() = default;
+
+    /// Return interfaceID
+    static const InterfaceID& interfaceID();
+
+    /// Initialize
+    virtual StatusCode initialize() override;
+
+    /// Finalize
+    virtual StatusCode finalize() override;
+
+
+    /// Convert clusters to space points: SCT_Clusters -> SCT_SpacePoints
+    void fillSCT_SpacePointCollection(const SpacePointCollection* clusters1,
+                                      SpacePointCollection* clusters2) const;
+
+
+  private:
+    /// @name Cut parameters
+    //@{
+  };
+}
+#endif //TrackerSpacePointMakerTool_H
diff --git a/Tracker/TrackerRecTools/TruthSeededTrackFinderTool/src/TruthSeededTrackFinderTool.cxx b/Tracker/TrackerRecTools/TruthSeededTrackFinderTool/src/TruthSeededTrackFinderTool.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..075440a4b066e55a032d759f8bba4f6dd43eda94
--- /dev/null
+++ b/Tracker/TrackerRecTools/TruthSeededTrackFinderTool/src/TruthSeededTrackFinderTool.cxx
@@ -0,0 +1,56 @@
+/*
+   Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+   */
+
+#include "TruthSeededTrackFinderTool/TruthSeededTrackFinderTool.h"
+
+// Cluster and space point collections
+#include "TrkSpacePoint/SpacePointCollection.h"
+#include "TrkSpacePoint/SpacePointOverlapCollection.h"
+
+#include "TrackerSpacePoint/FaserSCT_SpacePoint.h"
+
+namespace Tracker
+{
+
+static const InterfaceID IID_ITruthSeededTrackFinderTool
+("TruthSeededTrackFinderTool", 99490493, 0);
+
+const InterfaceID& TruthSeededTrackFinderTool::interfaceID() { 
+  return IID_ITruthSeededTrackFinderTool; 
+}
+
+// Constructor with parameters:
+TruthSeededTrackFinderTool::TruthSeededTrackFinderTool(const std::string& type,
+    const std::string& name,
+    const IInterface* parent) :
+  AthAlgTool(type, name, parent) {
+    declareInterface< TruthSeededTrackFinderTool>(this);
+  }
+//--------------------------------------------------------------------------
+StatusCode TruthSeededTrackFinderTool::initialize()  {
+  // Get the SCT Helper
+  return StatusCode::SUCCESS;
+}
+//--------------------------------------------------------------------------
+StatusCode TruthSeededTrackFinderTool::finalize() {
+  return StatusCode::SUCCESS;
+}
+
+//--------------------------------------------------------------------------
+void TruthSeededTrackFinderTool::fillSCT_SpacePointCollection(const SpacePointCollection* clusters1, 
+    SpacePointCollection* clusters2
+    ) const {
+  SpacePointCollection::const_iterator clusters1Next = clusters1->begin();
+  SpacePointCollection::const_iterator clusters1Finish = clusters1->end();
+  
+  for (; clusters1Next!= clusters1Finish; ++clusters1Next){
+    const Trk::SpacePoint* sp=&(**clusters1Finish);
+    clusters2->push_back(const_cast<Trk::SpacePoint*>(sp));
+  }
+
+
+}
+
+
+}
diff --git a/Tracker/TrackerRecTools/TruthSeededTrackFinderTool/src/components/TruthSeededTrackFinderTool_entries.cxx b/Tracker/TrackerRecTools/TruthSeededTrackFinderTool/src/components/TruthSeededTrackFinderTool_entries.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..ec655e68e07bd6c8ef8cd05965e2971c1f98e539
--- /dev/null
+++ b/Tracker/TrackerRecTools/TruthSeededTrackFinderTool/src/components/TruthSeededTrackFinderTool_entries.cxx
@@ -0,0 +1,4 @@
+#include "TruthSeededTrackFinderTool/TruthSeededTrackFinderTool.h"
+
+DECLARE_COMPONENT( Tracker::TruthSeededTrackFinderTool )
+
diff --git a/Tracking/Acts/ActsInterop/ActsInterop/IdentityHelper.h b/Tracking/Acts/ActsInterop/ActsInterop/IdentityHelper.h
new file mode 100644
index 0000000000000000000000000000000000000000..6095fb5daba5a79c30c84c66bec90c1b54c84cfa
--- /dev/null
+++ b/Tracking/Acts/ActsInterop/ActsInterop/IdentityHelper.h
@@ -0,0 +1,28 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+#pragma once
+
+#include "TrackerReadoutGeometry/SiDetectorElement.h"
+#include "TrackerIdentifier/FaserSCT_ID.h"
+#include "FaserDetDescr/FaserDetectorID.h"
+
+namespace TrackerDD {
+  class SiDetectorElement;
+}
+
+class SCT_ID;
+
+class IdentityHelper {
+
+public:
+  IdentityHelper(const TrackerDD::SiDetectorElement* detElem);
+  
+private:
+  const TrackerDD::SiDetectorElement* m_elem;
+  
+  const FaserDetectorID* getSCTIDHelper() const;
+
+  
+};
diff --git a/Tracking/Acts/ActsInterop/ActsInterop/Logger.h b/Tracking/Acts/ActsInterop/ActsInterop/Logger.h
new file mode 100644
index 0000000000000000000000000000000000000000..cf0b4a4f9af8ab364220d680882d3a01d9e9bfb2
--- /dev/null
+++ b/Tracking/Acts/ActsInterop/ActsInterop/Logger.h
@@ -0,0 +1,57 @@
+/*
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+*/
+
+#pragma once
+
+#include "Acts/Utilities/Logger.hpp"
+#include "GaudiKernel/MsgStream.h"
+#include "GaudiKernel/CommonMessaging.h"
+#include "GaudiKernel/INamedInterface.h"
+
+#include <memory>
+
+#include <boost/optional.hpp>
+
+class ActsAthenaPrintPolicy final : public Acts::Logging::OutputPrintPolicy
+{
+public:
+
+  ActsAthenaPrintPolicy(std::shared_ptr<MsgStream> msg) : m_msg(msg) {}
+
+  void
+  flush(const Acts::Logging::Level& lvl, const std::ostringstream& input);
+
+private:
+  std::shared_ptr<MsgStream> m_msg;
+};
+
+class ActsAthenaFilterPolicy final : public Acts::Logging::OutputFilterPolicy {
+public:
+  ActsAthenaFilterPolicy(std::shared_ptr<MsgStream> msg) : m_msg(msg) {}
+
+  //~AthenaFilterPolicy() = default;
+
+  bool doPrint(const Acts::Logging::Level& lvl) const;
+
+private:
+  std::shared_ptr<MsgStream> m_msg;
+};
+
+
+std::unique_ptr<const Acts::Logger>
+makeActsAthenaLogger(IMessageSvc *svc, const std::string& name, 
+    int level, boost::optional<std::string> parent_name);
+
+std::unique_ptr<const Acts::Logger>
+makeActsAthenaLogger(const CommonMessagingBase* parent, const std::string& name);
+
+std::unique_ptr<const Acts::Logger>
+makeActsAthenaLogger(const CommonMessagingBase* parent, const std::string& name, 
+    boost::optional<std::string> parent_name);
+
+// problem: string literal does not play well with boost::optional
+std::unique_ptr<const Acts::Logger>
+makeActsAthenaLogger(const CommonMessagingBase* parent, const std::string& name, 
+    const std::string& parent_name); 
+
diff --git a/Tracking/Acts/ActsInterop/CMakeLists.txt b/Tracking/Acts/ActsInterop/CMakeLists.txt
new file mode 100755
index 0000000000000000000000000000000000000000..41632f128825078ea3e7bc471117c1e35caae2fa
--- /dev/null
+++ b/Tracking/Acts/ActsInterop/CMakeLists.txt
@@ -0,0 +1,21 @@
+
+# Declare the package name:
+atlas_subdir( ActsInterop )
+
+# External dependencies:
+
+find_package(Acts COMPONENTS Core)
+
+# Component(s) in the package:
+atlas_add_library( ActsInteropLib
+                   src/*.cxx
+                   PUBLIC_HEADERS ActsInterop
+                   LINK_LIBRARIES 
+                   AthenaBaseComps
+                   Identifier
+                   FaserDetDescr
+                   TrackerIdentifier 
+                   TrackerReadoutGeometry
+                   ActsCore)
+
+
diff --git a/Tracking/Acts/ActsInterop/src/IdentityHelper.cxx b/Tracking/Acts/ActsInterop/src/IdentityHelper.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..0343ebe68a6a005653628442a17ea52c689efb28
--- /dev/null
+++ b/Tracking/Acts/ActsInterop/src/IdentityHelper.cxx
@@ -0,0 +1,22 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "ActsInterop/IdentityHelper.h"
+
+#include "TrackerReadoutGeometry/SiDetectorElement.h"
+#include "TrackerIdentifier/FaserSCT_ID.h"
+#include "FaserDetDescr/FaserDetectorID.h"
+
+
+IdentityHelper::IdentityHelper(const TrackerDD::SiDetectorElement *elem)
+  : m_elem(elem)
+{}
+  
+
+const FaserDetectorID* 
+IdentityHelper::getSCTIDHelper() const
+{
+  return dynamic_cast<const FaserDetectorID*>(m_elem->getIdHelper());
+}
+
diff --git a/Tracking/Acts/ActsInterop/src/Logger.cxx b/Tracking/Acts/ActsInterop/src/Logger.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..e40f9e47943baee1e5a33f7b34d535008661285e
--- /dev/null
+++ b/Tracking/Acts/ActsInterop/src/Logger.cxx
@@ -0,0 +1,95 @@
+/*
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "ActsInterop/Logger.h"
+
+#include "GaudiKernel/INamedInterface.h"
+#include "GaudiKernel/CommonMessaging.h"
+#include "GaudiKernel/IMessageSvc.h"
+#include "GaudiKernel/MsgStream.h"
+#include "GaudiKernel/CommonMessaging.h"
+
+#include "Acts/Utilities/Logger.hpp"
+
+#include <boost/optional.hpp>
+
+#include <iostream>
+#include <string>
+
+namespace {
+  const std::array<MSG::Level, 6> athLevelVector{
+    MSG::VERBOSE, 
+    MSG::DEBUG,
+    MSG::INFO, 
+    MSG::WARNING, 
+    MSG::ERROR, 
+    MSG::FATAL
+  };
+}
+
+void
+ActsAthenaPrintPolicy::flush(const Acts::Logging::Level& lvl, const std::ostringstream& input)
+{
+  MSG::Level athLevel = athLevelVector[lvl];
+  (*m_msg) << athLevel << input.str() << endmsg;
+}
+  
+
+bool
+ActsAthenaFilterPolicy::doPrint(const Acts::Logging::Level& lvl) const 
+{
+
+  MSG::Level athLevel = athLevelVector[lvl];
+  return m_msg->level() <= athLevel;
+}
+
+
+std::unique_ptr<const Acts::Logger>
+makeActsAthenaLogger(IMessageSvc *svc, const std::string& name, int level, boost::optional<std::string> parent_name)
+{
+  using namespace Acts::Logging;
+
+  std::string full_name = name;
+  if (parent_name) {
+    full_name = *parent_name + "." + full_name;
+  }
+
+  auto msg = std::make_shared<MsgStream>(svc, full_name);
+  msg->setLevel(level);
+  auto filter = std::make_unique<ActsAthenaFilterPolicy>(msg);
+  auto print = std::make_unique<ActsAthenaPrintPolicy>(msg);
+  return std::make_unique<const Acts::Logger>(std::move(print), std::move(filter));
+}
+
+std::unique_ptr<const Acts::Logger>
+makeActsAthenaLogger(const CommonMessagingBase* parent, const std::string& name)
+{
+  // no explicit name, get from component
+  const INamedInterface *inamed = dynamic_cast<const INamedInterface*>(parent);
+  boost::optional<std::string> parent_name = boost::none;
+  // this will not prefix if parent is not named (which it should be)
+  if (inamed == nullptr) {
+    throw std::invalid_argument("parent needs to be INamedInterface");
+  }
+  parent_name = inamed->name();
+  return makeActsAthenaLogger(parent, name, parent_name);
+}
+
+std::unique_ptr<const Acts::Logger>
+makeActsAthenaLogger(const CommonMessagingBase* parent, const std::string& name, boost::optional<std::string> parent_name)
+{
+  int level = 0;
+  const INamedInterface *inamed = dynamic_cast<const INamedInterface*>(parent);
+  if (inamed != nullptr) {
+    level = parent->msg().level();
+  }
+  return makeActsAthenaLogger(parent->msgSvc().get(), name, level, parent_name);
+}
+
+std::unique_ptr<const Acts::Logger>
+makeActsAthenaLogger(const CommonMessagingBase* parent, const std::string& name, const std::string& parent_name)
+{
+  
+  return makeActsAthenaLogger(parent, name, boost::optional<std::string>(parent_name));
+}
diff --git a/Tracking/Acts/FaserActsGeometry/CMakeLists.txt b/Tracking/Acts/FaserActsGeometry/CMakeLists.txt
new file mode 100755
index 0000000000000000000000000000000000000000..260732e2f948613aecae732b06a03fc6a9a1ef6e
--- /dev/null
+++ b/Tracking/Acts/FaserActsGeometry/CMakeLists.txt
@@ -0,0 +1,85 @@
+
+# Declare the package name:
+atlas_subdir( FaserActsGeometry )
+
+# External dependencies:
+find_package( CLHEP )
+find_package( Eigen )
+find_package( Boost )
+
+find_package( Acts COMPONENTS Core )
+
+atlas_add_library( FaserActsGeometryLib 
+		   FaserActsGeometry/FaserActsGeometryContext.h
+		   FaserActsGeometry/FaserActsDetectorElement.h
+		   src/FaserActsAlignmentStore.cxx
+		   src/FaserActsDetectorElement.cxx
+		   src/FaserActsLayerBuilder.cxx
+		   src/CuboidVolumeBuilder.cxx
+		   src/util/*.cxx
+		   PUBLIC_HEADERS FaserActsGeometry
+		   INCLUDE_DIRS ${CLHEP_INCLUDE_DIRS} ${EIGEN_INCLUDE_DIRS} ${BOOST_INCLUDE_DIRS}
+		   LINK_LIBRARIES ${CLHEP_LIBRARIES} ${EIGEN_LIBRARIES} ${BOOST_LIBRARIES}
+	       	   TrackerIdentifier 
+		   TrackerReadoutGeometry
+		   ActsInteropLib
+		   FaserActsGeometryInterfacesLib
+		   AthenaKernel												                         
+		   ActsCore
+		   MagFieldInterfaces 
+		   MagFieldElements 
+		   MagFieldConditions
+		   TrackerRawData 
+		   TrackerSimData 
+		   GeneratorObjects 
+		   TrackerSimEvent 
+		   TrackerSpacePoint 
+		   TrackerIdentifier 
+		   TrackerPrepRawData
+		   TrkSpacePoint
+		  )
+
+
+# Component(s) in the package:
+atlas_add_component( FaserActsGeometry
+##src/*.cxx
+		     src/FaserActsTrackingGeometrySvc.cxx
+		     src/FaserActsTrackingGeometryTool.cxx
+                     src/FaserActsWriteTrackingGeometry.cxx
+		     src/FaserActsObjWriterTool.cxx
+		     src/FaserActsExtrapolationAlg.cxx
+		     src/FaserActsExtrapolationTool.cxx
+		     src/FaserActsPropStepRootWriterSvc.cxx
+		     src/FaserActsAlignmentCondAlg.cxx
+		     src/NominalAlignmentCondAlg.cxx
+#src/FaserActsKalmanFilterAlg.cxx
+		     src/components/*.cxx
+                     PUBLIC_HEADERS FaserActsGeometry
+                     INCLUDE_DIRS ${CLHEP_INCLUDE_DIRS} ${EIGEN_INCLUDE_DIRS} ${BOOST_INCLUDE_DIRS}
+                     LINK_LIBRARIES ${CLHEP_LIBRARIES} ${EIGEN_LIBRARIES} ${BOOST_LIBRARIES}
+		     EventInfo
+		     AthenaBaseComps
+		     GaudiKernel
+		     FaserActsGeometryLib
+		     ActsInteropLib
+		     FaserActsGeometryInterfacesLib
+                     ActsCore
+                     MagFieldInterfaces
+                     MagFieldElements
+                     MagFieldConditions
+		     TrackerRawData 
+		     TrackerSimData 
+		     GeneratorObjects 
+	  	     TrackerSimEvent 
+	   	     TrackerSpacePoint 
+	   	     TrackerIdentifier 
+	   	     TrackerPrepRawData
+	   	     TrkSpacePoint
+
+	 	   )
+
+# Install files from the package:
+atlas_install_headers( FaserActsGeometry )
+atlas_install_python_modules( python/*.py )
+atlas_install_scripts( test/*.py )
+
diff --git a/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/CuboidVolumeBuilder.h b/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/CuboidVolumeBuilder.h
new file mode 100644
index 0000000000000000000000000000000000000000..44170eb23fe9152f2786fee8e7d06ce78fee5a5b
--- /dev/null
+++ b/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/CuboidVolumeBuilder.h
@@ -0,0 +1,184 @@
+// This file is part of the Acts project.
+//
+// Copyright (C) 2018 CERN for the benefit of the Acts project
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#pragma once
+
+#include <functional>
+#include <memory>
+#include <vector>
+#include "Acts/Geometry/GeometryContext.hpp"
+#include "Acts/Geometry/ITrackingVolumeBuilder.hpp"
+#include "Acts/Utilities/Definitions.hpp"
+#include "Acts/Geometry/GenericApproachDescriptor.hpp"
+
+namespace Acts{
+
+class TrackingVolume;
+class VolumeBounds;
+class RectangleBounds;
+class ISurfaceMaterial;
+class IVolumeMaterial;
+class DetectorElementBase;
+class PlaneSurface;
+class Surface;
+
+}
+
+namespace FaserActs{
+
+/// @brief This class builds a box detector with a configurable amount of
+/// surfaces in it. The idea is to allow a quick configuration of a detector for
+/// mostly unit test applications. Therefore this class does not demand to be a
+/// universal construction factory but a raw first draft of the idea of factory
+/// that may be extended in the future.
+class CuboidVolumeBuilder : public Acts::ITrackingVolumeBuilder {
+ public:
+  /// @brief This struct stores the data for the construction of a single
+  /// PlaneSurface
+  struct SurfaceConfig {
+    // Center position
+    Acts::Vector3D position;
+    // Rotation
+    Acts::RotationMatrix3D rotation = Acts::RotationMatrix3D::Identity();
+    // Bounds
+    std::shared_ptr<const Acts::RectangleBounds> rBounds = nullptr;
+    // Attached material
+    std::shared_ptr<const Acts::ISurfaceMaterial> surMat = nullptr;
+    // Thickness
+    double thickness = 0.;
+    // Constructor function for optional detector elements
+    // Arguments are transform, rectangle bounds and thickness.
+    std::function<Acts::DetectorElementBase*(std::shared_ptr<const Acts::Transform3D>,
+                                       std::shared_ptr<const Acts::RectangleBounds>,
+                                       double)>
+        detElementConstructor;
+  };
+
+  /// @brief This struct stores the data for the construction of a PlaneLayer
+  /// that has a single PlaneSurface encapsulated or array of surfaces
+  struct LayerConfig {
+    // Configuration of the surface
+    SurfaceConfig surfaceCfg;
+    // Encapsulated surface
+    std::shared_ptr<const Acts::PlaneSurface> surface = nullptr;
+    std::vector<std::shared_ptr<const Acts::Surface>> surfaces;
+    // Boolean flag if layer is active
+    bool active = false;
+    // Bins in X direction
+    size_t binsX = 1;
+    // Bins in Y direction
+    size_t binsY = 1;
+    // The approach descriptor
+    Acts::GenericApproachDescriptor *approachDescriptor = nullptr;
+  };
+
+  /// @brief This struct stores the data for the construction of a cuboid
+  /// TrackingVolume with a given number of PlaneLayers
+  struct VolumeConfig {
+    // Center position
+    Acts::Vector3D position;
+    // Lengths in x,y,z
+    Acts::Vector3D length;
+    // Configurations of its layers
+    std::vector<LayerConfig> layerCfg;
+    // Stored layers
+    std::vector<std::shared_ptr<const Acts::Layer>> layers;
+    // Configurations of confined volumes
+    std::vector<VolumeConfig> volumeCfg;
+    // Stored confined volumes
+    std::vector<std::shared_ptr<Acts::TrackingVolume>> trackingVolumes;
+    // Name of the volume
+    std::string name = "Volume";
+    // Material
+    std::shared_ptr<const Acts::IVolumeMaterial> volumeMaterial = nullptr;
+  };
+
+  /// @brief This struct stores the configuration of the tracking geometry
+  struct Config {
+    // Center position
+    Acts::Vector3D position = Acts::Vector3D(0., 0., 0.);
+    // Length in x,y,z
+    Acts::Vector3D length = Acts::Vector3D(0., 0., 0.);
+    // Configuration of its volumes
+    std::vector<VolumeConfig> volumeCfg = {};
+  };
+
+  /// @brief Default constructor without a configuration
+  CuboidVolumeBuilder() = default;
+
+  /// @brief Constructor that sets the config
+  ///
+  /// @param [in] cfg Configuration of the detector
+  CuboidVolumeBuilder(Config& cfg) : m_cfg(cfg) {}
+
+  /// @brief Setter of the config
+  ///
+  /// @param [in] cfg Configuration that is set
+  void setConfig(Config& cfg) { m_cfg = cfg; }
+
+  /// @brief This function creates a surface with a given configuration. A
+  /// detector element is attached if the template parameter is non-void.
+  ///
+  /// @param [in] gctx the geometry context for this building
+  /// @param [in] cfg Configuration of the surface
+  ///
+  /// @return Pointer to the created surface
+  std::shared_ptr<const Acts::PlaneSurface> buildSurface(
+      const Acts::GeometryContext& gctx, const SurfaceConfig& cfg) const;
+
+  /// @brief This function creates a layer with a surface encaspulated with a
+  /// given configuration. The surface gets a detector element attached if the
+  /// template parameter is non-void.
+  ///
+  /// @param [in] gctx the geometry context for this building
+  /// @param [in, out] cfg Configuration of the layer and the surface
+  ///
+  /// @return Pointer to the created layer
+  std::shared_ptr<const Acts::Layer> buildLayer(const Acts::GeometryContext& gctx,
+                                          LayerConfig& cfg) const;
+
+  /// @brief This function creates a TrackingVolume with a configurable number
+  /// of layers and surfaces. Each surface gets a detector element attached if
+  /// the template parameter is non-void.
+  ///
+  /// @param [in] gctx the geometry context for this building
+  /// @param [in, out] cfg Configuration of the TrackingVolume
+  ///
+  /// @return Pointer to the created TrackingVolume
+  std::shared_ptr<Acts::TrackingVolume> buildVolume(const Acts::GeometryContext& gctx,
+                                              VolumeConfig& cfg) const;
+
+  /// @brief This function evaluates the minimum and maximum of the binning as
+  /// given by the configurations of the surfaces and layers. The ordering
+  /// depends on the binning value specified in the configuration of the volume.
+  ///
+  /// @param [in] gctx the geometry context for this building
+  /// @param [in] cfg Container with the given surfaces and layers
+  ///
+  /// @return Pair containing the minimum and maximum along the binning
+  /// direction
+  std::pair<double, double> binningRange(const Acts::GeometryContext& gctx,
+                                         const VolumeConfig& cfg) const;
+
+  /// @brief This function builds a world TrackingVolume based on a given
+  /// configuration
+  ///
+  /// @param [in] gctx the geometry context for this building
+  ///
+  /// @return Pointer to the created TrackingGeometry
+  std::shared_ptr<Acts::TrackingVolume> trackingVolume(
+      const Acts::GeometryContext& gctx,
+      std::shared_ptr<const Acts::TrackingVolume> /*unused*/,
+      std::shared_ptr<const Acts::VolumeBounds> /*unused*/) const override;
+
+ private:
+  /// Configuration of the world volume
+  Config m_cfg;
+};
+
+}  // namespace Acts
diff --git a/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/FASERMagneticFieldWrapper.h b/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/FASERMagneticFieldWrapper.h
new file mode 100644
index 0000000000000000000000000000000000000000..b6700c291ca5a08e0ad703f8015a4bc255568319
--- /dev/null
+++ b/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/FASERMagneticFieldWrapper.h
@@ -0,0 +1,70 @@
+/*
+   Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+   */
+
+#ifndef FASERACTSGEOMETRY_FASERMAGNETICFIELDWRAPPER_H
+#define FASERACTSGEOMETRY_FASERMAGNETICFIELDWRAPPER_H
+
+#include "GaudiKernel/PhysicalConstants.h"
+#include "MagFieldConditions/FaserFieldCacheCondObj.h"
+#include "MagFieldElements/FaserFieldCache.h"
+#include "Acts/Utilities/Definitions.hpp"
+#include "Acts/Utilities/Units.hpp"
+#include "Acts/MagneticField/MagneticFieldContext.hpp"
+
+class FASERMagneticFieldWrapper
+{
+
+
+  public:
+
+    struct Cache {
+
+      Cache(std::reference_wrapper<const Acts::MagneticFieldContext> mctx) {
+        std::any_cast<const FaserFieldCacheCondObj*>(mctx)->getInitializedCache(fieldCache);
+      }
+
+      MagField::FaserFieldCache fieldCache;
+    };
+
+
+    FASERMagneticFieldWrapper() = default;
+
+    Acts::Vector3D
+    getField(const Acts::Vector3D& pos, Cache& cache) const
+      {
+	double pos0[]{pos.x(), pos.y(), pos.z()};
+	double bfield0[]{0., 0., 0.};
+	cache.fieldCache.getField(pos0, bfield0);
+	Acts::Vector3D bfield(bfield0[0], bfield0[1], bfield0[2]);
+
+	bfield *= m_bFieldUnit; // kT -> T;
+
+	return bfield;
+      }
+
+    Acts::Vector3D
+    getFieldGradient(const Acts::Vector3D& position, Acts::ActsMatrixD<3, 3>& gradient, Cache& cache) const
+      {
+	double position0[]{position.x(), position.y(), position.z()};
+	double bfield0[]{0., 0., 0.};
+	double grad[9];
+	cache.fieldCache.getField(position0, bfield0, grad);
+	Acts::Vector3D bfield(bfield0[0], bfield0[1], bfield0[2]);
+        Acts::ActsMatrixD<3, 3> tempGrad;
+	tempGrad << grad[0], grad[1], grad[2], grad[3], grad[4], grad[5], grad[6], grad[7], grad[8]; 
+	gradient = tempGrad;
+
+	bfield *= m_bFieldUnit; // kT -> T;
+	gradient *= m_bFieldUnit;
+
+	return bfield;
+      }
+
+
+  private:
+    const double m_bFieldUnit = 1000.*Acts::UnitConstants::T;
+};
+
+
+#endif
diff --git a/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/FaserActsAlignmentCondAlg.h b/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/FaserActsAlignmentCondAlg.h
new file mode 100644
index 0000000000000000000000000000000000000000..1a1d56fb174e7c3938009043353066fa1af7e2f1
--- /dev/null
+++ b/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/FaserActsAlignmentCondAlg.h
@@ -0,0 +1,58 @@
+/*
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef FASERACTSGEOMETRY_ACTSALIGNMENTCONDALG_H
+#define FASERACTSGEOMETRY_ACTSALIGNMENTCONDALG_H
+
+// ATHENA
+#include "AthenaBaseComps/AthAlgorithm.h"
+#include "EventInfo/EventInfo.h" // ReadHandleKey wants complete type
+#include "GaudiKernel/ServiceHandle.h"
+#include "StoreGate/WriteCondHandleKey.h"
+
+// PACKAGE
+
+// STL
+#include <string>
+
+namespace TrackerDD {
+class SCT_DetectorManager;
+} 
+
+class EventInfo;
+class ICondSvc;
+class StoreGateSvc;
+class IFaserActsTrackingGeometrySvc;
+class FaserActsAlignmentStore;
+class GeoAlignableTransform;
+class FaserActsGeometryContext;
+class GeoAlignmentStore;
+
+class FaserActsAlignmentCondAlg : public AthAlgorithm {
+
+public:
+  FaserActsAlignmentCondAlg(const std::string &name, ISvcLocator *pSvcLocator);
+  virtual ~FaserActsAlignmentCondAlg();
+
+  virtual bool isClonable() const override { return true; }
+
+  virtual StatusCode initialize() override;
+  virtual StatusCode execute() override;
+  virtual StatusCode finalize() override;
+
+private:
+
+  SG::ReadCondHandleKey<GeoAlignmentStore> m_sctAlignStoreReadKey{
+      this, "SCTAlignStoreReadKey", "SCTAlignmentStore", ""};
+
+  SG::WriteCondHandleKey<FaserActsGeometryContext> m_wchk{
+      this, "FaserActsAlignmentKey", "FaserActsAlignment", "cond handle key"};
+
+  ServiceHandle<ICondSvc> m_cs;
+  ServiceHandle<IFaserActsTrackingGeometrySvc> m_trackingGeometrySvc;
+
+  const TrackerDD::SCT_DetectorManager *p_SCTManager;
+};
+
+#endif
diff --git a/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/FaserActsAlignmentStore.h b/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/FaserActsAlignmentStore.h
new file mode 100644
index 0000000000000000000000000000000000000000..5566b42c71f6dd052a939bcfa47b50c35796a811
--- /dev/null
+++ b/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/FaserActsAlignmentStore.h
@@ -0,0 +1,37 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef FASERACTSGEOMETRY_ACTSALIGNMENTSTORE_H
+#define FASERACTSGEOMETRY_ACTSALIGNMENTSTORE_H
+
+#include "GeoModelUtilities/GeoAlignmentStore.h"
+#include "GeoModelUtilities/TransformMap.h"
+#include "AthenaKernel/CLASS_DEF.h"
+#include "AthenaKernel/CondCont.h"
+
+#include "Acts/Utilities/Definitions.hpp"
+
+#include <stdexcept>
+
+class FaserActsDetectorElement;
+
+class FaserActsAlignmentStore : public GeoAlignmentStore
+{
+  public:
+    FaserActsAlignmentStore() {}
+    FaserActsAlignmentStore(const GeoAlignmentStore& gas);
+
+    void setTransform(const FaserActsDetectorElement* key, const Acts::Transform3D&);
+    const Acts::Transform3D* getTransform(const FaserActsDetectorElement* key) const;
+
+    void append(const GeoAlignmentStore& gas);
+
+  private:
+    TransformMap<FaserActsDetectorElement, Acts::Transform3D> m_transforms;
+};
+
+CLASS_DEF(FaserActsAlignmentStore, 58650257, 1)
+CONDCONT_DEF( FaserActsAlignmentStore , 124731561 );
+
+#endif
diff --git a/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/FaserActsDetectorElement.h b/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/FaserActsDetectorElement.h
new file mode 100644
index 0000000000000000000000000000000000000000..9d985df94d31f2afdad19757126114d605a06291
--- /dev/null
+++ b/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/FaserActsDetectorElement.h
@@ -0,0 +1,100 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef FASERACTSGEOMETRY_ACTSDETECTORELEMENT_H
+#define FASERACTSGEOMETRY_ACTSDETECTORELEMENT_H
+
+// ATHENA INCLUDES
+#include "TrackerIdentifier/FaserSCT_ID.h"
+#include "TrackerReadoutGeometry/SiDetectorElement.h"
+
+// ACTS
+#include "Acts/Geometry/DetectorElementBase.hpp"
+#include "Acts/Geometry/GeometryContext.hpp"
+
+// STL
+#include <mutex>
+#include <iostream>
+
+// BOOST
+#include <boost/variant.hpp>
+
+namespace Acts {
+  class SurfaceBounds;
+}
+
+class FaserActsTrackingGeometrySvc;
+class FaserActsAlignmentStore;
+
+class IdentityHelper;
+
+/// @class FaserActsDetectorElement
+///
+class FaserActsDetectorElement : public Acts::DetectorElementBase
+{
+public:
+  enum class Subdetector { SCT };
+
+  FaserActsDetectorElement(const TrackerDD::SiDetectorElement* detElem);
+
+  ///  Destructor
+  virtual ~FaserActsDetectorElement() {}
+
+  /// Identifier
+  Identifier
+  identify() const;
+
+  void
+  storeTransform(FaserActsAlignmentStore* gas) const;
+  virtual const Acts::Transform3D &
+  transform(const Acts::GeometryContext &gctx) const final override;
+
+
+  /// Return surface associated with this identifier, which should come from the
+  virtual const Acts::Surface&
+  surface() const final override;
+
+  /// Returns the thickness of the module
+  virtual double
+  thickness() const final override;
+
+  IdentityHelper identityHelper() const;
+
+ 	bool operator==(const FaserActsDetectorElement& otherElem) {
+	    return m_detElement->identify() == otherElem.identify();
+	}
+
+private:
+  
+  /// For silicon detectors it is calulated from GM, and stored. Thus the method 
+  /// is not const. The store is mutexed.
+  const Acts::Transform3D&
+  getDefaultTransformMutexed() const;
+
+  /// Detector element 
+  const TrackerDD::SiDetectorElement* m_detElement;
+  /// Boundaries of the detector element
+  std::shared_ptr<const Acts::SurfaceBounds> m_bounds;
+  ///  Thickness of this detector element
+  double m_thickness;
+  /// Corresponding Surface
+  std::shared_ptr<const Acts::Surface> m_surface;
+  std::vector<std::shared_ptr<const Acts::Surface>> m_surfaces;
+
+  // this is pretty much only used single threaded, so
+  // the mutex does not hurt
+  mutable std::mutex m_cacheMutex;
+  mutable std::shared_ptr<const Acts::Transform3D> m_defTransform;
+
+  const FaserActsTrackingGeometrySvc* m_trackingGeometrySvc;
+  
+  Identifier m_explicitIdentifier;
+
+  // this is threadsafe!
+  //mutable Gaudi::Hive::ContextSpecificData<Acts::Transform3D> m_ctxSpecificTransform;
+
+
+};
+
+#endif
diff --git a/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/FaserActsExtrapolationAlg.h b/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/FaserActsExtrapolationAlg.h
new file mode 100755
index 0000000000000000000000000000000000000000..56c903c07c87c7b2054b4a7fadd840b906cb8445
--- /dev/null
+++ b/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/FaserActsExtrapolationAlg.h
@@ -0,0 +1,75 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef FASERACTSGEOMETRY_ACTSEXTRAPOLATIONALG_H
+#define FASERACTSGEOMETRY_ACTSEXTRAPOLATIONALG_H
+
+// ATHENA
+#include "AthenaBaseComps/AthReentrantAlgorithm.h"
+#include "GaudiKernel/ServiceHandle.h"
+#include "Gaudi/Property.h"  /*no forward decl: typedef*/
+#include "GaudiKernel/ISvcLocator.h"
+
+// ACTS
+#include "Acts/EventData/TrackParameters.hpp"
+#include "Acts/Geometry/GeometryID.hpp"
+#include "Acts/Utilities/Helpers.hpp"
+
+// PACKAGE
+#include "MagFieldConditions/FaserFieldCacheCondObj.h"
+#include "MagFieldElements/FaserFieldCache.h"
+
+// STL
+#include <memory>
+#include <vector>
+#include <fstream>
+#include <mutex>
+
+
+namespace Acts {
+  class TrackingGeometry;
+  
+  namespace detail {
+    class Step;
+  }
+}
+
+//class IFaserActsMaterialTrackWriterSvc;
+
+class EventContext;
+class IAthRNGSvc;
+class IFaserActsExtrapolationTool;
+class IFaserActsPropStepRootWriterSvc;
+
+class FaserActsExtrapolationAlg : public AthReentrantAlgorithm {
+public:
+  FaserActsExtrapolationAlg (const std::string& name, ISvcLocator* pSvcLocator);
+  StatusCode initialize() override;
+  StatusCode execute(const EventContext& ctx) const override;
+  StatusCode finalize() override;
+  
+private:
+  ServiceHandle<IFaserActsPropStepRootWriterSvc> m_propStepWriterSvc;
+  ServiceHandle<IAthRNGSvc> m_rndmGenSvc;
+
+  ToolHandle<IFaserActsExtrapolationTool> m_extrapolationTool{this, "ExtrapolationTool", "FaserActsExtrapolationTool"};
+
+  // poor-mans Particle Gun is included here right now
+  Gaudi::Property<std::vector<double>> m_etaRange{this, "EtaRange", {4, 10}, ""};
+  Gaudi::Property<std::vector<double>> m_ptRange{this, "PtRange", {0.1, 1000}, ""};
+  Gaudi::Property<size_t> m_nParticlePerEvent{this, "NParticlesPerEvent", 1, "The number of particles per event"};
+
+  // this does not work right now
+  //Gaudi::Property<bool> m_writeMaterialTracks{this, "WriteMaterialTracks", false, ""};
+  //ServiceHandle<IFaserActsMaterialTrackWriterSvc> m_materialTrackWriterSvc;
+  
+  mutable std::mutex m_writeMutex{};
+  mutable std::unique_ptr<std::ofstream> m_objOut;
+  mutable size_t m_objVtxCount{0};
+
+  void writeStepsObj(std::vector<Acts::detail::Step> steps) const;
+
+};
+
+#endif // ActsGeometry_ActsExtrapolation_h
diff --git a/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/FaserActsExtrapolationTool.h b/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/FaserActsExtrapolationTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..24498ac803be5dac0147c88ca0a9de6eb57f9f40
--- /dev/null
+++ b/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/FaserActsExtrapolationTool.h
@@ -0,0 +1,143 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef FASERACTSGEOMETRY_ACTSEXTRAPOLATIONTOOL_H
+#define FASERACTSGEOMETRY_ACTSEXTRAPOLATIONTOOL_H
+
+// ATHENA
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "GaudiKernel/IInterface.h"
+#include "GaudiKernel/ServiceHandle.h"
+#include "Gaudi/Property.h"
+#include "GaudiKernel/EventContext.h"
+
+// Need to include this early; otherwise, we run into errors with
+// ReferenceWrapperAnyCompat in clang builds due the is_constructable
+// specialization defined there getting implicitly instantiated earlier.
+#include "Acts/Propagator/Propagator.hpp"
+
+
+// PACKAGE
+#include "FaserActsGeometryInterfaces/IFaserActsExtrapolationTool.h"
+#include "FaserActsGeometryInterfaces/IFaserActsTrackingGeometryTool.h"
+#include "FaserActsGeometry/FaserActsGeometryContext.h"
+#include "MagFieldConditions/FaserFieldCacheCondObj.h"
+#include "MagFieldElements/FaserFieldCache.h"
+#include "FaserActsGeometry/FASERMagneticFieldWrapper.h"
+
+// ACTS
+#include "Acts/Propagator/EigenStepper.hpp"
+#include "Acts/Propagator/detail/SteppingLogger.hpp"
+#include "Acts/Propagator/Navigator.hpp"
+#include "Acts/Propagator/DebugOutputActor.hpp"
+#include "Acts/Propagator/StandardAborters.hpp"
+#include "Acts/MagneticField/ConstantBField.hpp"
+#include "Acts/MagneticField/MagneticFieldContext.hpp"
+#include "Acts/Utilities/Result.hpp"
+#include "Acts/Utilities/Units.hpp"
+#include "Acts/Utilities/Helpers.hpp"
+
+namespace Acts {
+  class Surface;
+  class BoundaryCheck;
+  class Logger;
+}
+
+namespace ActsExtrapolationDetail {
+  class VariantPropagator;
+}
+
+
+
+class FaserActsExtrapolationTool : public extends<AthAlgTool, IFaserActsExtrapolationTool>
+{
+
+public:
+  virtual StatusCode initialize() override;
+
+  FaserActsExtrapolationTool(const std::string& type, const std::string& name,
+	           const IInterface* parent);
+
+  ~FaserActsExtrapolationTool();
+
+private:
+  // set up options for propagation
+  using SteppingLogger = Acts::detail::SteppingLogger;
+  using DebugOutput = Acts::DebugOutputActor;
+  using EndOfWorld = Acts::EndOfWorldReached;
+  using ResultType = Acts::Result<std::pair<ActsPropagationOutput,
+                                            DebugOutput::result_type>>;
+
+public:
+  virtual
+  ActsPropagationOutput 
+  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
+  ActsPropagationOutput
+  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
+  const IFaserActsTrackingGeometryTool*
+  trackingGeometryTool() const override
+  {
+    return m_trackingGeometryTool.get();
+  }
+
+  virtual
+  Acts::MagneticFieldContext
+  getMagneticFieldContext(const EventContext& ctx) const override;
+
+
+
+private:
+
+  std::unique_ptr<ActsExtrapolationDetail::VariantPropagator> m_varProp;
+
+  std::unique_ptr<const Acts::Logger> m_logger{nullptr};
+
+  // Read handle for conditions object to get the field cache
+  SG::ReadCondHandleKey<FaserFieldCacheCondObj> m_fieldCondObjInputKey {this, "FaserFieldCacheCondObj", "fieldCondObj", "Name of the Magnetic Field conditions object key"};
+  
+  ToolHandle<IFaserActsTrackingGeometryTool> m_trackingGeometryTool{this, "TrackingGeometryTool", "FaserActsTrackingGeometryTool"};
+
+  Gaudi::Property<std::string> m_fieldMode{this, "FieldMode", "FASER"};
+  Gaudi::Property<std::vector<double>> m_constantFieldVector{this, "ConstantFieldVector", {0, 0, 0}};
+
+  Gaudi::Property<double> m_ptLoopers{this, "PtLoopers", 300, "PT loop protection threshold. Will be converted to Acts MeV unit"};
+
+  Gaudi::Property<double> m_maxStepSize{this, "MaxStepSize", 10, "Max step size in Acts m unit"};
+
+  // Material inteaction option
+  Gaudi::Property<bool> m_interactionMultiScatering{this, "InteractionMultiScatering", false, "Whether to consider multiple scattering in the interactor"};
+  Gaudi::Property<bool> m_interactionEloss{this, "InteractionEloss", false, "Whether to consider energy loss in the interactor"};
+  Gaudi::Property<bool> m_interactionRecord{this, "InteractionRecord", false, "Whether to record all material interactions"};
+  
+};
+
+
+
+#endif
diff --git a/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/FaserActsGeometryContext.h b/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/FaserActsGeometryContext.h
new file mode 100644
index 0000000000000000000000000000000000000000..5ff79e737b8ee67c215c647981c3c9a060eca73a
--- /dev/null
+++ b/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/FaserActsGeometryContext.h
@@ -0,0 +1,35 @@
+/*
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef FASERACTSGEOMETRY_ACTSGEOMETRYCONTEXT_H
+#define FASERACTSGEOMETRY_ACTSGEOMETRYCONTEXT_H
+
+#include "FaserActsGeometry/FaserActsAlignmentStore.h"
+
+#include "AthenaKernel/CLASS_DEF.h"
+#include "AthenaKernel/CondCont.h"
+
+#include "Acts/Geometry/GeometryContext.hpp"
+
+#include <memory>
+
+struct FaserActsGeometryContext {
+
+  bool construction{false};
+
+  std::unique_ptr<const FaserActsAlignmentStore> ownedAlignmentStore{nullptr};
+
+  const FaserActsAlignmentStore* alignmentStore{nullptr};
+
+  Acts::GeometryContext
+  any() const
+  {
+    return {this};
+  }
+};
+
+CLASS_DEF(FaserActsGeometryContext, 123437909, 1)
+CONDCONT_DEF( FaserActsGeometryContext , 27906711 );
+
+#endif
diff --git a/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/FaserActsLayerBuilder.h b/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/FaserActsLayerBuilder.h
new file mode 100644
index 0000000000000000000000000000000000000000..69843abf30e7ec18f6201f4686c5f3525177e4c2
--- /dev/null
+++ b/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/FaserActsLayerBuilder.h
@@ -0,0 +1,130 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef FASERACTSGEOMETRY_FASEERACTSLAYERBUILDER_H
+#define FASERACTSGEOMETRY_FASEERACTSLAYERBUILDER_H
+
+// PACKAGE
+#include "FaserActsGeometry/FaserActsDetectorElement.h"
+
+// ATHENA
+#include "TrackerReadoutGeometry/SiDetectorElement.h"
+
+// ACTS
+#include "Acts/Geometry/GeometryContext.hpp"
+#include "Acts/Geometry/ILayerBuilder.hpp"
+#include "Acts/Utilities/Logger.hpp"
+#include "Acts/Utilities/BinningType.hpp"
+#include "Acts/Utilities/Definitions.hpp"
+#include "Acts/Utilities/Units.hpp"
+#include "FaserActsGeometry/CuboidVolumeBuilder.h"
+
+using namespace Acts::UnitLiterals;
+
+class FaserActsTrackingGeomtrySvc;
+
+namespace TrackerDD {
+  class SCT_DetectorManager;
+}
+
+namespace Acts {
+class Surface;
+class LayerCreator;
+}
+
+/// @class FaserActsLayerBuilder
+class FaserActsLayerBuilder
+{
+public:
+  /// @struct Config
+  /// nested configuration struct for steering of the layer builder
+
+  struct Config
+  {
+    /// string based identification
+    std::string                          configurationName = "undefined";
+    FaserActsDetectorElement::Subdetector subdetector
+        = FaserActsDetectorElement::Subdetector::SCT;
+    const TrackerDD::SCT_DetectorManager*   mng;
+    std::shared_ptr<const Acts::LayerCreator> layerCreator = nullptr;
+    std::shared_ptr<std::vector<std::shared_ptr<const FaserActsDetectorElement>>> elementStore;
+    int station;
+    int plane;
+  };
+
+  /// Constructor
+  /// @param cfg is the configuration struct
+  /// @param logger the local logging instance
+  FaserActsLayerBuilder(const Config&                cfg,
+                       std::unique_ptr<const Acts::Logger> logger
+                       = Acts::getDefaultLogger("GMLayBldr", Acts::Logging::INFO))
+    : m_logger(std::move(logger))
+  {
+    // std::cout << "GMLB construct" << std::endl;
+    m_cfg = cfg;
+  }
+
+  /// Destructor
+  ~FaserActsLayerBuilder() {}
+
+  /// set the configuration object
+  /// @param cfg is the configuration struct
+  void
+  setConfiguration(const Config& cfg);
+
+  /// get the configuration object
+  // Config
+  // getConfiguration() const;
+
+  FaserActsLayerBuilder::Config
+  getConfiguration() const
+  {
+    return m_cfg;
+  }
+
+  const std::string&
+  identification() const
+  {
+    return m_cfg.configurationName;
+  }
+
+  /// set logging instance
+  void
+  setLogger(std::unique_ptr<const Acts::Logger> logger);
+
+  FaserActs::CuboidVolumeBuilder::Config
+  buildVolume(const Acts::GeometryContext&);
+
+  void
+  buildLayers(const Acts::GeometryContext&, std::vector<std::shared_ptr<const Acts::Surface> >&, FaserActs::CuboidVolumeBuilder::LayerConfig&, FaserActs::CuboidVolumeBuilder::SurfaceConfig&);
+
+private:
+  double m_ModuleWidth;
+  double m_ModuleLength;
+  /// configruation object
+  Config m_cfg;
+  Acts::Vector3D m_worldDimensions = { 400.0_mm, 400.0_mm, 6000.0_mm };
+  Acts::Vector3D m_worldCenter = {0.0, 0.0, 1276.0_mm};
+  Acts::Vector3D m_trackerDimensions = { 400.0_mm, 400.0_mm, 1200.0_mm };
+
+  /// Private access to the logger
+  const Acts::Logger&
+  logger() const
+  {
+    return *m_logger;
+  }
+
+  std::vector<std::shared_ptr<const FaserActsDetectorElement>>
+  getDetectorElements() const;
+
+  /// logging instance
+  std::unique_ptr<const Acts::Logger> m_logger;
+
+  ///// @todo make clear where the FaserActsDetectorElement lives
+  //std::vector<std::shared_ptr<const FaserActsDetectorElement>> m_elementStore;
+
+};
+
+
+#endif
diff --git a/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/FaserActsObjWriterTool.h b/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/FaserActsObjWriterTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..94aa12fe4fb99f4eb1bb94e27066863cb914eeee
--- /dev/null
+++ b/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/FaserActsObjWriterTool.h
@@ -0,0 +1,51 @@
+/*
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef FASERACTSGEOMETRY_ACTSOBJWRITERTOOL_H
+#define FASERACTSGEOMETRY_ACTSOBJWRITERTOOL_H
+
+#include <vector>
+
+#include "GaudiKernel/IAlgTool.h"
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "GaudiKernel/IInterface.h"
+#include "Gaudi/Property.h"  /*no forward decl: typedef*/
+#include "FaserActsGeometry/FaserActsGeometryContext.h"
+
+
+namespace Acts {
+
+class TrackingGeometry;
+class ObjTrackingGeometryWriter;
+
+}
+
+static const InterfaceID IID_FaserActsObjWriterTool("FaserActsObjWriterTool", 1, 0);
+
+class FaserActsObjWriterTool : public AthAlgTool
+{
+
+public:
+
+  static const InterfaceID& interfaceID(){return IID_FaserActsObjWriterTool;}
+
+  StatusCode initialize() override;
+
+  FaserActsObjWriterTool(const std::string& type, const std::string& name,
+    const IInterface* parent);
+
+  void
+  write(const FaserActsGeometryContext& gctx, const Acts::TrackingGeometry&) const;
+
+private:
+
+  Gaudi::Property<std::string> m_outputDirectory{this, "OutputDirectory", ".", ""};
+  Gaudi::Property<std::vector<std::string>> m_subDetectors{this, "SubDetectors", {}, ""};
+
+  std::shared_ptr<Acts::ObjTrackingGeometryWriter> m_tgObjWriter;
+
+
+};
+
+#endif
diff --git a/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/FaserActsPropStepRootWriterSvc.h b/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/FaserActsPropStepRootWriterSvc.h
new file mode 100644
index 0000000000000000000000000000000000000000..eeca580eb76f82fced49477a8ca1067cbea8d472
--- /dev/null
+++ b/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/FaserActsPropStepRootWriterSvc.h
@@ -0,0 +1,87 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef FASERACTSGEOMETRY_ACTSPROPSTEPROOTWRITERSVC_H
+#define FASERACTSGEOMETRY_ACTSPROPSTEPROOTWRITERSVC_H
+
+#include "AthenaBaseComps/AthService.h"
+#include "GaudiKernel/IInterface.h"
+#include "Gaudi/Property.h"  /*no forward decl: typedef*/
+
+#include "FaserActsGeometry/IFaserActsPropStepRootWriterSvc.h"
+
+#include "Acts/EventData/TrackParameters.hpp"
+
+#include <vector>
+#include <deque>
+#include <mutex>
+#include <thread>
+#include <atomic>
+
+template <typename T>
+class RootPropStepWriter;
+
+namespace Acts {
+
+template <class>
+class ExtrapolationCell;
+
+}
+
+class TFile;
+class TTree;
+
+
+class FaserActsPropStepRootWriterSvc : public extends<AthService, IFaserActsPropStepRootWriterSvc> {
+public:
+    
+  virtual StatusCode initialize() override;
+  virtual StatusCode finalize() override;
+    
+  FaserActsPropStepRootWriterSvc( const std::string& name, ISvcLocator* svc );
+
+  using StepVector = std::vector<Acts::detail::Step>;
+
+  void
+  write(const StepVector& steps) override;
+
+private:
+  using queue_item_t = std::pair<size_t, StepVector>;
+
+  //std::shared_ptr<RootPropStepWriter<Acts::TrackParameters>> m_rootEccWriter;
+  std::deque<queue_item_t> m_queue;
+  std::mutex m_writeMutex;
+  std::thread m_writeThread;
+  std::atomic<bool> m_doEnd;
+
+  void writeThread();
+  void doWrite(const StepVector& steps, size_t evtNum);
+  void end();
+
+  // jobOptions properties
+  Gaudi::Property<std::string> m_filePath{this, "FilePath", "propsteps.root", "Output root file for charged particle"};
+  Gaudi::Property<std::string> m_treeName{this, "TreeName", "propsteps", ""};
+  //Gaudi::Property<bool> m_writeBoundary{this, "WriteBoundary", true, ""};
+  //Gaudi::Property<bool> m_writeMaterial{this, "WriteMaterial", true, ""};
+  //Gaudi::Property<bool> m_writeSensitive{this, "WriteSensitive", true, ""};
+  //Gaudi::Property<bool> m_writePassive{this, "WritePassive", true, ""};
+
+  // root branch storage
+    TFile*             m_outputFile;    ///< the output file
+    TTree*             m_outputTree;    ///< the output tree
+    int m_eventNum;
+    std::vector<float> m_s_pX;   ///< global position x of the step
+    std::vector<float> m_s_pY;   ///< global position y of the step
+    std::vector<float> m_s_pZ;   ///< global position z of the step
+    std::vector<float> m_s_pR;   ///< global position z of the step
+    std::vector<int>   m_s_volumeID;    ///< volume identification
+    std::vector<int>   m_s_boundaryID;    ///< boundary identification
+    std::vector<int>   m_s_layerID;     ///< layer identification
+    std::vector<int>   m_s_approachID;     ///< approach identification
+    std::vector<int>   m_s_sensitiveID;   ///< sensitive identification
+
+};
+
+
+#endif 
diff --git a/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/FaserActsTrackingGeometrySvc.h b/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/FaserActsTrackingGeometrySvc.h
new file mode 100644
index 0000000000000000000000000000000000000000..28ef43bd3e51d8ecbb307182d25e9984f1756849
--- /dev/null
+++ b/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/FaserActsTrackingGeometrySvc.h
@@ -0,0 +1,82 @@
+/*
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef FASERACTSGEOMETRY_ACTSTRACKINGGEOMETRYSVC_H
+#define FASERACTSGEOMETRY_ACTSTRACKINGGEOMETRYSVC_H
+
+// ATHENA
+#include "AthenaBaseComps/AthService.h"
+#include "StoreGate/StoreGateSvc.h"
+#include "GaudiKernel/EventContext.h"
+
+// ACTS
+#include "Acts/Geometry/GeometryContext.hpp"
+#include "Acts/Utilities/Definitions.hpp"
+#include "Acts/Utilities/Units.hpp"
+
+// PACKAGE
+#include "FaserActsGeometryInterfaces/IFaserActsTrackingGeometrySvc.h"
+
+// STL
+#include <map>
+
+using namespace Acts::UnitLiterals;
+
+namespace TrackerDD {
+  class SCT_DetectorManager;
+}
+
+class FaserActsAlignmentStore;
+
+class FaserActsDetectorElement;
+
+namespace Acts {
+
+class TrackingGeometry;
+class CylinderVolumeHelper;
+class ITrackingVolumeBuilder;
+
+class GeometryID;
+class BinnedSurfaceMaterial;
+
+}
+
+
+class FaserActsTrackingGeometrySvc : public extends<AthService, IFaserActsTrackingGeometrySvc> {
+public:
+
+  StatusCode initialize() override;
+  //virtual StatusCode finalize() override;
+
+  FaserActsTrackingGeometrySvc( const std::string& name, ISvcLocator* pSvcLocator );
+
+  std::shared_ptr<const Acts::TrackingGeometry>
+  trackingGeometry() override;
+
+  void
+  populateAlignmentStore(FaserActsAlignmentStore *store) const override;
+
+  const FaserActsAlignmentStore*
+  getNominalAlignmentStore() const override;
+
+private:
+  std::shared_ptr<const Acts::ITrackingVolumeBuilder>
+  makeVolumeBuilder(const Acts::GeometryContext& gctx, const TrackerDD::SCT_DetectorManager* manager);
+
+  ServiceHandle<StoreGateSvc> m_detStore;
+  const TrackerDD::SCT_DetectorManager* p_SCTManager;
+
+  std::shared_ptr<std::vector<std::shared_ptr<const FaserActsDetectorElement>>> m_elementStore;
+  std::shared_ptr<const Acts::TrackingGeometry> m_trackingGeometry;
+
+  std::unique_ptr<const FaserActsAlignmentStore> m_nominalAlignmentStore{nullptr};
+
+  Gaudi::Property<bool> m_useMaterialMap{this, "UseMaterialMap", false, ""};
+  Gaudi::Property<std::string> m_materialMapInputFile{this, "MaterialMapInputFile", "", ""};
+  Gaudi::Property<std::vector<size_t>> m_MaterialBins{this, "BarrelMaterialBins", {10, 10}};
+};
+
+
+
+#endif
diff --git a/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/FaserActsTrackingGeometryTool.h b/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/FaserActsTrackingGeometryTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..7a32e70e994b29b5f2583d5104ad3b2cdd186c70
--- /dev/null
+++ b/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/FaserActsTrackingGeometryTool.h
@@ -0,0 +1,58 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef FASERACTSGEOMETRY_ACTSTRACKINGGEOMETRYTOOL_H
+#define FASERACTSGEOMETRY_ACTSTRACKINGGEOMETRYTOOL_H
+
+// ATHENA
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "GaudiKernel/EventContext.h"
+#include "GaudiKernel/IInterface.h"
+#include "GaudiKernel/ServiceHandle.h"
+#include "StoreGate/ReadCondHandleKey.h"
+
+// PACKAGE
+#include "FaserActsGeometry/FaserActsAlignmentStore.h" // ReadCondHandleKey wants complete type
+#include "FaserActsGeometry/FaserActsGeometryContext.h"
+#include "FaserActsGeometryInterfaces/IFaserActsTrackingGeometryTool.h"
+
+// ACTS
+
+namespace Acts {
+class TrackingGeometry;
+}
+
+class FaserActsGeometryContext;
+class IFaserActsTrackingGeometrySvc;
+
+
+class FaserActsTrackingGeometryTool : public extends<AthAlgTool, IFaserActsTrackingGeometryTool>
+{
+
+public:
+  StatusCode initialize() override;
+
+  FaserActsTrackingGeometryTool(const std::string &type, const std::string &name,
+                           const IInterface *parent);
+
+  virtual
+  std::shared_ptr<const Acts::TrackingGeometry>
+  trackingGeometry() const override;
+
+  virtual
+  const FaserActsGeometryContext&
+  getGeometryContext(const EventContext& ctx = Gaudi::Hive::currentContext()) const override;
+
+  virtual
+  FaserActsGeometryContext
+  getNominalGeometryContext() const override;
+
+private:
+  ServiceHandle<IFaserActsTrackingGeometrySvc> m_trackingGeometrySvc;
+
+  SG::ReadCondHandleKey<FaserActsGeometryContext> m_rchk{
+      this, "FaserActsAlignmentKey", "FaserActsAlignment", "cond read key"};
+};
+
+#endif
diff --git a/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/FaserActsWriteTrackingGeometry.h b/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/FaserActsWriteTrackingGeometry.h
new file mode 100755
index 0000000000000000000000000000000000000000..2de2fef9c67193d8b0d52e1352124bbe41e55939
--- /dev/null
+++ b/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/FaserActsWriteTrackingGeometry.h
@@ -0,0 +1,45 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef FASERACTSGEOMETRY_ACTSWRITETRACKINGGEOMETRY_H
+#define FASERACTSGEOMETRY_ACTSWRITETRACKINGGEOMETRY_H
+
+// ATHENA
+#include "AthenaBaseComps/AthReentrantAlgorithm.h"
+#include "GaudiKernel/ServiceHandle.h"
+#include "AthenaKernel/IAthRNGSvc.h"
+#include "Gaudi/Property.h"  /*no forward decl: typedef*/
+#include "GaudiKernel/ISvcLocator.h"
+
+// PACKAGE
+#include "FaserActsGeometry/FaserActsObjWriterTool.h"
+#include "FaserActsGeometry/FaserActsTrackingGeometryTool.h"
+
+// STL
+#include <fstream>
+#include <memory>
+#include <vector>
+
+namespace Acts {
+  class TrackingGeometry;
+}
+
+class IFaserActsTrackingGeometrySvc;
+
+class FaserActsWriteTrackingGeometry : public AthReentrantAlgorithm {
+public:
+  FaserActsWriteTrackingGeometry (const std::string& name, ISvcLocator* pSvcLocator);
+  virtual StatusCode initialize() override;
+  virtual StatusCode execute(const EventContext& ctx) const override;
+  virtual StatusCode finalize() override;
+
+private:
+
+  ToolHandle<FaserActsTrackingGeometryTool> m_trackingGeometryTool{this, "TrackingGeometryTool", "FaserActsTrackingGeometryTool"};
+
+  ToolHandle<FaserActsObjWriterTool> m_objWriterTool{this, "ObjWriterTool", "FaserActsObjWriterTool"};
+
+};
+
+#endif
diff --git a/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/FaserNominalAlignmentCondAlg.h b/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/FaserNominalAlignmentCondAlg.h
new file mode 100644
index 0000000000000000000000000000000000000000..bed4135c09794f919f3d5cd0db3c2405ec1e16a5
--- /dev/null
+++ b/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/FaserNominalAlignmentCondAlg.h
@@ -0,0 +1,45 @@
+/*
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+*/
+
+#pragma once
+
+// ATHENA
+#include "AthenaBaseComps/AthAlgorithm.h"
+#include "GaudiKernel/ICondSvc.h"
+#include "StoreGate/WriteCondHandleKey.h"
+
+// PACKAGE
+
+// STL
+#include <string>
+
+class IFaserActsTrackingGeometrySvc;
+class FaserActsAlignmentStore;
+
+class FaserActsGeometryContext;
+
+/// @class FaserNominalAlignmentCondAlg
+/// Conditions algorithm which produces an (effectively)
+/// infinitely valid FaserActsAlignmentStore which has
+/// nominal alignments (= identity deltas)
+///
+class FaserNominalAlignmentCondAlg : public AthAlgorithm {
+
+public:
+  FaserNominalAlignmentCondAlg(const std::string &name, ISvcLocator *pSvcLocator);
+  virtual ~FaserNominalAlignmentCondAlg();
+
+  virtual bool isClonable() const override { return true; }
+
+  virtual StatusCode initialize() override;
+  virtual StatusCode execute() override;
+  virtual StatusCode finalize() override;
+
+private:
+  SG::WriteCondHandleKey<FaserActsGeometryContext> m_wchk{
+      this, "FaserActsAlignmentKey", "FaserActsAlignment", "cond handle key"};
+
+  ServiceHandle<ICondSvc> m_cs;
+  ServiceHandle<IFaserActsTrackingGeometrySvc> m_trackingGeometrySvc;
+};
diff --git a/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/IFaserActsExCellWriterSvc.h b/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/IFaserActsExCellWriterSvc.h
new file mode 100644
index 0000000000000000000000000000000000000000..9c657fadb9467fb07b7abbbe63ca9225f242f8b3
--- /dev/null
+++ b/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/IFaserActsExCellWriterSvc.h
@@ -0,0 +1,33 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef FASERACTSGEOMETRY_IACTSEXCELLWRITERSVC_H
+#define FASERACTSGEOMETRY_IACTSEXCELLWRITERSVC_H
+
+#include "GaudiKernel/IInterface.h"
+#include "Acts/EventData/TrackParameters.hpp"
+
+namespace Acts {
+
+template <class>
+class ExtrapolationCell;
+
+}
+
+
+class IFaserActsExCellWriterSvc : virtual public IInterface {
+public:
+    
+  DeclareInterfaceID(IFaserActsExCellWriterSvc, 1, 0);
+
+  IFaserActsExCellWriterSvc() {;}
+    
+  void
+  virtual
+  store(std::vector<Acts::ExtrapolationCell<Acts::TrackParameters>>& ecells) = 0;
+
+};
+
+
+#endif 
diff --git a/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/IFaserActsPropStepRootWriterSvc.h b/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/IFaserActsPropStepRootWriterSvc.h
new file mode 100644
index 0000000000000000000000000000000000000000..45202b670818d420e8806505683c165968119439
--- /dev/null
+++ b/Tracking/Acts/FaserActsGeometry/FaserActsGeometry/IFaserActsPropStepRootWriterSvc.h
@@ -0,0 +1,32 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef FASERACTSGEOMETRY_IACTSPROPSTEPROOTWRITERSVC_H
+#define FASERACTSGEOMETRY_IACTSPROPSTEPROOTWRITERSVC_H
+
+#include "GaudiKernel/IInterface.h"
+#include "Acts/EventData/TrackParameters.hpp"
+
+namespace Acts {
+  namespace detail {
+    class Step;
+  }
+}
+
+
+class IFaserActsPropStepRootWriterSvc : virtual public IInterface {
+public:
+    
+  DeclareInterfaceID(IFaserActsPropStepRootWriterSvc, 1, 0);
+
+  IFaserActsPropStepRootWriterSvc() {;}
+    
+  void
+  virtual
+  write(const std::vector<Acts::detail::Step>& steps) = 0;
+
+};
+
+
+#endif 
diff --git a/Tracking/Acts/FaserActsGeometry/python/FaserActsExtrapolationConfig.py b/Tracking/Acts/FaserActsGeometry/python/FaserActsExtrapolationConfig.py
new file mode 100644
index 0000000000000000000000000000000000000000..ee53a9aac0530e4359fac3cc327be4ac683fb8af
--- /dev/null
+++ b/Tracking/Acts/FaserActsGeometry/python/FaserActsExtrapolationConfig.py
@@ -0,0 +1,58 @@
+"""
+Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+"""
+from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator
+from AthenaConfiguration.ComponentFactory import CompFactory
+from FaserGeoModel.FaserGeoModelConfig import FaserGeometryCfg
+from FaserGeoModel.SCTGMConfig import SctGeometryCfg
+from MagFieldServices.MagFieldServicesConfig import MagneticFieldSvcCfg
+
+
+FaserActsExtrapolationAlg,FaserActsExtrapolationTool,FaserActsTrackingGeometrySvc,FaserActsTrackingGeometryTool,FaserActsAlignmentCondAlg = CompFactory.getComps("FaserActsExtrapolationAlg","FaserActsExtrapolationTool","FaserActsTrackingGeometrySvc","FaserActsTrackingGeometryTool","FaserActsAlignmentCondAlg")
+
+def FaserActsTrackingGeometrySvcCfg(flags, **kwargs):
+    acc = ComponentAccumulator()
+    acc.addService(FaserActsTrackingGeometrySvc(name = "FaserActsTrackingGeometrySvc", **kwargs))
+    return acc 
+
+
+def FaserActsAlignmentCondAlgCfg(flags, **kwargs):
+    acc = ComponentAccumulator()
+    acc.addCondAlgo(CompFactory.FaserActsAlignmentCondAlg(name = "FaserActsAlignmentCondAlg", **kwargs))
+    #acc.addCondAlgo(CompFactory.NominalAlignmentCondAlg(name = "NominalAlignmentCondAlg", **kwargs))
+    return acc
+
+
+def FaserActsExtrapolationAlgBasicCfg(flags, **kwargs):
+    acc = ComponentAccumulator()
+    actsExtrapolationAlg=FaserActsExtrapolationAlg(**kwargs)
+    actsExtrapolationTool=FaserActsExtrapolationTool("FaserActsExtrapolationTool")
+    actsExtrapolationTool.FieldMode="FASER"
+    #actsExtrapolationTool.FieldMode="Constant"
+    actsExtrapolationTool.TrackingGeometryTool=FaserActsTrackingGeometryTool("TrackingGeometryTool")
+    actsExtrapolationAlg.ExtrapolationTool=actsExtrapolationTool
+    actsExtrapolationAlg.EtaRange=[1, 10]
+    actsExtrapolationAlg.PtRange=[0.1, 100]
+    actsExtrapolationAlg.NParticlesPerEvent=int(1e4)
+    acc.addEventAlgo(actsExtrapolationAlg)
+    return acc
+
+
+def FaserActsExtrapolationAlg_OutputCfg(flags):                                                                                                    
+    acc = ComponentAccumulator()
+    return acc
+
+
+def FaserActsExtrapolationAlgCfg(flags, **kwargs):
+    # Initialize GeoModel
+    #acc = FaserGeometryCfg(flags)
+    acc = SctGeometryCfg(flags)
+
+    # Initialize field service
+    acc.merge(MagneticFieldSvcCfg(flags))
+
+    acc.merge(FaserActsTrackingGeometrySvcCfg(flags, **kwargs))
+    #acc.merge(FaserActsAlignmentCondAlgCfg(flags))
+    acc.merge(FaserActsExtrapolationAlgBasicCfg(flags, **kwargs))
+    acc.merge(FaserActsExtrapolationAlg_OutputCfg(flags))
+    return acc
diff --git a/Tracking/Acts/FaserActsGeometry/python/FaserActsWriteTrackingGeometryConfig.py b/Tracking/Acts/FaserActsGeometry/python/FaserActsWriteTrackingGeometryConfig.py
new file mode 100644
index 0000000000000000000000000000000000000000..d4453a69f079186dc0181bdbe519b9932a4f9890
--- /dev/null
+++ b/Tracking/Acts/FaserActsGeometry/python/FaserActsWriteTrackingGeometryConfig.py
@@ -0,0 +1,45 @@
+"""
+Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+"""
+from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator
+from AthenaConfiguration.ComponentFactory import CompFactory
+#from FaserGeoModel.FaserGeoModelConfig import FaserGeometryCfg
+from FaserGeoModel.SCTGMConfig import SctGeometryCfg
+
+FaserActsWriteTrackingGeometry,FaserActsTrackingGeometrySvc,FaserActsTrackingGeometryTool,FaserActsObjWriterTool,FaserActsAlignmentCondAlg = CompFactory.getComps("FaserActsWriteTrackingGeometry","FaserActsTrackingGeometrySvc","FaserActsTrackingGeometryTool","FaserActsObjWriterTool","FaserActsAlignmentCondAlg")
+
+def FaserActsTrackingGeometrySvcCfg(flags, **kwargs):
+    acc = ComponentAccumulator()
+    acc.addService(FaserActsTrackingGeometrySvc(name = "FaserActsTrackingGeometrySvc", **kwargs))
+    return acc 
+
+
+def FaserActsAlignmentCondAlgCfg(flags, **kwargs):
+    acc = ComponentAccumulator()
+    acc.addCondAlgo(CompFactory.FaserActsAlignmentCondAlg(name = "FaserActsAlignmentCondAlg", **kwargs))
+    #acc.addCondAlgo(CompFactory.NominalAlignmentCondAlg(name = "NominalAlignmentCondAlg", **kwargs))
+    return acc
+
+
+def FaserActsWriteTrackingGeometryBasicCfg(flags, **kwargs):
+    acc = ComponentAccumulator()
+    actsWriteTrackingGeometry=FaserActsWriteTrackingGeometry(**kwargs)
+    actsWriteTrackingGeometry.TrackingGeometryTool=FaserActsTrackingGeometryTool("TrackingGeometryTool")
+    actsWriteTrackingGeometry.ObjWriterTool=FaserActsObjWriterTool("FaserActsObjWriterTool",OutputDirectory="./", SubDetectors=["Station_1","Station_2","Station_3"])
+    acc.addEventAlgo(actsWriteTrackingGeometry)
+    return acc
+
+
+def FaserActsWriteTrackingGeometry_OutputCfg(flags):                                                                                                    
+    acc = ComponentAccumulator()
+    return acc
+
+
+def FaserActsWriteTrackingGeometryCfg(flags, **kwargs):
+    #acc = FaserGeometryCfg(flags)
+    acc = SctGeometryCfg(flags)
+    acc.merge(FaserActsTrackingGeometrySvcCfg(flags, **kwargs))
+    #acc.merge(FaserActsAlignmentCondAlgCfg(flags))
+    acc.merge(FaserActsWriteTrackingGeometryBasicCfg(flags, **kwargs))
+    acc.merge(FaserActsWriteTrackingGeometry_OutputCfg(flags))
+    return acc
diff --git a/Tracking/Acts/FaserActsGeometry/src/CuboidVolumeBuilder.cxx b/Tracking/Acts/FaserActsGeometry/src/CuboidVolumeBuilder.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..2ded998d64f261412fc154226b23bb7832734e67
--- /dev/null
+++ b/Tracking/Acts/FaserActsGeometry/src/CuboidVolumeBuilder.cxx
@@ -0,0 +1,237 @@
+// This file is part of the Acts project.
+//
+// Copyright (C) 2018 CERN for the benefit of the Acts project
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include "FaserActsGeometry/CuboidVolumeBuilder.h"
+
+#include "Acts/Geometry/CuboidVolumeBounds.hpp"
+#include "Acts/Geometry/Layer.hpp"
+#include "Acts/Geometry/LayerArrayCreator.hpp"
+#include "Acts/Geometry/LayerCreator.hpp"
+#include "Acts/Geometry/PlaneLayer.hpp"
+#include "Acts/Geometry/TrackingGeometry.hpp"
+#include "Acts/Geometry/TrackingVolume.hpp"
+#include "Acts/Geometry/detail/DefaultDetectorElementBase.hpp"
+#include "Acts/Geometry/ApproachDescriptor.hpp"
+#include "Acts/Material/HomogeneousSurfaceMaterial.hpp"
+#include "Acts/Material/MaterialProperties.hpp"
+#include "Acts/Surfaces/PlaneSurface.hpp"
+#include "Acts/Surfaces/RectangleBounds.hpp"
+#include "Acts/Surfaces/SurfaceArray.hpp"
+#include "Acts/Utilities/BinnedArray.hpp"
+#include "Acts/Utilities/BinnedArrayXD.hpp"
+#include "Acts/Utilities/Definitions.hpp"
+
+namespace FaserActs{
+
+std::shared_ptr<const Acts::PlaneSurface>
+CuboidVolumeBuilder::buildSurface(
+    const Acts::GeometryContext& /*gctx*/,
+    const CuboidVolumeBuilder::SurfaceConfig& cfg) const {
+  std::shared_ptr<Acts::PlaneSurface> surface;
+
+  // Build transformation
+  Acts::Transform3D trafo(Acts::Transform3D::Identity() * cfg.rotation);
+  trafo.translation() = cfg.position;
+
+  // Create and store surface
+  if (cfg.detElementConstructor) {
+    surface = Acts::Surface::makeShared<Acts::PlaneSurface>(
+        cfg.rBounds,
+        *(cfg.detElementConstructor(std::make_shared<const Acts::Transform3D>(trafo),
+                                    cfg.rBounds, cfg.thickness)));
+  } else {
+    surface = Acts::Surface::makeShared<Acts::PlaneSurface>(
+        std::make_shared<const Acts::Transform3D>(trafo), cfg.rBounds);
+  }
+  surface->assignSurfaceMaterial(cfg.surMat);
+  return surface;
+}
+
+std::shared_ptr<const Acts::Layer> CuboidVolumeBuilder::buildLayer(
+    const Acts::GeometryContext& gctx,
+    CuboidVolumeBuilder::LayerConfig& cfg) const {
+  // Build the surface
+  if ( cfg.surface==nullptr && cfg.surfaces.empty() ) {
+    cfg.surface = buildSurface(gctx, cfg.surfaceCfg);
+  }
+  // Build transformation centered at the surface position
+  Acts::Transform3D trafo(Acts::Transform3D::Identity() * cfg.surfaceCfg.rotation);
+  trafo.translation() = cfg.surfaceCfg.position;
+
+  Acts::LayerCreator::Config lCfg;
+  lCfg.surfaceArrayCreator = std::make_shared<const Acts::SurfaceArrayCreator>();
+  Acts::LayerCreator layerCreator(lCfg);
+
+  std::unique_ptr<Acts::ApproachDescriptor> ap(cfg.approachDescriptor);
+
+  if ( !cfg.surfaces.empty() ) {
+    return layerCreator.planeLayer(gctx, cfg.surfaces, cfg.binsX, cfg.binsY,
+                                 Acts::BinningValue::binZ, std::nullopt,
+                                 std::make_shared<const Acts::Transform3D>(trafo), 
+				 std::move(ap));
+  } else {
+    return layerCreator.planeLayer(gctx, {cfg.surface}, cfg.binsX, cfg.binsY,
+                                 Acts::BinningValue::binZ, std::nullopt,
+                                 std::make_shared<const Acts::Transform3D>(trafo), 
+				 std::move(ap));
+  }
+}
+
+std::pair<double, double> CuboidVolumeBuilder::binningRange(
+    const Acts::GeometryContext& /*gctx*/,
+    const CuboidVolumeBuilder::VolumeConfig& cfg) const {
+  using namespace Acts::UnitLiterals;
+  // Construct return value
+  std::pair<double, double> minMax = std::make_pair(
+      std::numeric_limits<double>::max(), -std::numeric_limits<double>::max());
+  for (const auto& layercfg : cfg.layerCfg) {
+    // Test if new extreme is found and set it
+    
+    // For Faser, the thickness of each layer is about 5 mm due to staggering structure of SCTs
+    //if (layercfg.surfaceCfg.position.z() - 1_um < minMax.first) {
+      //minMax.first = layercfg.surfaceCfg.position.z() - 1_um;
+    if (layercfg.surfaceCfg.position.z() - 8_mm < minMax.first) {
+      minMax.first = layercfg.surfaceCfg.position.z() - 8_mm;
+    }
+    //if (layercfg.surfaceCfg.position.z() + 1_um > minMax.second) {
+      //minMax.second = layercfg.surfaceCfg.position.z() + 1_um;
+    if (layercfg.surfaceCfg.position.z() + 8_mm > minMax.second) {
+      minMax.second = layercfg.surfaceCfg.position.z() + 8_mm;
+    }
+  }
+  return minMax;
+}
+
+std::shared_ptr<Acts::TrackingVolume> CuboidVolumeBuilder::buildVolume(
+    const Acts::GeometryContext& gctx,
+    CuboidVolumeBuilder::VolumeConfig& cfg) const {
+  // Build transformation
+  Acts::Transform3D trafo(Acts::Transform3D::Identity());
+  trafo.translation() = cfg.position;
+  // Set bounds
+  auto bounds = std::make_shared<const Acts::CuboidVolumeBounds>(
+      cfg.length.x() * 0.5, cfg.length.y() * 0.5, cfg.length.z() * 0.5);
+
+  if (cfg.layerCfg.empty()) {
+    // Build dummy layer if no layer is given (tmp solution)
+    SurfaceConfig sCfg;
+    sCfg.position = cfg.position;
+    // Rotation of the surfaces: +pi/2 around axis y
+    Acts::Vector3D xPos(0., 0., 1.);
+    Acts::Vector3D yPos(0., 1., 0.);
+    Acts::Vector3D zPos(-1., 0., 0.);
+    sCfg.rotation.col(0) = xPos;
+    sCfg.rotation.col(1) = yPos;
+    sCfg.rotation.col(2) = zPos;
+    // Bounds
+    sCfg.rBounds = std::make_shared<const Acts::RectangleBounds>(
+        Acts::RectangleBounds(cfg.length.y() * 0.5, cfg.length.z() * 0.5));
+
+    LayerConfig lCfg;
+    lCfg.surfaceCfg = sCfg;
+
+    cfg.layerCfg.push_back(lCfg);
+  }
+
+  // Gather the layers
+  Acts::LayerVector layVec;
+  if (cfg.layers.empty()) {
+    cfg.layers.reserve(cfg.layerCfg.size());
+
+    for (auto& layerCfg : cfg.layerCfg) {
+      cfg.layers.push_back(buildLayer(gctx, layerCfg));
+      layVec.push_back(cfg.layers.back());
+    }
+  } else {
+    for (auto& lay : cfg.layers) {
+      layVec.push_back(lay);
+    }
+  }
+
+  // Build layer array
+  std::pair<double, double> minMax = binningRange(gctx, cfg);
+  Acts::LayerArrayCreator::Config lacCnf;
+  Acts::LayerArrayCreator layArrCreator(
+      lacCnf, Acts::getDefaultLogger("Acts::LayerArrayCreator", Acts::Logging::INFO));
+  std::unique_ptr<const Acts::LayerArray> layArr(
+      layArrCreator.layerArray(gctx, layVec, minMax.first, minMax.second,
+                               Acts::BinningType::arbitrary, Acts::BinningValue::binZ));
+
+  // Build confined volumes
+     if (cfg.trackingVolumes.empty())
+       for (VolumeConfig vc : cfg.volumeCfg)            
+	  cfg.trackingVolumes.push_back(buildVolume(gctx, vc));
+               
+  // Build TrackingVolume
+  auto trackVolume = Acts::TrackingVolume::create(
+      std::make_shared<const Acts::Transform3D>(trafo), bounds, cfg.volumeMaterial,
+      std::move(layArr), nullptr, cfg.trackingVolumes, cfg.name);
+  
+  return trackVolume;
+}
+
+Acts::MutableTrackingVolumePtr CuboidVolumeBuilder::trackingVolume(
+    const Acts::GeometryContext& gctx, Acts::TrackingVolumePtr /*unused*/,
+    Acts::VolumeBoundsPtr /*unused*/) const {
+  // Build volumes
+  std::vector<std::shared_ptr<Acts::TrackingVolume>> volumes;
+  volumes.reserve(m_cfg.volumeCfg.size());
+  for (VolumeConfig volCfg : m_cfg.volumeCfg) {
+    volumes.push_back(buildVolume(gctx, volCfg));
+  }
+
+  // Glue volumes
+  for (unsigned int i = 0; i < volumes.size() - 1; i++) {
+    volumes[i + 1]->glueTrackingVolume(
+        gctx, Acts::BoundarySurfaceFace::negativeFaceXY, volumes[i].get(),
+        Acts::BoundarySurfaceFace::positiveFaceXY);
+    volumes[i]->glueTrackingVolume(gctx, Acts::BoundarySurfaceFace::positiveFaceXY,
+                                   volumes[i + 1].get(),
+                                   Acts::BoundarySurfaceFace::negativeFaceXY);
+  }
+
+  // Translation
+  Acts::Transform3D trafo(Acts::Transform3D::Identity());
+  trafo.translation() = m_cfg.position;
+
+  // Size of the volume
+  auto volume = std::make_shared<const Acts::CuboidVolumeBounds>(
+      m_cfg.length.x() * 0.5, m_cfg.length.y() * 0.5, m_cfg.length.z() * 0.5);
+
+  // Build vector of confined volumes
+  std::vector<std::pair<Acts::TrackingVolumePtr, Acts::Vector3D>> tapVec;
+  tapVec.reserve(m_cfg.volumeCfg.size());
+  for (auto& tVol : volumes) {
+    tapVec.push_back(std::make_pair(tVol, tVol->center()));
+  }
+
+  // Set bin boundaries along binning
+  std::vector<float> binBoundaries;
+  binBoundaries.push_back(volumes[0]->center().z() -
+                          m_cfg.volumeCfg[0].length.z() * 0.5);
+  for (size_t i = 0; i < volumes.size(); i++) {
+    binBoundaries.push_back(volumes[i]->center().z() +
+                            m_cfg.volumeCfg[i].length.z() * 0.5);
+  }
+
+  // Build binning
+  Acts::BinningData binData(Acts::BinningOption::open, Acts::BinningValue::binZ, binBoundaries);
+  auto bu = std::make_unique<const Acts::BinUtility>(binData);
+
+  // Build TrackingVolume array
+  std::shared_ptr<const Acts::TrackingVolumeArray> trVolArr(
+      new Acts::BinnedArrayXD<Acts::TrackingVolumePtr>(tapVec, std::move(bu)));
+
+  // Create world volume
+  Acts::MutableTrackingVolumePtr mtvp(Acts::TrackingVolume::create(
+      std::make_shared<const Acts::Transform3D>(trafo), volume, trVolArr, "World"));
+
+  return mtvp;
+}
+
+}
diff --git a/Tracking/Acts/FaserActsGeometry/src/FaserActsAlignmentCondAlg.cxx b/Tracking/Acts/FaserActsGeometry/src/FaserActsAlignmentCondAlg.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..66cfdc7bd6b0fd92654fa1a4f45c2c79704084b7
--- /dev/null
+++ b/Tracking/Acts/FaserActsGeometry/src/FaserActsAlignmentCondAlg.cxx
@@ -0,0 +1,140 @@
+/*
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "FaserActsGeometry/FaserActsAlignmentCondAlg.h"
+
+// ATHENA
+#include "EventInfo/EventID.h"
+#include "EventInfo/EventInfo.h"
+#include "GaudiKernel/EventIDBase.h"
+#include "GaudiKernel/EventIDRange.h"
+#include "GaudiKernel/ICondSvc.h"
+#include "GeoModelKernel/GeoAlignableTransform.h"
+#include "StoreGate/StoreGateSvc.h"
+#include "StoreGate/WriteCondHandle.h"
+#include "TrackerReadoutGeometry/SCT_DetectorManager.h"
+
+// PACKAGE
+#include "FaserActsGeometry/FaserActsAlignmentStore.h"
+#include "FaserActsGeometry/FaserActsDetectorElement.h"
+#include "FaserActsGeometry/FaserActsGeometryContext.h"
+#include "FaserActsGeometryInterfaces/IFaserActsTrackingGeometrySvc.h"
+
+// ACTS
+#include "Acts/Geometry/DetectorElementBase.hpp"
+#include "Acts/Geometry/TrackingGeometry.hpp"
+#include "Acts/Surfaces/Surface.hpp"
+#include "Acts/Utilities/Definitions.hpp"
+
+// STL
+#include <memory>
+
+FaserActsAlignmentCondAlg::FaserActsAlignmentCondAlg(const std::string &name,
+                                           ISvcLocator *pSvcLocator)
+    : ::AthAlgorithm(name, pSvcLocator), m_cs("CondSvc", name),
+      m_trackingGeometrySvc("FaserActsTrackingGeometrySvc", name) {}
+
+FaserActsAlignmentCondAlg::~FaserActsAlignmentCondAlg() {}
+
+StatusCode FaserActsAlignmentCondAlg::initialize() {
+  ATH_MSG_DEBUG("initialize " << name());
+
+  ATH_CHECK(m_sctAlignStoreReadKey.initialize());
+
+  if (m_cs.retrieve().isFailure()) {
+    ATH_MSG_ERROR("unable to retrieve CondSvc");
+    return StatusCode::FAILURE;
+  }
+
+  ATH_CHECK(detStore()->retrieve(p_SCTManager, "SCT"));
+
+  if (m_wchk.initialize().isFailure()) {
+    ATH_MSG_ERROR("unable to initialize WriteCondHandle with key"
+                  << m_wchk.key());
+    return StatusCode::FAILURE;
+  }
+
+  if (m_cs->regHandle(this, m_wchk).isFailure()) {
+    ATH_MSG_ERROR("unable to register WriteCondHandle " << m_wchk.fullKey()
+                                                        << " with CondSvc");
+    return StatusCode::FAILURE;
+  }
+
+  return StatusCode::SUCCESS;
+}
+
+StatusCode FaserActsAlignmentCondAlg::finalize() {
+  ATH_MSG_DEBUG("finalize " << name());
+  return StatusCode::SUCCESS;
+}
+
+StatusCode FaserActsAlignmentCondAlg::execute() {
+  ATH_MSG_DEBUG("execute " << name());
+
+  auto trkGeom = m_trackingGeometrySvc->trackingGeometry();
+
+  EventIDBase now(getContext().eventID());
+  SG::WriteCondHandle<FaserActsGeometryContext> wch(m_wchk);
+
+  if (wch.isValid(now)) {
+    ATH_MSG_DEBUG(
+        "CondHandle is already valid for "
+        << now << ". In theory this should not be called, but may happen"
+        << " if multiple concurrent events are being processed out of order.");
+
+  } else {
+
+    ATH_MSG_DEBUG("  CondHandle " << wch.key() << " not valid now (" << now
+                                  << "). Getting new info for dbKey \""
+                                  << wch.dbKey() << "\" from CondDb");
+
+    SG::ReadCondHandle<GeoAlignmentStore> sctAlignStore(m_sctAlignStoreReadKey);
+
+
+    EventIDRange sctRange;
+    if(!sctAlignStore.range(sctRange)) {
+      ATH_MSG_FATAL("Failed to retrieve validity range for " << sctAlignStore.key());
+      return StatusCode::FAILURE;
+    }
+
+    // create an Acts aware geo alignment store from the one given
+    // (this makes a copy for now, which is not ideal)
+    auto actsAlignStore =
+        std::make_unique<FaserActsAlignmentStore>(**sctAlignStore);
+
+    // deltas are set, now populate sensitive element transforms
+    ATH_MSG_DEBUG("Populating FaserActsAlignmentStore for IOV");
+    size_t nElems = 0;
+    trkGeom->visitSurfaces([&actsAlignStore, &nElems](const Acts::Surface *srf) {
+      const Acts::DetectorElementBase *detElem =
+          srf->associatedDetectorElement();
+      const auto *gmde = static_cast<const FaserActsDetectorElement *>(detElem);
+      gmde->storeTransform(actsAlignStore.get());
+      nElems++;
+    });
+    ATH_MSG_DEBUG("FaserActsAlignmentStore populated for " << nElems
+                                                      << " detector elements");
+
+    // get a nominal alignment store from the tracking geometry service
+    // and plug it into a geometry context
+    auto gctx = std::make_unique<FaserActsGeometryContext>();
+    gctx->ownedAlignmentStore =
+        std::move(actsAlignStore); // GCTX owns the alignment store
+    gctx->alignmentStore = gctx->ownedAlignmentStore.get();
+
+    if (wch.record(sctRange, gctx.release()).isFailure()) {
+      ATH_MSG_ERROR("could not record alignment store "
+                    << wch.key() << " = " << gctx.get() << " with EventRange "
+                    << sctRange);
+      return StatusCode::FAILURE;
+    }
+
+    ATH_MSG_INFO("Recorded new " << wch.key() << " "
+                                       << " with range " << sctRange);
+  }
+
+
+
+  return StatusCode::SUCCESS;
+}
diff --git a/Tracking/Acts/FaserActsGeometry/src/FaserActsAlignmentStore.cxx b/Tracking/Acts/FaserActsGeometry/src/FaserActsAlignmentStore.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..1abb7d734075c8ad1892ad315f516d3ed32dcc74
--- /dev/null
+++ b/Tracking/Acts/FaserActsGeometry/src/FaserActsAlignmentStore.cxx
@@ -0,0 +1,44 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "FaserActsGeometry/FaserActsAlignmentStore.h"
+
+#include "FaserActsGeometry/FaserActsDetectorElement.h"
+
+#include "Acts/Utilities/Definitions.hpp"
+
+FaserActsAlignmentStore::FaserActsAlignmentStore(const GeoAlignmentStore &gas){
+
+  m_deltas = gas.getDeltas();
+  m_absPositions = gas.getAbsPositions();
+  m_defAbsPositions = gas.getDefAbsPositions();
+
+}
+
+void FaserActsAlignmentStore::setTransform(const FaserActsDetectorElement *ade,
+                                      const Acts::Transform3D &xf) {
+  if (!m_transforms.setTransform(ade, xf)) {
+    throw ExcAlignmentStore(
+        "Attempted to overwrite Delta in the Alignment Store");
+  }
+}
+
+const Acts::Transform3D *
+FaserActsAlignmentStore::getTransform(const FaserActsDetectorElement *ade) const {
+  return m_transforms.getTransform(ade);
+}
+
+void FaserActsAlignmentStore::append(const GeoAlignmentStore& gas) {
+  for(const auto& it : gas.getDeltas().container()) {
+    setDelta(it.first, it.second);
+  }
+
+  for(const auto& it : gas.getAbsPositions().container()) {
+    setAbsPosition(it.first, it.second);
+  }
+
+  for(const auto& it : gas.getDefAbsPositions().container()) {
+    setDefAbsPosition(it.first, it.second);
+  }
+}
diff --git a/Tracking/Acts/FaserActsGeometry/src/FaserActsDetectorElement.cxx b/Tracking/Acts/FaserActsGeometry/src/FaserActsDetectorElement.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..622f1d0b87a505fd4be48c79ba06795c65df38b8
--- /dev/null
+++ b/Tracking/Acts/FaserActsGeometry/src/FaserActsDetectorElement.cxx
@@ -0,0 +1,173 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "FaserActsGeometry/FaserActsDetectorElement.h"
+
+// ATHENA
+#include "TrkSurfaces/RectangleBounds.h"
+#include "TrkSurfaces/SurfaceBounds.h"
+#include "TrkSurfaces/TrapezoidBounds.h"
+#include "GeoPrimitives/CLHEPtoEigenConverter.h"
+
+// PACKAGE
+#include "FaserActsGeometry/FaserActsTrackingGeometrySvc.h"
+#include "FaserActsGeometry/FaserActsAlignmentStore.h"
+#include "FaserActsGeometry/FaserActsGeometryContext.h"
+#include "ActsInterop/IdentityHelper.h"
+
+// ACTS
+#include "Acts/Surfaces/StrawSurface.hpp"
+#include "Acts/Surfaces/LineBounds.hpp"
+#include "Acts/Surfaces/PlaneSurface.hpp"
+#include "Acts/Surfaces/RectangleBounds.hpp"
+#include "Acts/Surfaces/TrapezoidBounds.hpp"
+#include "Acts/Geometry/GeometryContext.hpp"
+#include "Acts/Utilities/Units.hpp"
+
+// STL
+#include <mutex>
+
+using Acts::Transform3D;
+using Acts::Surface;
+
+using namespace Acts::UnitLiterals;
+
+constexpr double length_unit = 1_mm;
+
+FaserActsDetectorElement::FaserActsDetectorElement(const TrackerDD::SiDetectorElement* detElem)
+{
+  m_detElement = detElem;
+
+  //auto center     = detElem->center();
+  auto boundsType = detElem->bounds().type();
+
+  // thickness
+  m_thickness = detElem->thickness();
+
+  if (boundsType == Trk::SurfaceBounds::Rectangle) {
+
+    const TrackerDD::SiDetectorDesign &design = detElem->design();
+    double hlX = design.width()/2. * length_unit;
+    double hlY = design.length()/2. * length_unit;
+
+    auto rectangleBounds = std::make_shared<const Acts::RectangleBounds>(hlX, hlY);
+
+    m_bounds = rectangleBounds;
+
+    m_surface = Acts::Surface::makeShared<Acts::PlaneSurface>(rectangleBounds, *this);
+
+  } else if (boundsType == Trk::SurfaceBounds::Trapezoid) {
+
+    std::string shapeString = detElem->getMaterialGeom()->getLogVol()->getShape()->type();
+    //std::cout << __FUNCTION__ << "tapezoid, GeoLogVol -> shape says: " << shapeString << std::endl;
+
+    const TrackerDD::SiDetectorDesign &design = detElem->design();
+
+    double minHlX = design.minWidth()/2. * length_unit;
+    double maxHlX = design.maxWidth()/2. * length_unit;
+    double hlY    = design.length()/2. * length_unit;
+
+    auto trapezoidBounds = std::make_shared<const Acts::TrapezoidBounds>(
+        minHlX, maxHlX, hlY);
+
+    m_bounds = trapezoidBounds;
+
+    m_surface = Acts::Surface::makeShared<Acts::PlaneSurface>(trapezoidBounds, *this);
+
+  } else {
+    throw std::domain_error("FaserActsDetectorElement does not support this surface type");
+  }
+}
+
+
+IdentityHelper
+FaserActsDetectorElement::identityHelper() const
+{
+    return IdentityHelper(m_detElement);
+}
+
+const Acts::Transform3D&
+FaserActsDetectorElement::transform(const Acts::GeometryContext& anygctx) const
+{
+  // any cast to known context type
+  const FaserActsGeometryContext* gctx = std::any_cast<const FaserActsGeometryContext*>(anygctx);
+
+  // This is needed for initial geometry construction. At that point, we don't have a
+  // consistent view of the geometry yet, and thus we can't populate an alignment store
+  // at that time.
+  if (gctx->construction) {
+    // this should only happen at initialize (1 thread, but mutex anyway)
+    return getDefaultTransformMutexed();
+  }
+
+  // unpack the alignment store from the context
+  const FaserActsAlignmentStore* alignmentStore = gctx->alignmentStore;
+
+  // no GAS, is this initialization?
+  assert(alignmentStore != nullptr);
+
+  // get the correct cached transform
+  // units should be fine here since we converted at construction
+  const Transform3D* cachedTrf = alignmentStore->getTransform(this);
+
+  assert(cachedTrf != nullptr);
+
+  return *cachedTrf;
+}
+
+void
+FaserActsDetectorElement::storeTransform(FaserActsAlignmentStore* gas) const
+{
+  Amg::Transform3D g2l
+        = m_detElement->getMaterialGeom()->getDefAbsoluteTransform()
+        * Amg::CLHEPTransformToEigen(m_detElement->recoToHitTransform());
+
+  // need to make sure translation has correct units
+  g2l.translation() *= length_unit;
+
+  gas->setTransform(this, g2l);
+  if (gas->getTransform(this) == nullptr) {
+    throw std::runtime_error("Detector element was unable to store transform in GAS");
+  }
+
+}
+
+const Acts::Transform3D&
+FaserActsDetectorElement::getDefaultTransformMutexed() const
+{
+  Amg::Transform3D g2l
+        = m_detElement->getMaterialGeom()->getDefAbsoluteTransform()
+        * Amg::CLHEPTransformToEigen(m_detElement->recoToHitTransform());
+
+  // need to make sure translation has correct units
+  g2l.translation() *= length_unit;
+
+  std::lock_guard<std::mutex> guard(m_cacheMutex);
+  if (m_defTransform) {
+    return *m_defTransform;
+  }
+  // transform not yet set
+  m_defTransform
+    = std::make_shared<const Transform3D>( g2l );
+
+  return *m_defTransform;
+}
+
+const Acts::Surface&
+FaserActsDetectorElement::surface() const
+{
+  return (*m_surface);
+}
+
+double
+FaserActsDetectorElement::thickness() const
+{
+  return m_thickness;
+}
+
+Identifier
+FaserActsDetectorElement::identify() const
+{
+  return m_detElement->identify();
+}
diff --git a/Tracking/Acts/FaserActsGeometry/src/FaserActsExtrapolationAlg.cxx b/Tracking/Acts/FaserActsGeometry/src/FaserActsExtrapolationAlg.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..5130f68e0c2ee0221fad2beb60aaf59bc29f72bb
--- /dev/null
+++ b/Tracking/Acts/FaserActsGeometry/src/FaserActsExtrapolationAlg.cxx
@@ -0,0 +1,149 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "FaserActsGeometry/FaserActsExtrapolationAlg.h"
+
+// ATHENA
+#include "AthenaKernel/RNGWrapper.h"
+#include "AthenaKernel/IAthRNGSvc.h"
+#include "GaudiKernel/EventContext.h"
+#include "GaudiKernel/ISvcLocator.h"
+#include "GaudiKernel/PhysicalConstants.h"
+
+// ACTS
+#include "Acts/Utilities/Helpers.hpp"
+#include "Acts/Propagator/detail/SteppingLogger.hpp"
+#include "Acts/Utilities/Units.hpp"
+#include "Acts/Utilities/Logger.hpp"
+#include "Acts/Surfaces/PerigeeSurface.hpp"
+
+// PACKAGE
+#include "FaserActsGeometryInterfaces/IFaserActsExtrapolationTool.h"
+#include "FaserActsGeometryInterfaces/IFaserActsTrackingGeometryTool.h"
+#include "ActsInterop/Logger.h"
+#include "FaserActsGeometry/FaserActsGeometryContext.h"
+#include "FaserActsGeometry/IFaserActsPropStepRootWriterSvc.h"
+//#include "FaserActsGeometry/IFaserActsMaterialTrackWriterSvc.h"
+
+// OTHER
+#include "CLHEP/Random/RandomEngine.h"
+
+// STL
+#include <string>
+#include <fstream>
+
+using namespace Acts::UnitLiterals;
+
+FaserActsExtrapolationAlg::FaserActsExtrapolationAlg(const std::string& name,
+                                 ISvcLocator* pSvcLocator)
+    : AthReentrantAlgorithm(name, pSvcLocator),
+      m_propStepWriterSvc("FaserActsPropStepRootWriterSvc", name),
+      m_rndmGenSvc("AthRNGSvc", name)//,
+      //m_materialTrackWriterSvc("FaserActsMaterialTrackWriterSvc", name)
+{
+}
+
+StatusCode FaserActsExtrapolationAlg::initialize() {
+
+  ATH_MSG_DEBUG(name() << "::" << __FUNCTION__);
+
+  ATH_CHECK( m_rndmGenSvc.retrieve() );
+  ATH_CHECK( m_extrapolationTool.retrieve() );
+  ATH_CHECK( m_propStepWriterSvc.retrieve() );
+
+  //if (m_writeMaterialTracks) {
+    //ATH_CHECK( m_materialTrackWriterSvc.retrieve() );
+  //}
+
+  m_objOut = std::make_unique<std::ofstream>("steps.obj");
+
+  return StatusCode::SUCCESS;
+}
+
+StatusCode FaserActsExtrapolationAlg::execute(const EventContext& ctx) const
+{
+
+  ATH_MSG_VERBOSE(name() << "::" << __FUNCTION__);
+
+  ATHRNG::RNGWrapper* rngWrapper = m_rndmGenSvc->getEngine(this);
+  rngWrapper->setSeed( name(), ctx );
+  CLHEP::HepRandomEngine* rngEngine = rngWrapper->getEngine(ctx);
+
+  ATH_MSG_VERBOSE("Extrapolating " << m_nParticlePerEvent << " particles");
+
+  for (size_t i = 0; i < m_nParticlePerEvent; i++) {
+
+  double d0 = 0;
+  double z0 = 0;
+  double phi = rngEngine->flat() * 2*M_PI - M_PI;
+  std::vector<double> etaRange = m_etaRange;
+  double etaMin = etaRange.at(0);
+  double etaMax = etaRange.at(1);
+  double eta = rngEngine->flat() * std::abs(etaMax - etaMin) + etaMin;
+
+  std::vector<double> ptRange = m_ptRange;
+  double ptMin = ptRange.at(0) * 1_GeV;
+  double ptMax = ptRange.at(1) * 1_GeV;
+
+  double pt = rngEngine->flat() * std::abs(ptMax - ptMin) + ptMin;
+
+  Acts::Vector3D momentum(
+      pt * std::cos(phi), pt * std::sin(phi), pt * std::sinh(eta));
+
+  double theta = Acts::VectorHelpers::theta(momentum);
+
+  double charge = rngEngine->flat() > 0.5 ? -1 : 1;
+
+  double qop =  charge / momentum.norm();
+
+  std::shared_ptr<Acts::PerigeeSurface> surface
+    = Acts::Surface::makeShared<Acts::PerigeeSurface>(Acts::Vector3D(0, 0, 0));
+
+  double t = 0;
+
+  Acts::BoundVector pars;
+  pars << d0, z0, phi, theta, qop, t;
+  std::optional<Acts::BoundSymMatrix> cov = std::nullopt;
+
+  if(charge != 0.) {
+      // Perigee, no alignment -> default geo context
+      FaserActsGeometryContext gctx
+        = m_extrapolationTool->trackingGeometryTool()->getNominalGeometryContext();
+      auto anygctx = gctx.any();
+      Acts::BoundParameters startParameters(anygctx,
+          std::move(cov), std::move(pars), std::move(surface));
+      auto output = m_extrapolationTool->propagationSteps(ctx, startParameters);
+      m_propStepWriterSvc->write(output.first);
+      writeStepsObj(output.first);
+  }
+
+
+  ATH_MSG_VERBOSE(name() << " execute done");
+  }
+
+  return StatusCode::SUCCESS;
+}
+
+StatusCode FaserActsExtrapolationAlg::finalize() {
+  return StatusCode::SUCCESS;
+}
+
+void FaserActsExtrapolationAlg::writeStepsObj(std::vector<Acts::detail::Step> steps) const
+{
+  std::lock_guard<std::mutex> lock(m_writeMutex);
+
+  std::ofstream& out = *m_objOut;
+  std::stringstream lstr;
+  lstr << "l";
+  for(const auto& step : steps) {
+    const auto& pos = step.position;
+    out << "v " << pos.x() << " " << pos.y() << " " << pos.z() << std::endl;
+    lstr << " " << m_objVtxCount;
+    m_objVtxCount++;
+  }
+
+  lstr << std::endl;
+
+  out << lstr.str() << std::endl;
+}
diff --git a/Tracking/Acts/FaserActsGeometry/src/FaserActsExtrapolationTool.cxx b/Tracking/Acts/FaserActsGeometry/src/FaserActsExtrapolationTool.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..d4b1b08db63c0049e3c631f53e547e90e766f3ab
--- /dev/null
+++ b/Tracking/Acts/FaserActsGeometry/src/FaserActsExtrapolationTool.cxx
@@ -0,0 +1,380 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "FaserActsGeometry/FaserActsExtrapolationTool.h"
+
+// ATHENA
+#include "GaudiKernel/IInterface.h"
+#include "GaudiKernel/PhysicalConstants.h"
+
+// PACKAGE
+#include "FaserActsGeometry/FaserActsTrackingGeometrySvc.h"
+#include "FaserActsGeometry/FaserActsTrackingGeometryTool.h"
+#include "ActsInterop/Logger.h"
+
+// ACTS
+#include "Acts/Surfaces/Surface.hpp"
+#include "Acts/Surfaces/BoundaryCheck.hpp"
+#include "Acts/Propagator/Navigator.hpp"
+#include "Acts/Propagator/EigenStepper.hpp"
+#include "Acts/Propagator/Propagator.hpp"
+#include "Acts/Propagator/AbortList.hpp"
+#include "Acts/Propagator/ActionList.hpp"
+
+// BOOST
+#include <boost/variant/variant.hpp>
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/variant/static_visitor.hpp>
+
+// STL
+#include <iostream>
+#include <memory>
+
+namespace ActsExtrapolationDetail {
+  using VariantPropagatorBase = boost::variant<
+    Acts::Propagator<Acts::EigenStepper<FASERMagneticFieldWrapper>, Acts::Navigator>,
+    Acts::Propagator<Acts::EigenStepper<Acts::ConstantBField>, Acts::Navigator>
+  >;
+
+  class VariantPropagator : public VariantPropagatorBase
+  {
+  public:
+    using VariantPropagatorBase::VariantPropagatorBase;
+  };
+
+}
+
+
+using ActsExtrapolationDetail::VariantPropagator;
+
+
+
+FaserActsExtrapolationTool::FaserActsExtrapolationTool(const std::string& type, const std::string& name,
+    const IInterface* parent)
+  : base_class(type, name, parent)
+{
+}
+
+
+FaserActsExtrapolationTool::~FaserActsExtrapolationTool()
+{
+}
+
+
+
+StatusCode
+FaserActsExtrapolationTool::initialize()
+{
+  using namespace std::literals::string_literals;
+
+
+  ATH_MSG_INFO("Initializing ACTS extrapolation");
+
+  m_logger = makeActsAthenaLogger(this, "Prop", "FaserActsExtrapTool");
+
+  ATH_CHECK( m_trackingGeometryTool.retrieve() );
+  std::shared_ptr<const Acts::TrackingGeometry> trackingGeometry
+    = m_trackingGeometryTool->trackingGeometry();
+
+  Acts::Navigator navigator(trackingGeometry);
+
+  if (m_fieldMode == "FASER") {
+    ATH_MSG_INFO("Using FASER magnetic field service");
+    using BField_t = FASERMagneticFieldWrapper;
+    ATH_CHECK( m_fieldCondObjInputKey.initialize() );
+    BField_t bField;
+    auto stepper = Acts::EigenStepper<BField_t>(std::move(bField));
+    auto propagator = Acts::Propagator<decltype(stepper), Acts::Navigator>(std::move(stepper),
+                                                                      std::move(navigator));
+    m_varProp = std::make_unique<VariantPropagator>(propagator);
+  }
+  else if (m_fieldMode == "Constant") {
+    std::vector<double> constantFieldVector = m_constantFieldVector;
+    double Bx = constantFieldVector.at(0);
+    double By = constantFieldVector.at(1);
+    double Bz = constantFieldVector.at(2);
+    ATH_MSG_INFO("Using constant magnetic field: (Bx, By, Bz) = (" << Bx << ", " << By << ", " << Bz << ")");
+    using BField_t = Acts::ConstantBField;
+    BField_t bField(Bx, By, Bz);
+    auto stepper = Acts::EigenStepper<BField_t>(std::move(bField));
+    auto propagator = Acts::Propagator<decltype(stepper), Acts::Navigator>(std::move(stepper),
+                                                                      std::move(navigator));
+    m_varProp = std::make_unique<VariantPropagator>(propagator);
+  }
+  
+  ATH_MSG_INFO("ACTS extrapolation successfully initialized");
+  return StatusCode::SUCCESS;
+}
+
+
+ActsPropagationOutput
+FaserActsExtrapolationTool::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");
+
+    Acts::MagneticFieldContext mctx = getMagneticFieldContext(ctx);
+    const FaserActsGeometryContext& gctx
+      //= m_trackingGeometryTool->getGeometryContext(ctx);
+      = m_trackingGeometryTool->getNominalGeometryContext();
+
+    auto anygctx = gctx.any();
+
+    // Action list and abort list
+    using ActionList = Acts::ActionList<SteppingLogger, Acts::MaterialInteractor, DebugOutput>;
+    using AbortConditions = Acts::AbortList<EndOfWorld>;
+    
+    using Options = Acts::PropagatorOptions<ActionList, AbortConditions>;
+    
+    Options options(anygctx, mctx, Acts::LoggerWrapper{*m_logger});
+    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;
+
+    auto& mInteractor = options.actionList.get<Acts::MaterialInteractor>();
+    mInteractor.multipleScattering = m_interactionMultiScatering;
+    mInteractor.energyLoss = m_interactionEloss;
+    mInteractor.recordInteractions = m_interactionRecord;
+
+    ActsPropagationOutput output;
+    DebugOutput::result_type debugOutput;
+    
+    auto res = boost::apply_visitor([&](const auto& propagator) -> ResultType {
+        auto result = propagator.propagate(startParameters, 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>();
+	auto materialResult = propRes.template get<Acts::MaterialInteractor::result_type>();
+	output.first = std::move(steppingResults.steps);
+	output.second = std::move(materialResult);
+        // try to force return value optimization, not sure this is necessary
+        return std::make_pair(std::move(output), std::move(debugOutput));
+        }, *m_varProp);
+
+    if (!res.ok()) {
+      ATH_MSG_ERROR("Got error during propagation:" << res.error() << " " << res.error().message()
+          << ". Returning empty step vector.");
+      return {};
+    }
+    std::tie(output, debugOutput) = std::move(*res);
+
+    if(debug) {
+      ATH_MSG_VERBOSE(debugOutput.debugString);
+    }
+
+    ATH_MSG_VERBOSE("Collected " << output.first.size() << " steps");
+    if (output.first.size() == 0) {
+       ATH_MSG_WARNING("ZERO steps returned by stepper, that is not typically a good sign");
+    }
+
+    ATH_MSG_VERBOSE(name() << "::" << __FUNCTION__ << " end");
+
+    return output;
+  }
+
+
+std::unique_ptr<const Acts::CurvilinearParameters>
+FaserActsExtrapolationTool::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 = getMagneticFieldContext(ctx);
+  const FaserActsGeometryContext& gctx
+      //= m_trackingGeometryTool->getGeometryContext(ctx);
+      = m_trackingGeometryTool->getNominalGeometryContext();
+
+  auto anygctx = gctx.any();
+
+  // Action list and abort list
+  using ActionList = Acts::ActionList<Acts::MaterialInteractor, DebugOutput>;
+  using AbortConditions = Acts::AbortList<EndOfWorld>;
+  using Options = Acts::PropagatorOptions<ActionList, AbortConditions>;
+
+  Options options(anygctx, mctx, Acts::LoggerWrapper{*m_logger});
+  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;
+
+  auto& mInteractor = options.actionList.get<Acts::MaterialInteractor>();
+  mInteractor.multipleScattering = m_interactionMultiScatering;
+  mInteractor.energyLoss = m_interactionEloss;
+  mInteractor.recordInteractions = m_interactionRecord;
+
+  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;
+}
+
+ActsPropagationOutput
+FaserActsExtrapolationTool::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 = getMagneticFieldContext(ctx);
+  const FaserActsGeometryContext& gctx
+    //= m_trackingGeometryTool->getGeometryContext(ctx);
+    = m_trackingGeometryTool->getGeometryContext(ctx );
+
+  auto anygctx = gctx.any();
+
+  // Action list and abort list
+  using ActionList = Acts::ActionList<SteppingLogger, Acts::MaterialInteractor, DebugOutput>;
+  using AbortConditions = Acts::AbortList<EndOfWorld>;
+  using Options = Acts::PropagatorOptions<ActionList, AbortConditions>;
+
+  Options options(anygctx, mctx, Acts::LoggerWrapper{*m_logger});
+  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;
+
+  auto& mInteractor = options.actionList.get<Acts::MaterialInteractor>();
+  mInteractor.multipleScattering = m_interactionMultiScatering;
+  mInteractor.energyLoss = m_interactionEloss;
+  mInteractor.recordInteractions = m_interactionRecord;
+
+  ActsPropagationOutput output;
+  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>();
+      auto materialResult = propRes.template get<Acts::MaterialInteractor::result_type>();
+      output.first = std::move(steppingResults.steps);
+      output.second = std::move(materialResult);
+      return std::make_pair(std::move(output), std::move(debugOutput));
+    }, *m_varProp);
+
+  if (!res.ok()) {
+    ATH_MSG_ERROR("Got error during propagation:" << res.error() << res.error().message()
+                  << ". Returning empty step vector.");
+    return {};
+  }
+  std::tie(output, debugOutput) = std::move(*res);
+
+  if(debug) {
+    ATH_MSG_VERBOSE(debugOutput.debugString);
+  }
+
+  ATH_MSG_VERBOSE("Collected " << output.first.size() << " steps");
+  if (output.first.size() == 0) {
+     ATH_MSG_WARNING("ZERO steps returned by stepper, that is not typically a good sign");
+  }
+
+  ATH_MSG_VERBOSE(name() << "::" << __FUNCTION__ << " end");
+
+  return output;
+}
+
+std::unique_ptr<const Acts::BoundParameters>
+FaserActsExtrapolationTool::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 = getMagneticFieldContext(ctx);
+  const FaserActsGeometryContext& gctx
+    //= m_trackingGeometryTool->getGeometryContext(ctx);
+    = m_trackingGeometryTool->getGeometryContext(ctx);
+
+  auto anygctx = gctx.any();
+
+  // Action list and abort list
+  using ActionList = Acts::ActionList<Acts::MaterialInteractor, DebugOutput>;
+  using AbortConditions = Acts::AbortList<EndOfWorld>;
+  using Options = Acts::PropagatorOptions<ActionList, AbortConditions>;
+
+  Options options(anygctx, mctx, Acts::LoggerWrapper{*m_logger});
+  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;
+
+  auto& mInteractor = options.actionList.get<Acts::MaterialInteractor>();
+  mInteractor.multipleScattering = m_interactionMultiScatering;
+  mInteractor.energyLoss = m_interactionEloss;
+  mInteractor.recordInteractions = m_interactionRecord;
+
+  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;
+}
+
+Acts::MagneticFieldContext FaserActsExtrapolationTool::getMagneticFieldContext(const EventContext& ctx) const {
+  SG::ReadCondHandle<FaserFieldCacheCondObj> readHandle{m_fieldCondObjInputKey, ctx};
+  if (!readHandle.isValid()) {
+     std::stringstream msg;
+     msg << "Failed to retrieve magnetic field condition data " << m_fieldCondObjInputKey.key() << ".";
+     throw std::runtime_error(msg.str());
+  }
+  const FaserFieldCacheCondObj* fieldCondObj{*readHandle};
+
+  return Acts::MagneticFieldContext(fieldCondObj);
+}
+
diff --git a/Tracking/Acts/FaserActsGeometry/src/FaserActsLayerBuilder.cxx b/Tracking/Acts/FaserActsGeometry/src/FaserActsLayerBuilder.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..f714148940079b8a10357b93b65c13c2b2328f10
--- /dev/null
+++ b/Tracking/Acts/FaserActsGeometry/src/FaserActsLayerBuilder.cxx
@@ -0,0 +1,201 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+// ATHENA
+#include "TrackerReadoutGeometry/SiDetectorElement.h"
+#include "TrackerReadoutGeometry/SiDetectorElementCollection.h"
+#include "TrackerReadoutGeometry/SCT_DetectorManager.h"
+
+// PACKAGE
+#include "FaserActsGeometry/FaserActsLayerBuilder.h"
+#include "FaserActsGeometry/FaserActsDetectorElement.h"
+#include "FaserActsGeometry/CuboidVolumeBuilder.h"
+#include "ActsInterop/IdentityHelper.h"
+
+// ACTS
+#include "Acts/Material/ProtoSurfaceMaterial.hpp"
+#include "Acts/Surfaces/CylinderSurface.hpp"
+#include "Acts/Surfaces/PlaneSurface.hpp"
+#include "Acts/Surfaces/RectangleBounds.hpp"
+#include "Acts/Geometry/GenericApproachDescriptor.hpp"
+#include "Acts/Geometry/ApproachDescriptor.hpp"
+#include "Acts/Geometry/ProtoLayer.hpp"
+#include "Acts/Geometry/LayerCreator.hpp"
+#include "Acts/Geometry/GeometryContext.hpp"
+#include "Acts/Utilities/Units.hpp"
+#include "Acts/Utilities/Definitions.hpp"
+#include "Acts/Utilities/BinningType.hpp"
+
+using Acts::Surface;
+using Acts::Transform3D;
+using Acts::Translation3D;
+
+using namespace Acts::UnitLiterals;
+
+FaserActs::CuboidVolumeBuilder::Config FaserActsLayerBuilder::buildVolume(const Acts::GeometryContext& gctx)
+{
+  //Acts::CuboidVolumeBuilder::Config cvbConfig;
+  FaserActs::CuboidVolumeBuilder::Config cvbConfig;
+  //std::vector<Acts::CuboidVolumeBuilder::VolumeConfig> volumeConfigs = {};
+  std::vector<FaserActs::CuboidVolumeBuilder::VolumeConfig> volumeConfigs = {};
+  
+
+  for (int iStation=1; iStation<4; iStation++) {
+
+      //Acts::CuboidVolumeBuilder::VolumeConfig volumeConfig;
+      FaserActs::CuboidVolumeBuilder::VolumeConfig volumeConfig;
+
+      //std::vector<Acts::CuboidVolumeBuilder::LayerConfig> layerConfigs;
+      std::vector<FaserActs::CuboidVolumeBuilder::LayerConfig> layerConfigs;
+      layerConfigs.clear();
+
+      for (int iPlane=0; iPlane<3; iPlane++) {
+
+         m_cfg.station = iStation;
+         m_cfg.plane = iPlane;
+         std::vector<std::shared_ptr<const Acts::Surface>> surfaces;
+         surfaces.clear();
+
+
+        //Acts::CuboidVolumeBuilder::SurfaceConfig surfacecfg;
+        FaserActs::CuboidVolumeBuilder::SurfaceConfig surfacecfg;
+    
+        //Acts::CuboidVolumeBuilder::LayerConfig layercfg;
+        FaserActs::CuboidVolumeBuilder::LayerConfig layercfg;
+        layercfg.binsX = 2;
+        layercfg.binsY = 4;
+
+        buildLayers(gctx, surfaces, layercfg, surfacecfg);
+
+	layercfg.surfaceCfg = surfacecfg;
+        layercfg.active = true;
+
+        layercfg.surfaces = surfaces;
+        layerConfigs.push_back(layercfg);
+
+        if (iPlane == 1) {
+          volumeConfig.position = Acts::Vector3D(0, 0, surfacecfg.position.z()); 
+        }
+        if (iStation == 0 && iPlane == 1) { 
+	  cvbConfig.position  = Acts::Vector3D(0, 0, surfacecfg.position.z());
+        }
+    }
+
+      volumeConfig.length   = m_trackerDimensions;
+      volumeConfig.layerCfg = layerConfigs;
+      volumeConfig.name     = "Station_" + std::to_string(iStation);
+      volumeConfigs.push_back(volumeConfig);
+  }
+    
+  //cvbConfig.position  = m_worldCenter;
+  cvbConfig.length    = m_worldDimensions;
+  cvbConfig.volumeCfg = volumeConfigs;
+
+  return cvbConfig;
+}
+
+void
+FaserActsLayerBuilder::buildLayers(const Acts::GeometryContext& gctx,
+    std::vector<std::shared_ptr<const Surface>>& surfaces,
+    FaserActs::CuboidVolumeBuilder::LayerConfig& layercfg,
+    FaserActs::CuboidVolumeBuilder::SurfaceConfig& surfacecfg)
+{
+
+  auto siDetMng = static_cast<const TrackerDD::SCT_DetectorManager*>(m_cfg.mng);
+  
+  for (int iRow = 0; iRow < 4; iRow++) {
+     for (int iModule = -1; iModule < 2; iModule++) {
+        for (int iSensor = 0; iSensor < 2; iSensor++) {
+        //for (int iSensor = 0; iSensor < 1; iSensor++) {  // only use the first sensor to construct the surface
+
+	   if (iModule == 0) continue;
+	   const TrackerDD::SiDetectorElement* siDetElement = siDetMng->getDetectorElement(m_cfg.station, m_cfg.plane, iRow, iModule, iSensor) ;
+
+           if (logger().doPrint(Acts::Logging::VERBOSE)) {
+	     ACTS_VERBOSE("Found SCT sensor (" << m_cfg.station << "/" << m_cfg.plane << "/" << iRow << "/" << iModule << "/" << iSensor << ") with global center at (" << siDetElement->center().x() << ", " << siDetElement->center().y() << ", " << siDetElement->center().z() << ")." );
+	   }
+
+           auto element = std::make_shared<const FaserActsDetectorElement>(siDetElement);
+
+           surfaces.push_back(element->surface().getSharedPtr());
+
+           m_cfg.elementStore->push_back(element);
+    
+           m_ModuleWidth = siDetElement->width();
+           m_ModuleLength = siDetElement->length();
+       }
+     }
+  }
+
+
+  Acts::ProtoLayer pl(gctx, surfaces);
+
+  if (logger().doPrint(Acts::Logging::VERBOSE)) {
+      ACTS_VERBOSE(" Plane's zMin / zMax: " << pl.min(Acts::binZ) << " / " << pl.max(Acts::binZ));
+  }
+
+  std::shared_ptr<const Acts::ProtoSurfaceMaterial> materialProxy = nullptr;
+
+  double layerZ = 0.5 * (pl.min(Acts::binZ) + pl.max(Acts::binZ));
+  double layerThickness = (pl.max(Acts::binZ) - pl.min(Acts::binZ));
+  double layerZInner = layerZ - layerThickness/2.;
+  double layerZOuter = layerZ + layerThickness/2.;
+
+  surfacecfg.position = Acts::Vector3D(0, 0, layerZ);
+
+  if (std::abs(layerZInner) > std::abs(layerZOuter)) std::swap(layerZInner, layerZOuter);
+
+      auto rBounds = std::make_shared<const Acts::RectangleBounds>( 0.5*layercfg.binsY*m_ModuleWidth, 0.5*layercfg.binsX*m_ModuleLength ) ;
+
+      auto transformNominal
+        = std::make_shared<const Transform3D>(Translation3D(0., 0., layerZ));
+      
+      auto transformInner
+        = std::make_shared<const Transform3D>(Translation3D(0., 0., layerZInner));
+      
+      auto transformOuter
+        = std::make_shared<const Transform3D>(Translation3D(0., 0., layerZOuter));
+
+      std::shared_ptr<Acts::PlaneSurface> innerBoundary 
+        = Acts::Surface::makeShared<Acts::PlaneSurface>(transformInner, rBounds);
+      
+      std::shared_ptr<Acts::PlaneSurface> nominalSurface 
+        = Acts::Surface::makeShared<Acts::PlaneSurface>(transformNominal, rBounds);
+      
+      std::shared_ptr<Acts::PlaneSurface> outerBoundary 
+        = Acts::Surface::makeShared<Acts::PlaneSurface>(transformOuter, rBounds);
+
+      size_t matBinsX = layercfg.binsX;
+      size_t matBinsY = layercfg.binsY;
+
+      Acts::BinUtility materialBinUtil(
+          matBinsX, -0.5*layercfg.binsY*m_ModuleWidth, 0.5*layercfg.binsY*m_ModuleWidth, Acts::open, Acts::binX);
+      materialBinUtil += Acts::BinUtility(
+          matBinsY, -0.5*layercfg.binsX*m_ModuleLength, 0.5*layercfg.binsX*m_ModuleLength, Acts::open, Acts::binY, transformInner);
+      
+      materialProxy
+        = std::make_shared<const Acts::ProtoSurfaceMaterial>(materialBinUtil);
+
+      ACTS_VERBOSE("[L] Layer is marked to carry support material on Surface ( "
+          "inner=0 / center=1 / outer=2 ) : " << "inner");
+      ACTS_VERBOSE("with binning: [" << matBinsX << ", " << matBinsY << "]");
+
+      ACTS_VERBOSE("Created ApproachSurfaces for layer at:");
+      ACTS_VERBOSE(" - inner:   Z=" << layerZInner);
+      ACTS_VERBOSE(" - central: Z=" << layerZ);
+      ACTS_VERBOSE(" - outer:   Z=" << layerZOuter);
+      
+
+      // set material on inner
+      // @TODO: make this configurable somehow
+      innerBoundary->assignSurfaceMaterial(materialProxy);
+
+      std::vector<std::shared_ptr<const Acts::Surface>> aSurfaces;
+      aSurfaces.push_back(std::move(innerBoundary));
+      aSurfaces.push_back(std::move(nominalSurface));
+      aSurfaces.push_back(std::move(outerBoundary));
+
+      layercfg.approachDescriptor = new Acts::GenericApproachDescriptor(aSurfaces);
+      
+}
+
diff --git a/Tracking/Acts/FaserActsGeometry/src/FaserActsObjWriterTool.cxx b/Tracking/Acts/FaserActsGeometry/src/FaserActsObjWriterTool.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..61a84e4c5d2617225261c85fdbb0a3195340c21b
--- /dev/null
+++ b/Tracking/Acts/FaserActsGeometry/src/FaserActsObjWriterTool.cxx
@@ -0,0 +1,86 @@
+/*
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "FaserActsGeometry/FaserActsObjWriterTool.h"
+
+// std
+#include <iostream>
+#include <vector>
+
+// Gaudi / Athena
+#include "GaudiKernel/IInterface.h"
+
+#include "FaserActsGeometry/FaserActsGeometryContext.h"
+// ACTS
+#include "Acts/Geometry/TrackingGeometry.hpp"
+
+// PRIVATE
+#include "util/ObjSurfaceWriter.h"
+#include "util/ObjTrackingGeometryWriter.h"
+
+FaserActsObjWriterTool::FaserActsObjWriterTool(const std::string& type, const std::string& name,
+    const IInterface* parent)
+  : AthAlgTool(type, name, parent)
+{
+  //declareProperty("OutputDirectory", m_outputDirectory = "");
+  //declareProperty("SubDetectors", m_subDetectors = {});
+}
+
+StatusCode
+FaserActsObjWriterTool::initialize()
+{
+
+
+  return StatusCode::SUCCESS;
+}
+
+void
+FaserActsObjWriterTool::write(const FaserActsGeometryContext& gctx, const Acts::TrackingGeometry& tg) const
+{
+
+  const auto& ctx = Gaudi::Hive::currentContext();
+  std::stringstream ss;
+  ss << ctx.eventID().run_number() << "_" << ctx.eventID().event_number();
+
+  using namespace std::string_literals;
+
+  std::vector<std::shared_ptr<Acts::ObjSurfaceWriter>> subWriters;
+  std::vector<std::shared_ptr<std::ofstream>>           subStreams;
+
+  for (const auto& sdet : m_subDetectors) {
+    auto        sdStream = std::shared_ptr<std::ofstream>(new std::ofstream);
+    std::string sdOutputName = m_outputDirectory + "/"s + sdet + "_" + ss.str() + ".obj"s;
+    sdStream->open(sdOutputName);
+    // object surface writers
+    Acts::ObjSurfaceWriter::Config sdObjWriterConfig(sdet,
+        Acts::Logging::INFO);
+    sdObjWriterConfig.filePrefix         = "";
+    sdObjWriterConfig.outputPhiSegments  = 10;
+    sdObjWriterConfig.outputPrecision    = 6;
+    sdObjWriterConfig.outputScalor       = 1.;
+    sdObjWriterConfig.outputThickness    = 1.;
+    sdObjWriterConfig.outputSensitive    = true;
+    sdObjWriterConfig.outputLayerSurface = false;
+    sdObjWriterConfig.outputStream       = sdStream;
+    auto sdObjWriter
+      = std::make_shared<Acts::ObjSurfaceWriter>(sdObjWriterConfig);
+    // push back
+    subWriters.push_back(sdObjWriter);
+    subStreams.push_back(sdStream);
+  }
+
+
+  // configure the tracking geometry writer
+  Acts::ObjTrackingGeometryWriter::Config tgObjWriterConfig(
+      "ObjTrackingGeometryWriter", Acts::Logging::INFO);
+  tgObjWriterConfig.surfaceWriters       = subWriters;
+  tgObjWriterConfig.filePrefix           = "";
+  tgObjWriterConfig.sensitiveGroupPrefix = "";
+  tgObjWriterConfig.layerPrefix          = "";
+  // the tracking geometry writers
+  auto tgObjWriter
+    = std::make_shared<Acts::ObjTrackingGeometryWriter>(tgObjWriterConfig);
+
+  tgObjWriter->write(gctx.any(), tg);
+}
diff --git a/Tracking/Acts/FaserActsGeometry/src/FaserActsPropStepRootWriterSvc.cxx b/Tracking/Acts/FaserActsGeometry/src/FaserActsPropStepRootWriterSvc.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..44e93ff0e3c1234d996e207d1d59e507a0c05e56
--- /dev/null
+++ b/Tracking/Acts/FaserActsGeometry/src/FaserActsPropStepRootWriterSvc.cxx
@@ -0,0 +1,182 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "FaserActsGeometry/FaserActsPropStepRootWriterSvc.h"
+#include "GaudiKernel/IInterface.h"
+
+#include "Acts/Propagator/detail/SteppingLogger.hpp"
+#include "Acts/Geometry/TrackingVolume.hpp"
+
+
+#include <vector>
+#include <deque>
+#include <mutex>
+#include <thread>
+
+#include "TTree.h"
+#include "TFile.h"
+
+FaserActsPropStepRootWriterSvc::FaserActsPropStepRootWriterSvc( const std::string& name, ISvcLocator* svc )
+: base_class(name, svc) {
+}
+
+StatusCode
+FaserActsPropStepRootWriterSvc::initialize()
+{
+
+  ATH_MSG_INFO("Starting writer thread");
+  m_doEnd = false;
+  m_writeThread = std::thread(&FaserActsPropStepRootWriterSvc::writeThread, this);
+
+  std::string filePath = m_filePath;
+  m_outputFile = TFile::Open(filePath.c_str(), "RECREATE");
+  if(m_outputFile == nullptr) {
+    ATH_MSG_ERROR("Unable to open output file at " << m_filePath);
+    return StatusCode::FAILURE;
+  }
+  m_outputFile->cd();
+
+  std::string treeName = m_treeName;
+  m_outputTree = new TTree(treeName.c_str(), "Acts Propagation Steps");
+  if(m_outputTree == nullptr) {
+    ATH_MSG_ERROR("Unable to create TTree");
+    return StatusCode::FAILURE;
+  }
+
+  m_outputTree->Branch("event_nr", &m_eventNum);
+  m_outputTree->Branch("step_x", &m_s_pX);
+  m_outputTree->Branch("step_y", &m_s_pY);
+  m_outputTree->Branch("step_z", &m_s_pZ);
+  m_outputTree->Branch("step_r", &m_s_pR);
+  m_outputTree->Branch("volume_id", &m_s_volumeID);
+  m_outputTree->Branch("boundary_id", &m_s_boundaryID);
+  m_outputTree->Branch("layer_id", &m_s_layerID);
+  m_outputTree->Branch("approach_id", &m_s_approachID);
+  m_outputTree->Branch("sensitive_id", &m_s_sensitiveID);
+
+
+  return StatusCode::SUCCESS;
+}
+  
+StatusCode 
+FaserActsPropStepRootWriterSvc::finalize()
+{
+  ATH_MSG_INFO("Waiting for writer thread to finish.");
+  m_doEnd = true;
+  m_writeThread.join();
+  ATH_MSG_INFO("Writer thread has terminated.");
+
+  return StatusCode::SUCCESS;
+}
+
+void 
+FaserActsPropStepRootWriterSvc::write(const StepVector& steps)
+{
+  
+  auto ctx = Gaudi::Hive::currentContext();
+
+  std::lock_guard<std::mutex> lock(m_writeMutex);
+
+  //for(size_t i=0;i<ecells.size();++i) {
+    //m_queue.emplace_back(ctx.eventID().event_number(), std::move(ecells[i]));
+  //}
+  m_queue.emplace_back(ctx.eventID().event_number(), steps);
+}
+
+void
+FaserActsPropStepRootWriterSvc::writeThread()
+{
+  using namespace std::chrono_literals;
+  // wait until we have events
+  while(m_queue.size() == 0) {
+    std::this_thread::sleep_for(2s);
+    if (m_doEnd) return;
+  }
+
+  while(true) {
+    std::unique_lock<std::mutex> lock(m_writeMutex);
+    
+    if (m_queue.empty()) {
+      lock.unlock();
+      if (!m_doEnd) {
+        std::this_thread::sleep_for(0.5s);
+        continue;
+      } else {
+        ATH_MSG_INFO("Writer thread caught termination signal. Shutting down.");
+        end();
+        return;
+      }
+    }
+
+    queue_item_t queue_item = std::move(m_queue.front());
+    m_queue.pop_front();
+
+    lock.unlock();
+    
+    size_t eventNum = queue_item.first;
+    StepVector steps = std::move(queue_item.second);
+
+    doWrite(steps, eventNum);
+  }
+
+}
+
+void
+FaserActsPropStepRootWriterSvc::doWrite(const StepVector& steps, size_t evtNum)
+{
+  using ag = Acts::GeometryID;
+
+  m_eventNum = evtNum;
+  m_s_pX.clear();
+  m_s_pY.clear();
+  m_s_pZ.clear();
+  m_s_pR.clear();
+  m_s_volumeID.clear();
+  m_s_boundaryID.clear();
+  m_s_layerID.clear();
+  m_s_approachID.clear();
+  m_s_sensitiveID.clear();
+
+  for(const auto& step : steps) {
+      Acts::GeometryID::Value volumeID    = 0;
+      Acts::GeometryID::Value boundaryID  = 0;
+      Acts::GeometryID::Value layerID     = 0;
+      Acts::GeometryID::Value approachID  = 0;
+      Acts::GeometryID::Value sensitiveID = 0;
+      // get the identification from the surface first
+      if (step.surface) {
+        auto geoID  = step.surface->geoID();
+        sensitiveID = geoID.sensitive();
+        approachID  = geoID.approach();
+        layerID     = geoID.layer();
+        boundaryID  = geoID.boundary();
+        volumeID    = geoID.volume();
+      }
+      // a current volume overwrites the surface tagged one
+      if (step.volume) {
+        volumeID = step.volume->geoID().volume();
+      }
+      // now fill
+      m_s_sensitiveID.push_back(sensitiveID);
+      m_s_approachID.push_back(approachID);
+      m_s_layerID.push_back(layerID);
+      m_s_boundaryID.push_back(boundaryID);
+      m_s_volumeID.push_back(volumeID);
+
+      m_s_pX.push_back(step.position.x());
+      m_s_pY.push_back(step.position.y());
+      m_s_pZ.push_back(step.position.z());
+      m_s_pR.push_back(Acts::VectorHelpers::perp(step.position));
+  }
+  
+  m_outputTree->Fill();
+}
+
+void
+FaserActsPropStepRootWriterSvc::end()
+{
+  m_outputFile->cd();
+  m_outputTree->Write();
+  //m_outputFile->Close();
+}
diff --git a/Tracking/Acts/FaserActsGeometry/src/FaserActsTrackingGeometrySvc.cxx b/Tracking/Acts/FaserActsGeometry/src/FaserActsTrackingGeometrySvc.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..fe4e3a99fc7604fac4b523cf6413e2a0239886fb
--- /dev/null
+++ b/Tracking/Acts/FaserActsGeometry/src/FaserActsTrackingGeometrySvc.cxx
@@ -0,0 +1,157 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "FaserActsGeometry/FaserActsTrackingGeometrySvc.h"
+
+// ATHENA
+#include "TrackerReadoutGeometry/SCT_DetectorManager.h"
+#include "StoreGate/StoreGateSvc.h"
+#include "GaudiKernel/EventContext.h"
+#include "TrackerIdentifier/FaserSCT_ID.h"
+
+// ACTS
+#include "Acts/Geometry/GeometryContext.hpp"
+#include "Acts/Geometry/TrackingGeometry.hpp"
+#include "Acts/Geometry/ITrackingVolumeBuilder.hpp"
+#include "Acts/Geometry/LayerArrayCreator.hpp"
+#include "Acts/Geometry/SurfaceArrayCreator.hpp"
+#include "Acts/Geometry/LayerCreator.hpp"
+#include "Acts/Geometry/TrackingVolumeArrayCreator.hpp"
+#include "Acts/Geometry/CylinderVolumeHelper.hpp"
+#include "Acts/Geometry/TrackingGeometryBuilder.hpp"
+#include "Acts/Geometry/CylinderVolumeBuilder.hpp"
+//#include "Acts/Geometry/CuboidVolumeBuilder.hpp"
+#include "FaserActsGeometry/CuboidVolumeBuilder.h"
+#include "Acts/ActsVersion.hpp"
+#include "Acts/Utilities/Units.hpp"
+
+// PACKAGE
+#include "FaserActsGeometry/FaserActsLayerBuilder.h"
+#include "FaserActsGeometry/FaserActsDetectorElement.h"
+#include "FaserActsGeometry/FaserActsAlignmentStore.h"
+#include "FaserActsGeometry/FaserActsGeometryContext.h"
+#include "ActsInterop/IdentityHelper.h"
+#include "ActsInterop/Logger.h"
+
+using namespace Acts::UnitLiterals;
+
+FaserActsTrackingGeometrySvc::FaserActsTrackingGeometrySvc(const std::string& name, ISvcLocator* svc)
+   : base_class(name,svc),
+   m_detStore("StoreGateSvc/DetectorStore", name)
+{
+  m_elementStore = std::make_shared<std::vector<std::shared_ptr<const FaserActsDetectorElement>>>();
+}
+
+StatusCode
+FaserActsTrackingGeometrySvc::initialize()
+{
+  ATH_MSG_INFO(name() << " is initializing");
+  ATH_MSG_INFO("Acts version is: v" << Acts::VersionMajor << "."
+                                    << Acts::VersionMinor << "."
+                                    << Acts::VersionPatch
+                                    << " [" << Acts::CommitHash << "]");
+
+  ATH_CHECK ( m_detStore->retrieve(p_SCTManager, "SCT") );
+
+  Acts::LayerArrayCreator::Config lacCfg;
+  auto layerArrayCreator = std::make_shared<const Acts::LayerArrayCreator>(
+      lacCfg, makeActsAthenaLogger(this, "LayArrCrtr", "ActsTGSvc"));
+
+  Acts::TrackingVolumeArrayCreator::Config tvcCfg;
+  auto trackingVolumeArrayCreator
+      = std::make_shared<const Acts::TrackingVolumeArrayCreator>(
+          tvcCfg, makeActsAthenaLogger(this, "TrkVolArrCrtr", "ActsTGSvc"));
+
+  Acts::CylinderVolumeHelper::Config cvhConfig;
+  cvhConfig.layerArrayCreator          = layerArrayCreator;
+  cvhConfig.trackingVolumeArrayCreator = trackingVolumeArrayCreator;
+
+  auto cylinderVolumeHelper
+    = std::make_shared<const Acts::CylinderVolumeHelper>(
+        cvhConfig, makeActsAthenaLogger(this, "CylVolHlpr", "ActsTGSvc"));
+
+  Acts::TrackingGeometryBuilder::Config tgbConfig;
+  try {
+    // SCT
+    tgbConfig.trackingVolumeBuilders.push_back([&](
+          const auto& gctx, const auto& /*inner*/, const auto&) {
+        auto tv = makeVolumeBuilder(gctx, p_SCTManager);
+        return tv->trackingVolume(gctx);
+    });
+
+  }
+  catch (const std::invalid_argument& e) {
+    ATH_MSG_ERROR(e.what());
+    return StatusCode::FAILURE;
+  }
+
+
+  auto trackingGeometryBuilder
+      = std::make_shared<const Acts::TrackingGeometryBuilder>(tgbConfig,
+          makeActsAthenaLogger(this, "TrkGeomBldr", "ActsTGSvc"));
+
+
+  // default geometry context, this is nominal
+  FaserActsGeometryContext constructionContext;
+  constructionContext.construction = true;
+
+  m_trackingGeometry = trackingGeometryBuilder
+    ->trackingGeometry(constructionContext.any());
+
+  ATH_MSG_VERBOSE("Building nominal alignment store");
+  FaserActsAlignmentStore* nominalAlignmentStore = new FaserActsAlignmentStore();
+
+  populateAlignmentStore(nominalAlignmentStore);
+
+  // manage ownership
+  m_nominalAlignmentStore = std::unique_ptr<const FaserActsAlignmentStore>(nominalAlignmentStore);
+
+  ATH_MSG_INFO("Acts TrackingGeometry construction completed");
+
+  return StatusCode::SUCCESS;
+}
+
+std::shared_ptr<const Acts::TrackingGeometry>
+FaserActsTrackingGeometrySvc::trackingGeometry() {
+
+  ATH_MSG_VERBOSE("Retrieving tracking geometry");
+  return m_trackingGeometry;
+}
+
+std::shared_ptr<const Acts::ITrackingVolumeBuilder>
+FaserActsTrackingGeometrySvc::makeVolumeBuilder(const Acts::GeometryContext& gctx, const TrackerDD::SCT_DetectorManager* manager)
+{
+  std::string managerName = manager->getName();
+
+  std::shared_ptr<FaserActsLayerBuilder> gmLayerBuilder;
+
+  FaserActsLayerBuilder::Config cfg;
+  cfg.subdetector = FaserActsDetectorElement::Subdetector::SCT;
+  cfg.mng = static_cast<const TrackerDD::SCT_DetectorManager*>(manager);
+  cfg.elementStore = m_elementStore;
+  gmLayerBuilder = std::make_shared<FaserActsLayerBuilder>(cfg,
+      makeActsAthenaLogger(this, "GMLayBldr", "ActsTGSvc"));
+  auto cvbConfig = gmLayerBuilder->buildVolume(gctx);
+  auto cvb = std::make_shared<const FaserActs::CuboidVolumeBuilder>(cvbConfig);
+
+  return cvb;
+}
+
+void
+FaserActsTrackingGeometrySvc::populateAlignmentStore(FaserActsAlignmentStore *store) const
+{
+  // populate the alignment store with all detector elements
+  m_trackingGeometry->visitSurfaces(
+    [store](const Acts::Surface* srf) {
+    const Acts::DetectorElementBase* detElem = srf->associatedDetectorElement();
+    const auto* gmde = dynamic_cast<const FaserActsDetectorElement*>(detElem);
+    gmde->storeTransform(store);
+  });
+}
+
+const FaserActsAlignmentStore*
+FaserActsTrackingGeometrySvc::getNominalAlignmentStore() const
+{
+  return m_nominalAlignmentStore.get();
+}
diff --git a/Tracking/Acts/FaserActsGeometry/src/FaserActsTrackingGeometryTool.cxx b/Tracking/Acts/FaserActsGeometry/src/FaserActsTrackingGeometryTool.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..ae50ea2756e3c705f6eb9f1942849c6c9ec5b331
--- /dev/null
+++ b/Tracking/Acts/FaserActsGeometry/src/FaserActsTrackingGeometryTool.cxx
@@ -0,0 +1,64 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "FaserActsGeometry/FaserActsTrackingGeometryTool.h"
+
+// ATHENA
+#include "GaudiKernel/EventContext.h"
+
+// PACKAGE
+#include "FaserActsGeometry/FaserActsAlignmentStore.h"
+#include "FaserActsGeometryInterfaces/IFaserActsTrackingGeometrySvc.h"
+
+// STL
+#include <iostream>
+#include <memory>
+
+FaserActsTrackingGeometryTool::FaserActsTrackingGeometryTool(const std::string& type, const std::string& name,
+    const IInterface* parent) 
+  : base_class(type, name, parent),
+    m_trackingGeometrySvc("FaserActsTrackingGeometrySvc", name)
+{
+}
+
+StatusCode
+FaserActsTrackingGeometryTool::initialize()
+{
+  ATH_MSG_INFO(name() << " initializing");
+
+  ATH_CHECK( m_trackingGeometrySvc.retrieve() );
+
+  ATH_CHECK( m_rchk.initialize() );
+
+  return StatusCode::SUCCESS;
+}
+
+std::shared_ptr<const Acts::TrackingGeometry>
+FaserActsTrackingGeometryTool::trackingGeometry() const
+{
+  return m_trackingGeometrySvc->trackingGeometry();
+}
+
+const FaserActsGeometryContext&
+FaserActsTrackingGeometryTool::getGeometryContext(const EventContext& ctx) const
+{
+  ATH_MSG_DEBUG("Creating alignment context for event");
+  SG::ReadCondHandle<FaserActsGeometryContext> rch(m_rchk, ctx);
+
+  if(!rch.isValid()) {
+    ATH_MSG_ERROR("Creating alignment context failed: read cond handle invalid!");
+  }
+
+  return **rch;
+}
+
+FaserActsGeometryContext
+FaserActsTrackingGeometryTool::getNominalGeometryContext() const
+{
+
+  FaserActsGeometryContext gctx;
+  gctx.alignmentStore = m_trackingGeometrySvc->getNominalAlignmentStore();
+
+  return gctx;
+}
diff --git a/Tracking/Acts/FaserActsGeometry/src/FaserActsWriteTrackingGeometry.cxx b/Tracking/Acts/FaserActsGeometry/src/FaserActsWriteTrackingGeometry.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..3e05c12a23433253b0050966f530103aa017c656
--- /dev/null
+++ b/Tracking/Acts/FaserActsGeometry/src/FaserActsWriteTrackingGeometry.cxx
@@ -0,0 +1,49 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+#include "FaserActsGeometry/FaserActsWriteTrackingGeometry.h"
+
+// ATHENA
+#include "AthenaKernel/RNGWrapper.h"
+#include "Acts/Utilities/Logger.hpp"
+#include "AthenaBaseComps/AthReentrantAlgorithm.h"
+#include "GaudiKernel/ISvcLocator.h"
+
+// PACKAGE
+#include "FaserActsGeometryInterfaces/IFaserActsTrackingGeometrySvc.h"
+#include "FaserActsGeometry/FaserActsGeometryContext.h"
+#include "ActsInterop/Logger.h"
+
+// STL
+#include <string>
+
+FaserActsWriteTrackingGeometry::FaserActsWriteTrackingGeometry(const std::string& name,
+                                 ISvcLocator* pSvcLocator)
+    : AthReentrantAlgorithm(name, pSvcLocator)
+{
+}
+
+StatusCode FaserActsWriteTrackingGeometry::initialize() {
+  ATH_MSG_INFO("initializing");
+
+  ATH_CHECK(m_objWriterTool.retrieve());
+  ATH_CHECK(m_trackingGeometryTool.retrieve());
+
+  return StatusCode::SUCCESS;
+}
+
+StatusCode FaserActsWriteTrackingGeometry::execute(const EventContext& /*ctx*/ ) const {
+  auto trackingGeometry = m_trackingGeometryTool->trackingGeometry();
+
+  // Use nominal context
+  //FaserActsGeometryContext defGctx;
+  //const FaserActsGeometryContext& gctx = m_trackingGeometryTool->getGeometryContext(ctx);
+  const FaserActsGeometryContext& gctx = m_trackingGeometryTool->getNominalGeometryContext();
+
+  m_objWriterTool->write(gctx, *trackingGeometry);
+  return StatusCode::SUCCESS;
+}
+
+StatusCode FaserActsWriteTrackingGeometry::finalize() {
+  return StatusCode::SUCCESS;
+}
diff --git a/Tracking/Acts/FaserActsGeometry/src/FaserNominalAlignmentCondAlg.cxx b/Tracking/Acts/FaserActsGeometry/src/FaserNominalAlignmentCondAlg.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..b63cf8d48290c78204ed0a04670a412047a05b18
--- /dev/null
+++ b/Tracking/Acts/FaserActsGeometry/src/FaserNominalAlignmentCondAlg.cxx
@@ -0,0 +1,103 @@
+/*
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "FaserActsGeometry/FaserNominalAlignmentCondAlg.h"
+
+// ATHENA
+#include "StoreGate/WriteCondHandle.h"
+#include "GaudiKernel/ServiceHandle.h"
+#include "GaudiKernel/EventIDBase.h"
+#include "GaudiKernel/EventIDRange.h"
+
+// PACKAGE
+#include "FaserActsGeometryInterfaces/IFaserActsTrackingGeometrySvc.h"
+#include "FaserActsGeometry/FaserActsDetectorElement.h"
+#include "FaserActsGeometry/FaserActsAlignmentStore.h"
+#include "FaserActsGeometry/FaserActsGeometryContext.h"
+
+// ACTS
+#include "Acts/Utilities/Definitions.hpp"
+#include "Acts/Geometry/TrackingGeometry.hpp"
+#include "Acts/Surfaces/Surface.hpp"
+
+FaserNominalAlignmentCondAlg::FaserNominalAlignmentCondAlg( const std::string& name,
+            ISvcLocator* pSvcLocator ) :
+  ::AthAlgorithm( name, pSvcLocator ),
+  m_cs("CondSvc",name),
+  m_trackingGeometrySvc("FaserActsTrackingGeometrySvc", name)
+{
+}
+
+FaserNominalAlignmentCondAlg::~FaserNominalAlignmentCondAlg() {}
+
+StatusCode FaserNominalAlignmentCondAlg::initialize() {
+  ATH_MSG_DEBUG(name() << "::" << __FUNCTION__);
+
+  if (m_cs.retrieve().isFailure()) {
+    ATH_MSG_ERROR("unable to retrieve CondSvc");
+  }
+
+  if (m_wchk.initialize().isFailure()) {
+    ATH_MSG_ERROR("unable to initialize WriteCondHandle with key" << m_wchk.key() );
+    return StatusCode::FAILURE;
+  }
+
+  if (m_cs->regHandle(this, m_wchk).isFailure()) {
+    ATH_MSG_ERROR("unable to register WriteCondHandle " << m_wchk.fullKey()
+                  << " with CondSvc");
+    return StatusCode::FAILURE;
+  }
+
+  return StatusCode::SUCCESS;
+}
+
+StatusCode FaserNominalAlignmentCondAlg::finalize() {
+  ATH_MSG_DEBUG(name() << "::" << __FUNCTION__);
+  return StatusCode::SUCCESS;
+}
+
+StatusCode FaserNominalAlignmentCondAlg::execute() {
+  ATH_MSG_DEBUG(name() << "::" << __FUNCTION__);
+
+  SG::WriteCondHandle<FaserActsGeometryContext> wch(m_wchk);
+
+  EventIDBase now(getContext().eventID());
+
+  // do we have a valid m_wch for current time?
+  if ( wch.isValid(now) ) {
+    ATH_MSG_DEBUG("CondHandle is already valid for " << now
+		  << ". In theory this should not be called, but may happen"
+		  << " if multiple concurrent events are being processed out of order.");
+
+  } else {
+
+    ATH_MSG_DEBUG("  CondHandle " << wch.key()
+                  << " not valid now (" << now << "). Setting nominal alignment cond");
+
+
+    EventIDBase start(1, EventIDBase::UNDEFEVT);
+    EventIDBase end(1, EventIDBase::UNDEFEVT);
+    start.set_lumi_block(0);
+    end.set_lumi_block(9999); // this is not actually forever
+
+    EventIDRange r(start, end);
+
+    ATH_MSG_DEBUG("Will register nominal alignment for range: " << r);
+
+    // get a nominal alignment store from the tracking geometry service
+    // and plug it into a geometry context
+    auto gctx = std::make_unique<FaserActsGeometryContext>();
+    gctx->alignmentStore = m_trackingGeometrySvc->getNominalAlignmentStore();
+
+    // and write it to the conditions store
+    if (wch.record(r, gctx.release()).isFailure()) {
+      ATH_MSG_ERROR("could not record nominal FaserActsGeometryContext " << wch.key()
+                    << " with EventRange " << r);
+      return StatusCode::FAILURE;
+    }
+
+    ATH_MSG_DEBUG("WCH is valid now? " << wch.isValid(now));
+  }
+  return StatusCode::SUCCESS;
+}
diff --git a/Tracking/Acts/FaserActsGeometry/src/components/FaserActsGeometry_entries.cxx b/Tracking/Acts/FaserActsGeometry/src/components/FaserActsGeometry_entries.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..9ad80a9d5d68164965de8c40d355bd9fc02e05ae
--- /dev/null
+++ b/Tracking/Acts/FaserActsGeometry/src/components/FaserActsGeometry_entries.cxx
@@ -0,0 +1,34 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "FaserActsGeometry/FaserActsExtrapolationAlg.h"
+#include "FaserActsGeometry/FaserActsWriteTrackingGeometry.h"
+#include "FaserActsGeometry/FaserActsTrackingGeometrySvc.h"
+#include "FaserActsGeometry/FaserActsExtrapolationTool.h"
+#include "FaserActsGeometry/FaserActsObjWriterTool.h"
+#include "FaserActsGeometry/FaserActsTrackingGeometryTool.h"
+#include "FaserActsGeometry/FaserActsPropStepRootWriterSvc.h"
+#include "FaserActsGeometry/FaserActsAlignmentCondAlg.h"
+#include "FaserActsGeometry/FaserNominalAlignmentCondAlg.h"
+//#include "FaserActsGeometry/FaserActsKalmanFilterAlg.h"
+//#include "FaserActsGeometry/FaserActsExCellWriterSvc.h"
+//#include "FaserActsGeometry/FaserActsMaterialTrackWriterSvc.h"
+//#include "FaserActsGeometry/GeomShiftCondAlg.h"
+//#include "FaserActsGeometry/FaserActsWriteTrackingGeometryTransforms.h"
+
+
+DECLARE_COMPONENT( FaserActsTrackingGeometrySvc )
+DECLARE_COMPONENT( FaserActsTrackingGeometryTool )
+DECLARE_COMPONENT( FaserActsExtrapolationAlg )
+DECLARE_COMPONENT( FaserActsExtrapolationTool )
+DECLARE_COMPONENT( FaserActsPropStepRootWriterSvc )
+DECLARE_COMPONENT( FaserActsObjWriterTool )
+DECLARE_COMPONENT( FaserActsWriteTrackingGeometry )
+DECLARE_COMPONENT( FaserActsAlignmentCondAlg )
+//DECLARE_COMPONENT( FaserActsKalmanFilterAlg )
+//DECLARE_COMPONENT( FaserNominalAlignmentCondAlg )
+//DECLARE_COMPONENT( FaserActsExCellWriterSvc )
+//DECLARE_COMPONENT( FaserActsMaterialTrackWriterSvc )
+//DECLARE_COMPONENT( FaserActsWriteTrackingGeometryTransforms )
+//DECLARE_COMPONENT( FaserGeomShiftCondAlg )
diff --git a/Tracking/Acts/FaserActsGeometry/src/util/ObjHelper.cxx b/Tracking/Acts/FaserActsGeometry/src/util/ObjHelper.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..66181d9810cb614df41406f8df5ebe45d5dc134e
--- /dev/null
+++ b/Tracking/Acts/FaserActsGeometry/src/util/ObjHelper.cxx
@@ -0,0 +1,195 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+// This file was largely imported from the Acts testing framework
+
+#include "ObjHelper.h"
+
+#include <vector>
+
+void
+ObjHelper::writeVTN(std::ofstream&        stream,
+                             VtnCounter&           vtnCounter,
+                             double                scalor,
+                             const Acts::Vector3D& vertex,
+                             const std::string&    vtntype,
+                             bool                  point)
+{
+  // in case you make a point
+  unsigned int cp = 0;
+  // the counter
+  if (vtntype == "v") {
+    ++vtnCounter.vcounter;
+    cp = vtnCounter.vcounter;
+  } else if (vtntype == "t") {
+    ++vtnCounter.vtcounter;
+    cp = vtnCounter.vtcounter;
+  } else if (vtntype == "n") {
+    ++vtnCounter.ncounter;
+    cp = vtnCounter.ncounter;
+  } else
+    return;
+
+  // write out the vertex, texture vertex, normal
+  stream << vtntype << " " << scalor * vertex.x() << " " << scalor * vertex.y()
+         << " " << scalor * vertex.z() << '\n';
+  // we create a point if needed
+  if (point) stream << "p " << cp;
+}
+
+void
+ObjHelper::constructVerticalFaces(
+    std::ofstream&                   stream,
+    unsigned int                     start,
+    const std::vector<unsigned int>& vsides)
+{
+  // construct the vertical faces
+  size_t       nsides = vsides.size();
+  unsigned int sstart = start;
+  for (auto vside : vsides) {
+    if (vside) {
+      // start streaming the side
+      // all but the last
+      if (start - sstart < nsides - 1) {
+        stream << "f " << start << " " << start + 1 << " ";
+        stream << start + nsides + 1 << " " << start + nsides;
+      } else {
+        stream << "f " << start << " " << sstart << " ";
+        stream << sstart + nsides << " " << start + nsides;
+      }
+    }
+    stream << '\n';
+    // increase
+    ++start;
+  }
+}
+
+void
+ObjHelper::writePlanarFace(std::ofstream& stream,
+                                    VtnCounter&    vtnCounter,
+                                    double         scalor,
+                                    const std::vector<Acts::Vector3D>& vertices,
+                                    double                           thickness,
+                                    const std::vector<unsigned int>& vsides)
+{
+  // minimum 3 vertices needed
+  if (vertices.size() < 3) return;
+  // the first vertex
+  unsigned int fvertex = vtnCounter.vcounter + 1;
+  // lets create the normal vector first
+  Acts::Vector3D sideOne = vertices[1] - vertices[0];
+  Acts::Vector3D sideTwo = vertices[2] - vertices[1];
+  Acts::Vector3D nvector(sideTwo.cross(sideOne).normalized());
+  // write the normal vector
+  writeVTN(stream, vtnCounter, scalor, nvector, "n");
+  // thickness or not thickness
+  std::vector<int> sides     = {1};
+  if (thickness != 0.) sides = {-1, 1};
+  // now write all the vertices - this works w/wo thickness
+  for (auto side : sides) {
+    // save the current vertex counter
+    unsigned int cvc = vtnCounter.vcounter;
+    // loop over the sides
+    for (auto v : vertices)
+      writeVTN(stream,
+               vtnCounter,
+               scalor,
+               v + (0.5 * side * thickness) * nvector,
+               "v");
+    // decide if you want to add texture
+    std::string vtphr
+        = "/";  // vtnCounter.vtcounter ? "/"+std::to_string(vtcounter) : "/";
+    std::string ntphr = "/" + std::to_string(vtnCounter.ncounter);
+    // now write the face
+    stream << "f ";
+    for (size_t i=0;i<vertices.size();++i) stream << ++cvc << vtphr << ntphr << " ";
+    stream << '\n';
+  }
+  // now process the vertical sides
+  constructVerticalFaces(stream, fvertex, vsides);
+}
+
+void
+ObjHelper::writeTube(std::ofstream&           stream,
+                              VtnCounter&              vtnCounter,
+                              double                   scalor,
+                              unsigned int             nSegments,
+                              const Acts::Transform3D& transform,
+                              double                   r,
+                              double                   hZ,
+                              double                   thickness)
+{
+  // flip along plus/minus and declare the faces
+  std::vector<int> flip   = {-1, 1};
+  std::vector<int> vfaces = {1, 2, 4, 3};
+  // the number of phisteps
+  double phistep = 2 * M_PI / nSegments;
+  // make it twice if necessary
+  std::vector<double> roffsets  = {0.};
+  if (thickness != 0.) roffsets = {-0.5 * thickness, 0.5 * thickness};
+  // now loop over the thickness and make an outer and inner
+  unsigned int cvc   = vtnCounter.vcounter;
+  size_t       iside = 0;
+  for (auto t : roffsets) {
+    size_t iphi = 0;
+    // loop over phi steps
+    for (; iphi < nSegments; ++iphi) {
+      // currentPhi
+      double phi = -M_PI + iphi * phistep;
+      for (auto iflip : flip) {
+        // create the vertex
+        Acts::Vector3D point(transform * Acts::Vector3D((r + t) * cos(phi),
+                                                        (r + t) * sin(phi),
+                                                        iflip * hZ));
+        // write the normal vector
+        writeVTN(stream, vtnCounter, scalor, point, "v");
+      }
+    }
+    // now create the faces
+    iphi = 0;
+    // side offset for faces
+    unsigned int soff = 2 * iside * nSegments;
+    for (; iphi < nSegments - 1; ++iphi) {
+      // output to file
+      stream << "f ";
+      for (auto face : vfaces) stream << soff + cvc + (2 * iphi) + face << " ";
+      stream << '\n';
+    }
+    // close the loop
+    stream << "f " << soff + cvc + (2 * iphi) + 1 << " "
+           << soff + cvc + (2 * iphi) + 2 << " " << soff + cvc + 2 << " "
+           << soff + cvc + 1 << '\n';
+    // new line at the end of the line
+    stream << '\n';
+    ++iside;
+  }
+
+  // construct the sides at the end when all vertices are done
+  Acts::Vector3D nvectorSide = transform.rotation().col(2);
+  // write the normal vector @todo flip sides
+  writeVTN(stream, vtnCounter, scalor, nvectorSide, "n");
+  std::string ntphr = "//" + std::to_string(vtnCounter.ncounter);
+
+  if (thickness != 0.) {
+    // loop over the two sides
+    for (iside = 0; iside < 2; ++iside) {
+      // rest iphi
+      size_t iphi = 0;
+      for (; iphi < nSegments - 1; ++iphi) {
+        stream << "f ";
+        unsigned int base = cvc + (2 * iphi) + 1;
+        stream << iside + base << ntphr << " ";
+        stream << iside + base + 2 << ntphr << " ";
+        stream << iside + base + (2 * nSegments) + 2 << ntphr << " ";
+        stream << iside + base + (2 * nSegments) << ntphr << '\n';
+      }
+      // close the loop
+      stream << "f ";
+      stream << iside + cvc + (2 * iphi) + 1 << ntphr << " ";
+      stream << iside + cvc + 1 << ntphr << " ";
+      stream << iside + cvc + 1 + (2 * nSegments) << ntphr << " ";
+      stream << iside + cvc + (2 * iphi) + 1 + (2 * nSegments) << ntphr << '\n';
+    }
+  }
+}
diff --git a/Tracking/Acts/FaserActsGeometry/src/util/ObjHelper.h b/Tracking/Acts/FaserActsGeometry/src/util/ObjHelper.h
new file mode 100644
index 0000000000000000000000000000000000000000..2c55113fc96b4a257267c1074f7a5e409e64bd87
--- /dev/null
+++ b/Tracking/Acts/FaserActsGeometry/src/util/ObjHelper.h
@@ -0,0 +1,72 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+// This file was largely imported from the Acts testing framework
+
+#pragma once
+
+#include <fstream>
+#include <vector>
+#include "Acts/Utilities/Definitions.hpp"
+
+
+namespace ObjHelper {
+
+  /// This is the counter struct for keeping track of the vertices
+  struct VtnCounter
+  {
+    unsigned int vcounter  = 0;
+    unsigned int vtcounter = 0;
+    unsigned int ncounter  = 0;
+  };
+
+  /// This will write a vertex to the fstream
+  /// @param stream is the stream where to write to
+  /// @param vertex is the vertex to be written out
+  /// @param cvertex is the current vertex number
+  void
+  writeVTN(std::ofstream&        stream,
+           VtnCounter&           vtnCounter,
+           double                scalor,
+           const Acts::Vector3D& vertex,
+           const std::string&    vtntype = "v",
+           bool                  point   = false);
+
+  /// construct vertical faces
+  /// this takes a range and constructs faces
+  void
+  constructVerticalFaces(std::ofstream&                   stream,
+                         unsigned int                     start,
+                         const std::vector<unsigned int>& vsides);
+
+  /// This will write a planar face
+  /// - normal is given by cross product
+  ///
+  /// @param stream is the stream where to write to
+  /// @param face is the face to be written out
+  /// @param cvertex is the current vertex number
+  /// @param thickness is the (optional) thickness
+  void
+  writePlanarFace(std::ofstream&                     stream,
+                  VtnCounter&                        vtnCounter,
+                  double                             scalor,
+                  const std::vector<Acts::Vector3D>& vertices,
+                  double                             thickness = 0.,
+                  const std::vector<unsigned int>&   vsides    = {});
+
+  /// This will write a cylindrical object
+  ///
+  /// @param stream is the stream where to write to
+  void
+  writeTube(std::ofstream&           stream,
+            VtnCounter&              vtnCounter,
+            double                   scalor,
+            unsigned int             nSegments,
+            const Acts::Transform3D& transform,
+            double                   r,
+            double                   hZ,
+            double                   thickness = 0.);
+
+}  // enf of namespace
+
diff --git a/Tracking/Acts/FaserActsGeometry/src/util/ObjSurfaceWriter.cxx b/Tracking/Acts/FaserActsGeometry/src/util/ObjSurfaceWriter.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..162a34efc441269d2d3f8266a2de852989b37800
--- /dev/null
+++ b/Tracking/Acts/FaserActsGeometry/src/util/ObjSurfaceWriter.cxx
@@ -0,0 +1,209 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+// This file was largely imported from the Acts testing framework
+
+#include "ObjSurfaceWriter.h"
+
+#include <ios>
+#include <iostream>
+#include <stdexcept>
+
+#include "Acts/Geometry/Layer.hpp"
+#include "Acts/Surfaces/CylinderBounds.hpp"
+#include "Acts/Surfaces/PlanarBounds.hpp"
+#include "Acts/Surfaces/RadialBounds.hpp"
+#include "Acts/Surfaces/SurfaceBounds.hpp"
+#include "Acts/Geometry/GeometryID.hpp"
+
+#include "Acts/Geometry/Polyhedron.hpp"
+#include "Acts/Surfaces/CylinderSurface.hpp"
+#include "Acts/Surfaces/StrawSurface.hpp"
+
+namespace {
+	// this method went away in acts 0.19.0. Porting over this code to use IVisualization seems
+	// to be not worth, so porting this (relatively simple) method here.
+	std::string objString(const Acts::Polyhedron& polyhedron, size_t vtxOffset) {
+		std::stringstream sstr;
+
+		for (const auto& vtx : polyhedron.vertices) {
+			sstr << "v " << vtx.x() << " " << vtx.y() << " " << vtx.z() << std::endl;
+
+		}
+		for (const auto& face : polyhedron.faces) {
+			sstr << "f";
+			for (const auto& idx : face) {
+				sstr << " " << (vtxOffset + idx + 1);
+
+			}
+			sstr << std::endl;
+
+		}
+		return sstr.str();
+
+	}
+}
+
+
+
+
+Acts::ObjSurfaceWriter::ObjSurfaceWriter(
+    const ObjSurfaceWriter::Config& cfg)
+  : m_cfg(cfg)
+{
+  // Validate the configuration
+  if (!m_cfg.logger) {
+    throw std::invalid_argument("Missing logger");
+  } else if (m_cfg.name.empty()) {
+    throw std::invalid_argument("Missing algorithm name");
+  } else if (!m_cfg.outputStream) {
+    throw std::invalid_argument("Missing output stream");
+  }
+
+  // Write down the file prefix
+  (*(m_cfg.outputStream)) << m_cfg.filePrefix << '\n';
+}
+
+std::string
+Acts::ObjSurfaceWriter::name() const
+{
+  return m_cfg.name;
+}
+void
+Acts::ObjSurfaceWriter::write(const std::string& sinfo)
+{
+  // lock the mutex for writing
+  std::lock_guard<std::mutex> lock(m_write_mutex);
+  // and write
+  (*m_cfg.outputStream) << sinfo;
+}
+
+void
+Acts::ObjSurfaceWriter::write(const Acts::GeometryContext &gctx,
+                              const Acts::Surface &surface)
+{
+  std::lock_guard<std::mutex> lock(m_write_mutex);
+
+  // check
+  ACTS_DEBUG(">>Obj: Writer for Surface object called.");
+
+  auto scalor = m_cfg.outputScalor;
+  // let's get the bounds & the transform
+  const Acts::SurfaceBounds& surfaceBounds = surface.bounds();
+  auto sTransform = surface.transform(gctx);
+
+  // dynamic_cast to PlanarBounds
+  const Acts::PlanarBounds* planarBounds
+      = dynamic_cast<const Acts::PlanarBounds*>(&surfaceBounds);
+  
+  const Acts::CylinderBounds* cylinderBounds
+      = dynamic_cast<const Acts::CylinderBounds*>(&surfaceBounds);
+  
+  const Acts::StrawSurface* strawSurface
+      = dynamic_cast<const Acts::StrawSurface*>(&surface);
+
+  // only continue if the cast worked
+  if (m_cfg.outputSensitive) {
+    if (planarBounds) {
+      ACTS_VERBOSE(">>Obj: Writing out a PlaneSurface");
+      // set the precision - just to be sure
+      (*(m_cfg.outputStream)) << '\n';
+      (*(m_cfg.outputStream)) << std::setprecision(m_cfg.outputPrecision);
+      // get the vertices
+      auto planarVertices = planarBounds->vertices();
+      // loop over the vertices
+      std::vector<Acts::Vector3D> vertices;
+      vertices.reserve(planarVertices.size());
+      for (auto pv : planarVertices) {
+        // get the point in 3D
+        Acts::Vector3D v3D(sTransform * Acts::Vector3D(pv.x(), pv.y(), 0.));
+        vertices.push_back(v3D);
+      }
+      // get the thickness and vertical faces
+      double                    thickness = 0.;
+      std::vector<unsigned int> vfaces;
+      if (surface.associatedDetectorElement()) {
+        // get the thickness form the detector element
+        thickness = surface.associatedDetectorElement()->thickness();
+        vfaces    = {1, 1, 1, 1};
+      }
+      // output to file
+      ObjHelper::writePlanarFace(*(m_cfg.outputStream),
+                                   m_vtnCounter,
+                                   scalor,
+                                   vertices,
+                                   thickness,
+                                   vfaces);
+      (*(m_cfg.outputStream)) << '\n';
+    }
+    else if(cylinderBounds) {
+      
+      auto cylinderSurface = dynamic_cast<const Acts::CylinderSurface*>(&surface);
+
+      Acts::Polyhedron ph =
+          cylinderSurface->polyhedronRepresentation(gctx, 10);
+      (*(m_cfg.outputStream)) << objString(ph, m_vtnCounter.vcounter);
+      m_vtnCounter.vcounter += ph.vertices.size();
+
+    }
+    else if(strawSurface) {
+
+      Acts::Polyhedron ph =
+          strawSurface->polyhedronRepresentation(gctx, 10);
+      (*(m_cfg.outputStream)) << objString(ph, m_vtnCounter.vcounter);
+      m_vtnCounter.vcounter += ph.vertices.size();
+
+    }
+    else {
+      ACTS_ERROR("Unable to print this bounds type: " << surfaceBounds.type());
+    }
+  }
+
+  // check if you have layer and check what your have
+  // dynamic cast to CylinderBounds work the same
+  if (cylinderBounds && m_cfg.outputLayerSurface) {
+    ACTS_VERBOSE(">>Obj: Writing out a CylinderSurface with r = "
+                 << cylinderBounds->get(Acts::CylinderBounds::eR));
+    // name the object
+    auto layerID = surface.geoID().layer();
+    (*(m_cfg.outputStream))
+        << " o Cylinder_" << std::to_string(layerID) << '\n';
+    // output to the file
+    ObjHelper::writeTube(*(m_cfg.outputStream),
+                           m_vtnCounter,
+                           scalor,
+                           m_cfg.outputPhiSegments,
+                           sTransform,
+                           cylinderBounds->get(Acts::CylinderBounds::eR),
+                           cylinderBounds->get(Acts::CylinderBounds::eHalfLengthZ),
+                           m_cfg.outputThickness);
+    (*(m_cfg.outputStream)) << '\n';
+  }
+
+  ////dynamic cast to RadialBounds or disc bounds work the same
+  const Acts::RadialBounds* radialBounds
+      = dynamic_cast<const Acts::RadialBounds*>(&surfaceBounds);
+  if (radialBounds && m_cfg.outputLayerSurface) {
+    ACTS_VERBOSE(">>Obj: Writing out a DiskSurface at z = "
+                 << sTransform.translation().z());
+    // name the object
+    auto layerID = surface.geoID().layer();
+    (*(m_cfg.outputStream)) << "o Disk_" << std::to_string(layerID) << '\n';
+    // we use the tube writer in the other direction
+    double rMin      = radialBounds->rMin();
+    double rMax      = radialBounds->rMax();
+    double thickness = rMax - rMin;
+    // output to the file
+    ObjHelper::writeTube(*(m_cfg.outputStream),
+                           m_vtnCounter,
+                           scalor,
+                           m_cfg.outputPhiSegments,
+                           sTransform,
+                           0.5 * (rMin + rMax),
+                           m_cfg.outputThickness,
+                           thickness);
+    (*(m_cfg.outputStream)) << '\n';
+  }
+
+}
diff --git a/Tracking/Acts/FaserActsGeometry/src/util/ObjSurfaceWriter.h b/Tracking/Acts/FaserActsGeometry/src/util/ObjSurfaceWriter.h
new file mode 100644
index 0000000000000000000000000000000000000000..37507ef6aa42fe8f38a8e496f6332dc1c3f54627
--- /dev/null
+++ b/Tracking/Acts/FaserActsGeometry/src/util/ObjSurfaceWriter.h
@@ -0,0 +1,97 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+// This file was largely imported from the Acts testing framework
+
+#pragma once
+
+#include "Acts/Geometry/GeometryContext.hpp"
+#include <fstream>
+#include <iostream>
+#include <mutex>
+#include "ObjHelper.h"
+#include "Acts/Surfaces/Surface.hpp"
+#include "Acts/Utilities/Logger.hpp"
+
+namespace Acts {
+
+/// @class ObjSurfaceWriter
+///
+/// An Obj writer for the geometry
+///
+class ObjSurfaceWriter
+{
+public:
+  // @class Config
+  //
+  // The nested config class
+  class Config
+  {
+  public:
+    /// the default logger
+    std::shared_ptr<const Acts::Logger> logger;
+    /// the name of the algorithm
+    std::string name;
+    /// approximate cyinders by that
+    unsigned int outputPhiSegments = 72;
+    /// write thickness if available
+    double outputThickness = 2.;
+    /// write sensitive surfaces
+    bool outputSensitive = true;
+    /// write the layer surface out
+    bool outputLayerSurface = true;
+    /// output scalor
+    double outputScalor = 1.;
+    /// precision for out
+    unsigned int outputPrecision = 6;
+    /// file prefix to be written out
+    std::string filePrefix = "";
+    /// prefixes
+    /// @todo These aren't used anywhere, should they be dropped?
+    std::string planarPrefix   = "";
+    std::string cylinderPrefix = "";
+    std::string diskPrefix     = "";
+    /// the output stream
+    std::shared_ptr<std::ofstream> outputStream = nullptr;
+
+    Config(const std::string&   lname = "ObjSurfaceWriter",
+           Acts::Logging::Level lvl   = Acts::Logging::INFO)
+      : logger(Acts::getDefaultLogger(lname, lvl)), name(lname)
+    {
+    }
+  };
+
+  /// Constructor
+  ///
+  /// @param cfg is the configuration class
+  ObjSurfaceWriter(const Config& cfg);
+
+  /// Framework name() method
+  std::string
+  name() const;
+
+  /// The write interface
+  /// @param surface to be written out
+  void
+  write(const Acts::GeometryContext &gctx, const Acts::Surface &surface);
+
+  /// write a bit of string
+  /// @param is the string to be written
+  void
+  write(const std::string& sinfo);
+
+private:
+  Config                  m_cfg;         ///< the config class
+  ObjHelper::VtnCounter m_vtnCounter;  ///< vertex, texture, normal
+  std::mutex m_write_mutex;  ///< mutex to protect multi-threaded writes
+
+  /// Private access to the logging instance
+  const Acts::Logger&
+  logger() const
+  {
+    return *m_cfg.logger;
+  }
+};
+
+}
diff --git a/Tracking/Acts/FaserActsGeometry/src/util/ObjTrackingGeometryWriter.cxx b/Tracking/Acts/FaserActsGeometry/src/util/ObjTrackingGeometryWriter.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..05da67b11c553987e898ccffae915ede2b0e8f30
--- /dev/null
+++ b/Tracking/Acts/FaserActsGeometry/src/util/ObjTrackingGeometryWriter.cxx
@@ -0,0 +1,84 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+// This file was largely imported from the Acts testing framework
+
+#include "ObjTrackingGeometryWriter.h"
+
+#include <iostream>
+#include "Acts/Geometry/TrackingVolume.hpp"
+#include "Acts/Surfaces/Surface.hpp"
+#include "Acts/Geometry/GeometryContext.hpp"
+
+Acts::ObjTrackingGeometryWriter::ObjTrackingGeometryWriter(
+    const ObjTrackingGeometryWriter::Config& cfg)
+  : m_cfg(cfg)
+{
+}
+
+std::string
+Acts::ObjTrackingGeometryWriter::name() const
+{
+  return m_cfg.name;
+}
+
+void
+Acts::ObjTrackingGeometryWriter::write(const Acts::GeometryContext& gctx, const Acts::TrackingGeometry& tGeometry)
+{
+  ACTS_DEBUG(">>Obj: Writer for TrackingGeometry object called.");
+  // get the world volume
+  auto world = tGeometry.highestTrackingVolume();
+  if (world) write(gctx, *world);
+  // return the success code
+}
+
+/// process this volume
+void
+Acts::ObjTrackingGeometryWriter::write(const Acts::GeometryContext& gctx, const Acts::TrackingVolume& tVolume)
+{
+  ACTS_DEBUG(">>Obj: Writer for TrackingVolume object called.");
+  // get the confined layers and process them
+  if (tVolume.confinedLayers()) {
+    ACTS_VERBOSE(">>Obj: Layers are present, process them.");
+    // loop over the layers
+    for (auto layer : tVolume.confinedLayers()->arrayObjects()) {
+      // we jump navigation layers
+      if (layer->layerType() == Acts::navigation) continue;
+      // get the volume name
+      const std::string& volumeName = tVolume.volumeName();
+      // find the right surfacewriter
+      std::shared_ptr<ObjSurfaceWriter> surfaceWriter = nullptr;
+      for (auto writer : m_cfg.surfaceWriters) {
+        // get name and writer
+        auto writerName = writer->name();
+        if (volumeName.find(writerName) != std::string::npos) {
+          // asign the writer
+          surfaceWriter = writer;
+          // and break
+          break;
+        }
+      }
+      // bail out if you have no surface writer
+      if (!surfaceWriter) return;
+      // layer prefix
+      surfaceWriter->write(m_cfg.layerPrefix);
+      // check for sensitive surfaces
+      if (layer->surfaceArray() && surfaceWriter) {
+        // surfaces
+        surfaceWriter->write(m_cfg.sensitiveGroupPrefix);
+        // loop over the surface
+        for (auto surface : layer->surfaceArray()->surfaces()) {
+          if (surface) surfaceWriter->write(gctx, *surface);
+        }
+      }
+    }
+  }
+  // get the confined volumes and step down the hierarchy
+  if (tVolume.confinedVolumes()) {
+    // loop over the volumes and write what they have
+    for (auto volume : tVolume.confinedVolumes()->arrayObjects()) {
+      write(gctx, *volume.get());
+    }
+  }
+}
diff --git a/Tracking/Acts/FaserActsGeometry/src/util/ObjTrackingGeometryWriter.h b/Tracking/Acts/FaserActsGeometry/src/util/ObjTrackingGeometryWriter.h
new file mode 100644
index 0000000000000000000000000000000000000000..65f263739e6e7b35277b5a69d5e890308ca095ce
--- /dev/null
+++ b/Tracking/Acts/FaserActsGeometry/src/util/ObjTrackingGeometryWriter.h
@@ -0,0 +1,84 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+// This file was largely imported from the Acts testing framework
+
+#pragma once
+
+#include <mutex>
+
+#include <fstream>
+#include <iostream>
+#include "ObjSurfaceWriter.h"
+#include "Acts/Geometry/TrackingGeometry.hpp"
+#include "Acts/Surfaces/Surface.hpp"
+#include "Acts/Utilities/Logger.hpp"
+#include "Acts/Geometry/GeometryContext.hpp"
+
+namespace Acts {
+class TrackingVolume;
+
+/// @class ObjTrackingGeometryWriter
+///
+/// An Obj writer for the geometry
+/// It delegates the writing of surfaces to the surface writers
+class ObjTrackingGeometryWriter {
+public:
+  // @class Config
+  //
+  // The nested config class
+  class Config
+  {
+  public:
+    /// the default logger
+    std::shared_ptr<const Acts::Logger> logger;
+    /// the name of the writer
+    std::string name = "";
+    /// surfaceWriters
+    std::vector<std::shared_ptr<ObjSurfaceWriter>> surfaceWriters;
+    std::string                                    filePrefix           = "";
+    std::string                                    sensitiveGroupPrefix = "";
+    std::string                                    layerPrefix          = "";
+
+    Config(const std::string&   lname = "ObjTrackingGeometryWriter",
+           Acts::Logging::Level lvl   = Acts::Logging::INFO)
+      : logger(Acts::getDefaultLogger(lname, lvl))
+      , name(lname)
+      , surfaceWriters()
+    {
+    }
+  };
+
+  /// Constructor
+  /// @param cfg is the configuration class
+  ObjTrackingGeometryWriter(const Config& cfg);
+
+  /// Framework name() method
+  /// @return the name of the tool
+  std::string
+  name() const;
+
+  /// The write interface
+  /// @param tGeometry is the geometry to be written out
+  /// @return ProcessCode to indicate success/failure
+  void
+  write(const Acts::GeometryContext& gctx, const Acts::TrackingGeometry& tGeometry);
+
+private:
+  Config m_cfg;  ///< the config class
+
+  /// process this volume
+  /// @param tVolume the volume to be processed
+  void
+  write(const Acts::GeometryContext& gctx, const Acts::TrackingVolume& tVolume);
+
+  /// Private access to the logging instance
+  const Acts::Logger&
+  logger() const
+  {
+    return *m_cfg.logger;
+  }
+};
+
+}
diff --git a/Tracking/Acts/FaserActsGeometry/test/FaserActsExtrapolationAlg.py b/Tracking/Acts/FaserActsGeometry/test/FaserActsExtrapolationAlg.py
new file mode 100644
index 0000000000000000000000000000000000000000..136742de70c41c077304d0f942a68ccd6ead6ca5
--- /dev/null
+++ b/Tracking/Acts/FaserActsGeometry/test/FaserActsExtrapolationAlg.py
@@ -0,0 +1,57 @@
+#!/usr/bin/env python
+
+import sys
+from AthenaCommon.Logging import log, logging
+from AthenaCommon.Constants import DEBUG, VERBOSE, INFO
+from AthenaCommon.Configurable import Configurable
+from CalypsoConfiguration.AllConfigFlags import ConfigFlags
+from AthenaConfiguration.TestDefaults import defaultTestFiles
+from AthenaConfiguration.MainServicesConfig import MainServicesCfg
+from AthenaPoolCnvSvc.PoolReadConfig import PoolReadCfg
+from AthenaPoolCnvSvc.PoolWriteConfig import PoolWriteCfg
+from OutputStreamAthenaPool.OutputStreamConfig import OutputStreamCfg
+from FaserActsGeometry.FaserActsExtrapolationConfig import FaserActsExtrapolationAlgCfg
+
+# Set up logging and new style config
+log.setLevel(DEBUG)
+Configurable.configurableRun3Behavior = True
+
+# Configure
+#ConfigFlags.Input.Files = ["/cvmfs/atlas-nightlies.cern.ch/repo/data/data-art/esd/100evts10lumiblocks.ESD.root"]
+#ConfigFlags.Output.RDOFileName = "myRDO_sp.pool.root"
+ConfigFlags.Input.isMC = True                                # Needed to bypass autoconfig
+ConfigFlags.IOVDb.GlobalTag = "OFLCOND-XXXX-XXX-XX"
+ConfigFlags.GeoModel.FaserVersion = "FASER-01"               # Always needed
+# Workaround for bug/missing flag; unimportant otherwise 
+ConfigFlags.addFlag("Input.InitialTimeStamp", 0)
+# Workaround to avoid problematic ISF code
+ConfigFlags.GeoModel.Layout = "Development"
+ConfigFlags.Detector.SimulateFaserSCT = True
+#ConfigFlags.GeoModel.AtlasVersion = "ATLAS-R2-2016-01-00-01" # Always needed to fool autoconfig; value ignored
+ConfigFlags.GeoModel.Align.Dynamic = False
+#ConfigFlags.Concurrency.NumThreads = 1
+#ConfigFlags.Beam.NumberOfCollisions = 0.
+ConfigFlags.lock()
+
+# Core components
+acc = MainServicesCfg(ConfigFlags)
+#acc.merge(PoolReadCfg(ConfigFlags))
+#acc.merge(PoolWriteCfg(ConfigFlags))
+
+# Inner Detector
+acc.merge(FaserActsExtrapolationAlgCfg(ConfigFlags))
+
+# Dump config
+logging.getLogger('forcomps').setLevel(VERBOSE)
+acc.foreach_component("*").OutputLevel = VERBOSE
+acc.foreach_component("*ClassID*").OutputLevel = INFO
+#acc.getCondAlgo("FaserActsAlignmentCondAlg").OutputLevel = VERBOSE
+#acc.getCondAlgo("FaserNominalAlignmentCondAlg").OutputLevel = VERBOSE
+acc.getService("StoreGateSvc").Dump = True
+acc.getService("ConditionStore").Dump = True
+acc.printConfig(withDetails=True)
+ConfigFlags.dump()
+# Execute and finish
+sc = acc.run(maxEvents=1)
+# Success should be 0
+sys.exit(not sc.isSuccess())
diff --git a/Tracking/Acts/FaserActsGeometry/test/FaserActsWriteTrackingGeometry.py b/Tracking/Acts/FaserActsGeometry/test/FaserActsWriteTrackingGeometry.py
new file mode 100644
index 0000000000000000000000000000000000000000..d7aa806a3916cc65b62a60677b884392a82b9fe7
--- /dev/null
+++ b/Tracking/Acts/FaserActsGeometry/test/FaserActsWriteTrackingGeometry.py
@@ -0,0 +1,66 @@
+#!/usr/bin/env python
+
+import sys
+from AthenaCommon.Logging import log, logging
+from AthenaCommon.Constants import DEBUG, VERBOSE, INFO
+from AthenaCommon.Configurable import Configurable
+from CalypsoConfiguration.AllConfigFlags import ConfigFlags
+from AthenaConfiguration.TestDefaults import defaultTestFiles
+from AthenaConfiguration.MainServicesConfig import MainServicesCfg
+from AthenaPoolCnvSvc.PoolReadConfig import PoolReadCfg
+from AthenaPoolCnvSvc.PoolWriteConfig import PoolWriteCfg
+from OutputStreamAthenaPool.OutputStreamConfig import OutputStreamCfg
+from FaserActsGeometry.FaserActsWriteTrackingGeometryConfig import FaserActsWriteTrackingGeometryCfg
+
+# Set up logging and new style config
+log.setLevel(DEBUG)
+Configurable.configurableRun3Behavior = True
+
+# Configure
+ConfigFlags.Input.Files = ["/cvmfs/atlas-nightlies.cern.ch/repo/data/data-art/esd/100evts10lumiblocks.ESD.root"]
+#ConfigFlags.Output.RDOFileName = "myRDO_sp.pool.root"
+ConfigFlags.IOVDb.GlobalTag = "OFLCOND-XXXX-XXX-XX"
+ConfigFlags.GeoModel.FaserVersion = "FASER-01"               # Always needed
+# Workaround for bug/missing flag; unimportant otherwise 
+ConfigFlags.addFlag("Input.InitialTimeStamp", 0)
+# Workaround to avoid problematic ISF code
+ConfigFlags.GeoModel.Layout = "Development"
+ConfigFlags.Detector.SimulateFaserSCT = True
+ConfigFlags.GeoModel.AtlasVersion = "ATLAS-R2-2016-01-00-01" # Always needed to fool autoconfig; value ignored
+ConfigFlags.GeoModel.Align.Dynamic = False
+#ConfigFlags.Concurrency.NumThreads = 1
+#ConfigFlags.Beam.NumberOfCollisions = 0.
+ConfigFlags.lock()
+
+# Core components
+acc = MainServicesCfg(ConfigFlags)
+acc.merge(PoolReadCfg(ConfigFlags))
+acc.merge(PoolWriteCfg(ConfigFlags))
+
+# Inner Detector
+acc.merge(FaserActsWriteTrackingGeometryCfg(ConfigFlags))
+
+# Output Stream customization
+#oStream = acc.getEventAlgo("OutputStreamRDO")
+#oStream.ItemList += ["EventInfo#*",
+#                     "McEventCollection#TruthEvent",
+#                     "McEventCollection#GEN_EVENT"
+#                    ]
+                    
+# Timing
+#acc.merge(MergeRecoTimingObjCfg(ConfigFlags))
+
+# Dump config
+logging.getLogger('forcomps').setLevel(VERBOSE)
+acc.foreach_component("*").OutputLevel = VERBOSE
+acc.foreach_component("*ClassID*").OutputLevel = INFO
+#acc.getCondAlgo("FaserActsAlignmentCondAlg").OutputLevel = VERBOSE
+#acc.getCondAlgo("FaserNominalAlignmentCondAlg").OutputLevel = VERBOSE
+acc.getService("StoreGateSvc").Dump = True
+acc.getService("ConditionStore").Dump = True
+acc.printConfig(withDetails=True)
+ConfigFlags.dump()
+# Execute and finish
+sc = acc.run(maxEvents=-1)
+# Success should be 0
+sys.exit(not sc.isSuccess())
diff --git a/Tracking/Acts/FaserActsGeometryInterfaces/CMakeLists.txt b/Tracking/Acts/FaserActsGeometryInterfaces/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..633d8584e7fb89fbfe48d84c3eb634eae4807b56
--- /dev/null
+++ b/Tracking/Acts/FaserActsGeometryInterfaces/CMakeLists.txt
@@ -0,0 +1,19 @@
+
+# Declare the package name:
+atlas_subdir( FaserActsGeometryInterfaces )
+
+# External dependencies:
+find_package( Eigen )
+find_package( Acts COMPONENTS Core )
+
+# Component(s) in the package:
+
+atlas_add_library( FaserActsGeometryInterfacesLib
+                   FaserActsGeometryInterfaces/*.h
+                   INTERFACE
+                   PUBLIC_HEADERS FaserActsGeometryInterfaces
+                   INCLUDE_DIRS ${EIGEN_INCLUDE_DIRS}
+                   LINK_LIBRARIES ${EIGEN_LIBRARIES}
+                   AthenaKernel
+                   ActsInteropLib
+                   ActsCore)
diff --git a/Tracking/Acts/FaserActsGeometryInterfaces/FaserActsGeometryInterfaces/IFaserActsExtrapolationTool.h b/Tracking/Acts/FaserActsGeometryInterfaces/FaserActsGeometryInterfaces/IFaserActsExtrapolationTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..6f04868ee03c29a0e35513eb4d7ff94345d39940
--- /dev/null
+++ b/Tracking/Acts/FaserActsGeometryInterfaces/FaserActsGeometryInterfaces/IFaserActsExtrapolationTool.h
@@ -0,0 +1,78 @@
+/*
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef FASERACTSGEOMETRYINTERFACES_IACTSEXTRAPOLATIONTOOL_H
+#define FASERACTSGEOMETRYINTERFACES_IACTSEXTRAPOLATIONTOOL_H
+
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "GaudiKernel/IInterface.h"
+#include "GaudiKernel/IAlgTool.h"
+#include "GaudiKernel/EventContext.h"
+
+#include "Acts/Propagator/detail/SteppingLogger.hpp"
+#include "Acts/EventData/TrackParameters.hpp"
+#include "Acts/Propagator/MaterialInteractor.hpp"
+
+#include "FaserActsGeometry/FaserActsGeometryContext.h"
+#include "Acts/MagneticField/MagneticFieldContext.hpp"
+
+/// Using some short hands for Recorded Material
+using ActsRecordedMaterial = Acts::MaterialInteractor::result_type;
+/// Finally the output of the propagation test
+using ActsPropagationOutput =
+        std::pair<std::vector<Acts::detail::Step>, ActsRecordedMaterial>;
+
+
+namespace Acts {
+  class TrackingGeometry;
+}
+
+class IFaserActsTrackingGeometryTool;
+
+
+class IFaserActsExtrapolationTool : virtual public IAlgTool {
+  public:
+
+  DeclareInterfaceID(IFaserActsExtrapolationTool, 1, 0);
+
+  virtual
+  ActsPropagationOutput
+  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
+  ActsPropagationOutput
+  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
+  const IFaserActsTrackingGeometryTool*
+  trackingGeometryTool() const = 0;
+
+  virtual 
+  Acts::MagneticFieldContext getMagneticFieldContext(const EventContext& ctx) const = 0;
+
+};
+
+#endif
diff --git a/Tracking/Acts/FaserActsGeometryInterfaces/FaserActsGeometryInterfaces/IFaserActsTrackingGeometrySvc.h b/Tracking/Acts/FaserActsGeometryInterfaces/FaserActsGeometryInterfaces/IFaserActsTrackingGeometrySvc.h
new file mode 100644
index 0000000000000000000000000000000000000000..1c7798352d663f87435d00f12337cee263b0cb4e
--- /dev/null
+++ b/Tracking/Acts/FaserActsGeometryInterfaces/FaserActsGeometryInterfaces/IFaserActsTrackingGeometrySvc.h
@@ -0,0 +1,37 @@
+/*
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef FASERACTSGEOMETRYINTERFACES_IACTSTRACKINGGEOMETRYSVC_H
+#define FASERACTSGEOMETRYINTERFACES_IACTSTRACKINGGEOMETRYSVC_H
+
+#include "GaudiKernel/IInterface.h"
+
+class EventContext;
+class FaserActsAlignmentStore;
+
+namespace Acts {
+  class TrackingGeometry;
+}
+
+
+class IFaserActsTrackingGeometrySvc : virtual public IInterface {
+  public:
+
+  DeclareInterfaceID(IFaserActsTrackingGeometrySvc, 1, 0);
+
+  virtual
+  std::shared_ptr<const Acts::TrackingGeometry>
+  trackingGeometry() = 0;
+
+  virtual
+  void
+  populateAlignmentStore(FaserActsAlignmentStore *store) const = 0;
+
+  virtual
+  const FaserActsAlignmentStore*
+  getNominalAlignmentStore() const = 0;
+
+};
+
+#endif
diff --git a/Tracking/Acts/FaserActsGeometryInterfaces/FaserActsGeometryInterfaces/IFaserActsTrackingGeometryTool.h b/Tracking/Acts/FaserActsGeometryInterfaces/FaserActsGeometryInterfaces/IFaserActsTrackingGeometryTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..e13ff4454b95a16de7b8932bd002260432d80069
--- /dev/null
+++ b/Tracking/Acts/FaserActsGeometryInterfaces/FaserActsGeometryInterfaces/IFaserActsTrackingGeometryTool.h
@@ -0,0 +1,37 @@
+/*
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef FASERACTSGEOMETRYINTERFACES_IACTSTRACKINGGEOMETRYTOOL_H
+#define FASERACTSGEOMETRYINTERFACES_IACTSTRACKINGGEOMETRYTOOL_H
+
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "GaudiKernel/IInterface.h"
+#include "GaudiKernel/IAlgTool.h"
+#include "GaudiKernel/EventContext.h"
+#include "FaserActsGeometry/FaserActsGeometryContext.h"
+
+namespace Acts {
+  class TrackingGeometry;
+}
+
+
+class IFaserActsTrackingGeometryTool : virtual public IAlgTool {
+  public:
+
+  DeclareInterfaceID(IFaserActsTrackingGeometryTool, 1, 0);
+
+  virtual
+  std::shared_ptr<const Acts::TrackingGeometry>
+  trackingGeometry() const = 0;
+
+  virtual
+  const FaserActsGeometryContext&
+  getGeometryContext(const EventContext& ctx = Gaudi::Hive::currentContext()) const = 0;
+
+  virtual
+  FaserActsGeometryContext
+  getNominalGeometryContext() const = 0;
+};
+
+#endif
diff --git a/Tracking/Acts/FaserActsKalmanFilter/CMakeLists.txt b/Tracking/Acts/FaserActsKalmanFilter/CMakeLists.txt
new file mode 100755
index 0000000000000000000000000000000000000000..2e4f94741746e376b7f79ea1da16cb2921f825a3
--- /dev/null
+++ b/Tracking/Acts/FaserActsKalmanFilter/CMakeLists.txt
@@ -0,0 +1,55 @@
+# Declare the package name:
+atlas_subdir(FaserActsKalmanFilter)
+
+# External dependencies:
+find_package( CLHEP )
+find_package( Eigen )
+find_package( Boost )
+find_package( Acts COMPONENTS Core )
+
+# Component(s) in the package:
+atlas_add_library( FaserActsKalmanFilterLib
+    PUBLIC_HEADERS FaserActsKalmanFilter
+    INCLUDE_DIRS ${CLHEP_INCLUDE_DIRS} ${EIGEN_INCLUDE_DIRS} ${BOOST_INCLUDE_DIRS}
+    LINK_LIBRARIES ${CLHEP_LIBRARIES} ${EIGEN_LIBRARIES}
+    AthenaKernel
+    ActsCore
+    TrackerIdentifier
+    TrackerReadoutGeometry
+    ActsInteropLib
+    FaserActsGeometryLib
+    FaserActsGeometryInterfacesLib
+)
+
+atlas_add_component(FaserActsKalmanFilter
+    src/*.cxx
+    src/components/*.cxx
+    FaserActsKalmanFilter/*.h
+    FaserActsKalmanFilter/src/*.cxx
+    PUBLIC_HEADERS FaserActsKalmanFilter
+    INCLUDE_DIRS ${CLHEP_INCLUDE_DIRS} ${EIGEN_INCLUDE_DIRS} ${BOOST_INCLUDE_DIRS}
+    LINK_LIBRARIES ${CLHEP_LIBRARIES} ${EIGEN_LIBRARIES}
+    ActsCore
+    EventInfo
+    FaserActsKalmanFilterLib
+    ActsInteropLib
+    FaserActsGeometryLib
+    FaserActsGeometryInterfacesLib
+    MagFieldInterfaces
+    MagFieldElements
+    MagFieldConditions
+    TrkPrepRawData
+    TrackerPrepRawData
+    TrackerSpacePoint
+    GeoModelUtilities
+    GeneratorObjects
+    TrackerIdentifier
+    TrackerReadoutGeometry
+    Identifier
+    TrackerSimData
+)
+
+# Install files from the package:
+atlas_install_headers(FaserActsKalmanFilter)
+atlas_install_python_modules( python/*.py )
+atlas_install_scripts( test/*.py )
diff --git a/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/FaserActsKalmanFilterAlg.h b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/FaserActsKalmanFilterAlg.h
new file mode 100755
index 0000000000000000000000000000000000000000..da8f7995c1e16469392f48e2472763049dea053d
--- /dev/null
+++ b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/FaserActsKalmanFilterAlg.h
@@ -0,0 +1,271 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef FASERACTSKALMANFILTER_FASERACTSKALMANFILTERALG_H
+#define FASERACTSKALMANFILTER_FASERACTSKALMANFILTERALG_H
+
+// ATHENA
+#include "AthenaBaseComps/AthAlgorithm.h"
+#include "AthenaBaseComps/AthReentrantAlgorithm.h"
+#include "GaudiKernel/ServiceHandle.h"
+#include "GaudiKernel/ITHistSvc.h"
+#include "Gaudi/Property.h"  /*no forward decl: typedef*/
+#include "GaudiKernel/ISvcLocator.h"
+#include "StoreGate/StoreGateSvc.h"
+#include "StoreGate/ReadCondHandleKey.h"
+#include "TrackerPrepRawData/FaserSCT_ClusterCollection.h"
+#include "TrkSpacePoint/SpacePoint.h"
+#include "MagFieldConditions/FaserFieldCacheCondObj.h"
+#include "MagFieldElements/FaserFieldCache.h"
+#include "TrackerReadoutGeometry/SiDetectorElementCollection.h"
+#include "TrackerSpacePoint/SpacePointForSeedCollection.h"
+#include "Identifier/Identifier.h"
+#include "GeneratorObjects/McEventCollection.h"
+#include "TrackerSimData/TrackerSimDataCollection.h"
+
+// ACTS
+#include "Acts/MagneticField/ConstantBField.hpp"
+#include "Acts/MagneticField/InterpolatedBFieldMap.hpp"
+#include "Acts/MagneticField/SharedBField.hpp"
+#include "Acts/Propagator/EigenStepper.hpp"
+#include "Acts/Propagator/Propagator.hpp"
+#include "Acts/Propagator/detail/SteppingLogger.hpp"
+#include "Acts/Fitter/KalmanFitter.hpp"
+#include "Acts/Geometry/TrackingGeometry.hpp"
+#include "Acts/EventData/TrackParameters.hpp"
+#include "Acts/Geometry/GeometryID.hpp"
+#include "Acts/Utilities/Helpers.hpp"
+#include "Acts/Utilities/Definitions.hpp"
+
+// PACKAGE
+#include "FaserActsGeometry/FASERMagneticFieldWrapper.h"
+#include "FaserActsGeometry/FaserActsTrackingGeometryTool.h"
+#include "FaserActsGeometryInterfaces/IFaserActsTrackingGeometryTool.h"
+#include "FaserActsGeometryInterfaces/IFaserActsExtrapolationTool.h"
+#include "FaserActsKalmanFilter/FaserActsRecSourceLink.h"
+#include "FaserActsKalmanFilter/FaserActsRecMultiTrajectory.h"
+
+// STL
+#include <memory>
+#include <vector>
+#include <fstream>
+#include <mutex>
+
+class EventContext;
+class IAthRNGSvc;
+class FaserSCT_ID;
+class TTree;
+
+namespace ActsExtrapolationDetail {
+  class VariantPropagator;
+}
+
+namespace TrackerDD {
+  class SCT_DetectorManager;
+}
+
+using TrajectoryContainer = std::vector<FaserActsRecMultiTrajectory>;
+
+//class FaserActsKalmanFilterAlg : public AthReentrantAlgorithm {
+class FaserActsKalmanFilterAlg : public AthAlgorithm {
+public:
+  FaserActsKalmanFilterAlg (const std::string& name, ISvcLocator* pSvcLocator);
+  StatusCode initialize() override;
+  //StatusCode execute(const EventContext& ctx) const override;
+  StatusCode execute() override;
+  StatusCode finalize() override;
+ 
+  using FitterResult = Acts::Result<Acts::KalmanFitterResult<RecSourceLink>>;
+  // Fit function that takes input measurements, initial trackstate and fitter
+  // options and returns some fit-specific result.
+  using FitterFunction = std::function<FitterResult(
+     const std::vector<RecSourceLink>&,
+     const Acts::CurvilinearParameters&,
+     const Acts::KalmanFitterOptions<Acts::VoidOutlierFinder>&)>;
+
+  // Create the fitter function implementation.
+  static FitterFunction
+  makeFitterFunction(
+     ActsExtrapolationDetail::VariantPropagator* varProp);
+
+  virtual
+  Acts::MagneticFieldContext
+  //getMagneticFieldContext(const EventContext& ctx) const;
+  getMagneticFieldContext() const;
+
+  void initializeTree();
+
+  void fillFitResult(const Acts::GeometryContext& geoctx, const TrajectoryContainer& trajectories, const Acts::BoundParameters& truthParam);
+
+  void clearTrackVariables();
+
+private:
+  const FaserSCT_ID* m_idHelper{nullptr};
+
+  // Read handle for conditions object to get the field cache
+  SG::ReadCondHandleKey<FaserFieldCacheCondObj> m_fieldCondObjInputKey {this, "FaserFieldCacheCondObj", "fieldCondObj", "Name of the Magnetic Field conditions object key"};
+
+  ToolHandle<IFaserActsExtrapolationTool> m_extrapolationTool{this, "ExtrapolationTool", "FaserActsExtrapolationTool"};
+
+  Gaudi::Property<std::string> m_fieldMode{this, "FieldMode", "FASER"};
+  Gaudi::Property<std::vector<double>> m_constantFieldVector{this, "ConstantFieldVector", {0, 0, 0}};
+
+  SG::ReadHandleKey<SpacePointForSeedCollection>  m_seed_spcollectionKey{this, "FaserSpacePointsSeedsName", "SpacePointForSeedCollection", "SpacePointForSeedCollection"};
+
+    SG::ReadHandleKey<McEventCollection> m_mcEventKey       { this, "McEventCollection", "GEN_EVENT" };
+    SG::ReadHandleKey<TrackerSimDataCollection> m_sctMap {this, "TrackerSimDataCollection", "SCT_SDO_Map"};
+    const TrackerDD::SCT_DetectorManager* m_detManager{nullptr};
+
+  ServiceHandle<ITHistSvc> m_thistSvc;
+
+  TTree *m_trackTree{nullptr};
+
+  /// Acts tree values
+  int m_eventNr{0};
+  int m_trajNr{0};
+  int m_trackNr{0};
+
+  unsigned long m_t_barcode{0};  /// Truth particle barcode
+  int m_t_charge{0};             /// Truth particle charge
+  float m_t_eT{0};               /// Truth particle time on the first layer
+  float m_t_eLOC0{-99.};         /// Truth local x on the first layer
+  float m_t_eLOC1{-99.};         /// Truth local y on the first layer
+  float m_t_eTHETA{-99.};        /// Truth particle momentum theta on the first layer
+  float m_t_ePHI{-99.};          /// Truth particle momentum phi on the first layer
+  float m_t_eQOP{-99.};          /// Truth particle momentum qop on the first layer
+  float m_t_x{-99.};             /// Truth particle position x on the first layer
+  float m_t_y{-99.};             /// Truth particle position y on the first layer
+  float m_t_z{-99.};             /// Truth particle position z on the first layer
+  float m_t_px{-99.};            /// Truth particle momentum px on the first layer
+  float m_t_py{-99.};            /// Truth particle momentum py on the first layer
+  float m_t_pz{-99.};            /// Truth particle momentum pz on the first layer
+
+  int m_nHoles{0};                  /// number of holes in the track fit
+  int m_nOutliers{0};               /// number of outliers in the track fit
+  int m_nStates{0};                 /// number of all states
+  int m_nMeasurements{0};           /// number of states with measurements
+  std::vector<int> m_volumeID;      /// volume identifier
+  std::vector<int> m_layerID;       /// layer identifier
+  std::vector<int> m_moduleID;      /// surface identifier
+  std::vector<float> m_lx_hit;      /// uncalibrated measurement local x
+  std::vector<float> m_ly_hit;      /// uncalibrated measurement local y
+  std::vector<float> m_x_hit;       /// uncalibrated measurement global x
+  std::vector<float> m_y_hit;       /// uncalibrated measurement global y
+  std::vector<float> m_z_hit;       /// uncalibrated measurement global z
+  std::vector<float> m_res_x_hit;   /// hit residual x
+  std::vector<float> m_res_y_hit;   /// hit residual y
+  std::vector<float> m_err_x_hit;   /// hit err x
+  std::vector<float> m_err_y_hit;   /// hit err y
+  std::vector<float> m_pull_x_hit;  /// hit pull x
+  std::vector<float> m_pull_y_hit;  /// hit pull y
+  std::vector<int> m_dim_hit;       /// dimension of measurement
+
+  bool m_hasFittedParams{false};  /// if the track has fitted parameter
+  float m_eLOC0_fit{-99.};        /// fitted parameter eLOC_0
+  float m_eLOC1_fit{-99.};        /// fitted parameter eLOC_1
+  float m_ePHI_fit{-99.};         /// fitted parameter ePHI
+  float m_eTHETA_fit{-99.};       /// fitted parameter eTHETA
+  float m_eQOP_fit{-99.};         /// fitted parameter eQOP
+  float m_eT_fit{-99.};           /// fitted parameter eT
+  float m_err_eLOC0_fit{-99.};    /// fitted parameter eLOC_-99.err
+  float m_err_eLOC1_fit{-99.};    /// fitted parameter eLOC_1 err
+  float m_err_ePHI_fit{-99.};     /// fitted parameter ePHI err
+  float m_err_eTHETA_fit{-99.};   /// fitted parameter eTHETA err
+  float m_err_eQOP_fit{-99.};     /// fitted parameter eQOP err
+  float m_err_eT_fit{-99.};       /// fitted parameter eT err
+  float m_px_fit{-99.};           /// fitted parameter global px
+  float m_py_fit{-99.};           /// fitted parameter global py
+  float m_pz_fit{-99.};           /// fitted parameter global pz
+  float m_x_fit{-99.};            /// fitted parameter global PCA x
+  float m_y_fit{-99.};            /// fitted parameter global PCA y
+  float m_z_fit{-99.};            /// fitted parameter global PCA z
+  float m_chi2_fit{-99.};         /// fitted parameter chi2
+  float m_ndf_fit{-99.};          /// fitted parameter ndf
+  int m_charge_fit{-99};          /// fitted parameter charge
+
+  int m_nPredicted{0};                   /// number of states with predicted parameter
+  std::vector<bool> m_prt;               /// predicted status
+  std::vector<float> m_eLOC0_prt;        /// predicted parameter eLOC0
+  std::vector<float> m_eLOC1_prt;        /// predicted parameter eLOC1
+  std::vector<float> m_ePHI_prt;         /// predicted parameter ePHI
+  std::vector<float> m_eTHETA_prt;       /// predicted parameter eTHETA
+  std::vector<float> m_eQOP_prt;         /// predicted parameter eQOP
+  std::vector<float> m_eT_prt;           /// predicted parameter eT
+  std::vector<float> m_res_eLOC0_prt;    /// predicted parameter eLOC0 residual
+  std::vector<float> m_res_eLOC1_prt;    /// predicted parameter eLOC1 residual
+  std::vector<float> m_err_eLOC0_prt;    /// predicted parameter eLOC0 error
+  std::vector<float> m_err_eLOC1_prt;    /// predicted parameter eLOC1 error
+  std::vector<float> m_err_ePHI_prt;     /// predicted parameter ePHI error
+  std::vector<float> m_err_eTHETA_prt;   /// predicted parameter eTHETA error
+  std::vector<float> m_err_eQOP_prt;     /// predicted parameter eQOP error
+  std::vector<float> m_err_eT_prt;       /// predicted parameter eT error
+  std::vector<float> m_pull_eLOC0_prt;   /// predicted parameter eLOC0 pull
+  std::vector<float> m_pull_eLOC1_prt;   /// predicted parameter eLOC1 pull
+  std::vector<float> m_x_prt;            /// predicted global x
+  std::vector<float> m_y_prt;            /// predicted global y
+  std::vector<float> m_z_prt;            /// predicted global z
+  std::vector<float> m_px_prt;           /// predicted momentum px
+  std::vector<float> m_py_prt;           /// predicted momentum py
+  std::vector<float> m_pz_prt;           /// predicted momentum pz
+  std::vector<float> m_eta_prt;          /// predicted momentum eta
+  std::vector<float> m_pT_prt;           /// predicted momentum pT
+
+  int m_nFiltered{0};                    /// number of states with filtered parameter
+  std::vector<bool> m_flt;               /// filtered status
+  std::vector<float> m_eLOC0_flt;        /// filtered parameter eLOC0
+  std::vector<float> m_eLOC1_flt;        /// filtered parameter eLOC1
+  std::vector<float> m_ePHI_flt;         /// filtered parameter ePHI
+  std::vector<float> m_eTHETA_flt;       /// filtered parameter eTHETA
+  std::vector<float> m_eQOP_flt;         /// filtered parameter eQOP
+  std::vector<float> m_eT_flt;           /// filtered parameter eT
+  std::vector<float> m_res_eLOC0_flt;    /// filtered parameter eLOC0 residual
+  std::vector<float> m_res_eLOC1_flt;    /// filtered parameter eLOC1 residual
+  std::vector<float> m_err_eLOC0_flt;    /// filtered parameter eLOC0 error
+  std::vector<float> m_err_eLOC1_flt;    /// filtered parameter eLOC1 error
+  std::vector<float> m_err_ePHI_flt;     /// filtered parameter ePHI error
+  std::vector<float> m_err_eTHETA_flt;   /// filtered parameter eTHETA error
+  std::vector<float> m_err_eQOP_flt;     /// filtered parameter eQOP error
+  std::vector<float> m_err_eT_flt;       /// filtered parameter eT error
+  std::vector<float> m_pull_eLOC0_flt;   /// filtered parameter eLOC0 pull
+  std::vector<float> m_pull_eLOC1_flt;   /// filtered parameter eLOC1 pull
+  std::vector<float> m_x_flt;            /// filtered global x
+  std::vector<float> m_y_flt;            /// filtered global y
+  std::vector<float> m_z_flt;            /// filtered global z
+  std::vector<float> m_px_flt;           /// filtered momentum px
+  std::vector<float> m_py_flt;           /// filtered momentum py
+  std::vector<float> m_pz_flt;           /// filtered momentum pz
+  std::vector<float> m_eta_flt;          /// filtered momentum eta
+  std::vector<float> m_pT_flt;           /// filtered momentum pT
+  std::vector<float> m_chi2;             /// chisq from filtering
+
+  int m_nSmoothed{0};                    /// number of states with smoothed parameter
+  std::vector<bool> m_smt;               /// smoothed status
+  std::vector<float> m_eLOC0_smt;        /// smoothed parameter eLOC0
+  std::vector<float> m_eLOC1_smt;        /// smoothed parameter eLOC1
+  std::vector<float> m_ePHI_smt;         /// smoothed parameter ePHI
+  std::vector<float> m_eTHETA_smt;       /// smoothed parameter eTHETA
+  std::vector<float> m_eQOP_smt;         /// smoothed parameter eQOP
+  std::vector<float> m_eT_smt;           /// smoothed parameter eT
+  std::vector<float> m_res_eLOC0_smt;    /// smoothed parameter eLOC0 residual
+  std::vector<float> m_res_eLOC1_smt;    /// smoothed parameter eLOC1 residual
+  std::vector<float> m_err_eLOC0_smt;    /// smoothed parameter eLOC0 error
+  std::vector<float> m_err_eLOC1_smt;    /// smoothed parameter eLOC1 error
+  std::vector<float> m_err_ePHI_smt;     /// smoothed parameter ePHI error
+  std::vector<float> m_err_eTHETA_smt;   /// smoothed parameter eTHETA error
+  std::vector<float> m_err_eQOP_smt;     /// smoothed parameter eQOP error
+  std::vector<float> m_err_eT_smt;       /// smoothed parameter eT error
+  std::vector<float> m_pull_eLOC0_smt;   /// smoothed parameter eLOC0 pull
+  std::vector<float> m_pull_eLOC1_smt;   /// smoothed parameter eLOC1 pull
+  std::vector<float> m_x_smt;            /// smoothed global x
+  std::vector<float> m_y_smt;            /// smoothed global y
+  std::vector<float> m_z_smt;            /// smoothed global z
+  std::vector<float> m_px_smt;           /// smoothed momentum px
+  std::vector<float> m_py_smt;           /// smoothed momentum py
+  std::vector<float> m_pz_smt;           /// smoothed momentum pz
+  std::vector<float> m_eta_smt;          /// smoothed momentum eta
+  std::vector<float> m_pT_smt;           /// smoothed momentum pT
+
+};
+
+#endif
diff --git a/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/FaserActsRecMultiTrajectory.h b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/FaserActsRecMultiTrajectory.h
new file mode 100644
index 0000000000000000000000000000000000000000..bea0c15839b628789ffee7da18b54b9b9e255350
--- /dev/null
+++ b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/FaserActsRecMultiTrajectory.h
@@ -0,0 +1,87 @@
+// Copyright (C) 2019 CERN for the benefit of the Acts project
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/
+
+#pragma once
+
+#include <unordered_map>
+#include <utility>
+
+// ACTS
+#include "Acts/EventData/MultiTrajectory.hpp"
+#include "Acts/EventData/TrackParameters.hpp"
+
+// PACKAGE
+#include "FaserActsKalmanFilter/FaserActsRecSourceLink.h"
+
+using IndexedParams = std::unordered_map<size_t, Acts::BoundParameters>;
+
+struct FaserActsRecMultiTrajectory
+{
+ public:
+  FaserActsRecMultiTrajectory() = default;
+
+  FaserActsRecMultiTrajectory(const Acts::MultiTrajectory<RecSourceLink>& multiTraj,
+                     const std::vector<size_t>& tTips,
+                     const IndexedParams& parameters)
+      : m_multiTrajectory(multiTraj),
+        m_trackTips(tTips),
+        m_trackParameters(parameters) {}
+
+  FaserActsRecMultiTrajectory(const FaserActsRecMultiTrajectory& rhs)
+      : m_multiTrajectory(rhs.m_multiTrajectory),
+        m_trackTips(rhs.m_trackTips),
+        m_trackParameters(rhs.m_trackParameters) {}
+
+  FaserActsRecMultiTrajectory(FaserActsRecMultiTrajectory&& rhs)
+      : m_multiTrajectory(std::move(rhs.m_multiTrajectory)),
+        m_trackTips(std::move(rhs.m_trackTips)),
+        m_trackParameters(std::move(rhs.m_trackParameters)) {}
+
+  ~FaserActsRecMultiTrajectory() = default;
+
+  FaserActsRecMultiTrajectory& operator=(const FaserActsRecMultiTrajectory& rhs) {
+    m_multiTrajectory = rhs.m_multiTrajectory;
+    m_trackTips = rhs.m_trackTips;
+    m_trackParameters = rhs.m_trackParameters;
+    return *this;
+  }
+
+  FaserActsRecMultiTrajectory& operator=(FaserActsRecMultiTrajectory&& rhs) {
+    m_multiTrajectory = std::move(rhs.m_multiTrajectory);
+    m_trackTips = std::move(rhs.m_trackTips);
+    m_trackParameters = std::move(rhs.m_trackParameters);
+    return *this;
+  }
+
+  bool hasTrajectory(const size_t& entryIndex) const {
+    return std::count(m_trackTips.begin(), m_trackTips.end(), entryIndex) > 0;
+  }
+
+  bool hasTrackParameters(const size_t& entryIndex) const {
+    return m_trackParameters.count(entryIndex) > 0;
+  }
+
+  std::pair<std::vector<size_t>, Acts::MultiTrajectory<RecSourceLink>>
+  trajectory() const {
+    return std::make_pair(m_trackTips, m_multiTrajectory);
+  }
+
+  const Acts::BoundParameters& trackParameters(const size_t& entryIndex) const {
+    auto it = m_trackParameters.find(entryIndex);
+    if (it != m_trackParameters.end()) {
+      return it->second;
+    } else {
+      throw std::runtime_error(
+          "No fitted track parameters for trajectory with entry index = " +
+          std::to_string(entryIndex));
+    }
+  }
+
+ private:
+  Acts::MultiTrajectory<RecSourceLink> m_multiTrajectory;
+  std::vector<size_t> m_trackTips = {};
+  IndexedParams m_trackParameters = {};
+};
diff --git a/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/FaserActsRecSourceLink.h b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/FaserActsRecSourceLink.h
new file mode 100644
index 0000000000000000000000000000000000000000..def70b00d059e7f8271a50c475e2e62514bec2a2
--- /dev/null
+++ b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/FaserActsRecSourceLink.h
@@ -0,0 +1,44 @@
+# pragma once
+
+// ACTS
+#include "Acts/EventData/Measurement.hpp"
+#include "Acts/Utilities/ParameterDefinitions.hpp"
+
+// ATHENA
+#include "TrkSpacePoint/SpacePoint.h"
+
+
+class RecSourceLink {
+public:
+    // TODO convert Trk::LocalParameters to acts::BoundVector and Amg::MatrixX& to ACTS::BoundMatrix
+    RecSourceLink(const Acts::Surface& surface, const Trk::SpacePoint& spacePoint)
+        : m_values(spacePoint.localParameters()),
+          m_cov(spacePoint.localCovariance()),
+          m_surface(&surface),
+          m_spacePoint(&spacePoint) {}
+
+    RecSourceLink() = default;
+
+    constexpr const Acts::Surface& referenceSurface() const { return *m_surface; }
+    constexpr const Trk::SpacePoint& spacePoint() const { return *m_spacePoint; }
+
+    Acts::FittableMeasurement<RecSourceLink> operator*() const {
+        return Acts::Measurement<RecSourceLink, Acts::BoundParametersIndices, Acts::ParDef::eLOC_0, Acts::ParDef::eLOC_1> {
+            m_surface->getSharedPtr(),
+            *this,
+            m_cov.topLeftCorner<2, 2>(),
+            m_values[0],
+            m_values[1]
+        };
+    }
+
+private:
+    Acts::BoundVector m_values;
+    Acts::BoundMatrix m_cov;
+    const Acts::Surface* m_surface;
+    const Trk::SpacePoint* m_spacePoint;
+
+    friend constexpr bool operator==(const RecSourceLink& lhs, const RecSourceLink& rhs) {
+        return lhs.m_spacePoint == rhs.m_spacePoint;
+    }
+};
diff --git a/Tracking/Acts/FaserActsKalmanFilter/python/FaserActsKalmanFilterConfig.py b/Tracking/Acts/FaserActsKalmanFilter/python/FaserActsKalmanFilterConfig.py
new file mode 100644
index 0000000000000000000000000000000000000000..0a955d80a50c7fcb5de8878841404565cd870f1b
--- /dev/null
+++ b/Tracking/Acts/FaserActsKalmanFilter/python/FaserActsKalmanFilterConfig.py
@@ -0,0 +1,48 @@
+from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator
+from AthenaConfiguration.ComponentFactory import CompFactory
+from OutputStreamAthenaPool.OutputStreamConfig import OutputStreamCfg
+from MagFieldServices.MagFieldServicesConfig import MagneticFieldSvcCfg
+
+FaserActsKalmanFilterAlg,FaserActsTrackingGeometrySvc, FaserActsTrackingGeometryTool, FaserActsExtrapolationTool,FaserActsAlignmentCondAlg, THistSvc = CompFactory.getComps("FaserActsKalmanFilterAlg","FaserActsTrackingGeometrySvc", "FaserActsTrackingGeometryTool", "FaserActsExtrapolationTool","FaserActsAlignmentCondAlg", "THistSvc")
+
+def FaserActsTrackingGeometrySvcCfg(flags, **kwargs):
+    acc = ComponentAccumulator()
+    acc.addService(FaserActsTrackingGeometrySvc(name = "FaserActsTrackingGeometrySvc", **kwargs))
+    return acc 
+
+def FaserActsAlignmentCondAlgCfg(flags, **kwargs):
+    acc = ComponentAccumulator()
+    acc.addCondAlgo(CompFactory.FaserActsAlignmentCondAlg(name = "FaserActsAlignmentCondAlg", **kwargs))
+    #acc.addCondAlgo(CompFactory.NominalAlignmentCondAlg(name = "NominalAlignmentCondAlg", **kwargs))
+    return acc
+
+def FaserActsKalmanFilterCfg(flags, **kwargs):
+    acc = ComponentAccumulator()
+    # Initialize field service
+    acc.merge(MagneticFieldSvcCfg(flags))
+
+    acc.merge(FaserActsTrackingGeometrySvcCfg(flags, **kwargs))
+    acc.merge(FaserActsAlignmentCondAlgCfg(flags, **kwargs))
+    
+    kwargs.setdefault("FaserSpacePointsSeedsName", "Seeds_SpacePointContainer")
+    actsKalmanFilterAlg = FaserActsKalmanFilterAlg(**kwargs)
+    #actsKalmanFilterAlg.TrackingGeometryTool = FaserActsTrackingGeometryTool("TrackingGeometryTool")
+    actsExtrapolationTool=FaserActsExtrapolationTool("FaserActsExtrapolationTool")
+    actsExtrapolationTool.FieldMode="FASER"
+    #actsExtrapolationTool.FieldMode="Constant"
+    actsExtrapolationTool.TrackingGeometryTool=FaserActsTrackingGeometryTool("TrackingGeometryTool")
+    actsKalmanFilterAlg.ExtrapolationTool=actsExtrapolationTool
+    acc.addEventAlgo(actsKalmanFilterAlg)
+    histSvc= THistSvc()
+    histSvc.Output += [ "KalmanTracks DATAFILE='KalmanTracks.root' OPT='RECREATE'" ]
+    acc.addService(histSvc)
+    acc.merge(FaserActsKalmanFilter_OutputCfg(flags))
+    return  acc
+
+def FaserActsKalmanFilter_OutputCfg(flags):
+    """Return ComponentAccumulator with Output for SCT. Not standalone."""
+    acc = ComponentAccumulator()
+    acc.merge(OutputStreamCfg(flags, "ESD"))
+    ostream = acc.getEventAlgo("OutputStreamESD")
+    ostream.TakeItemsFromInput = True
+    return acc
diff --git a/Tracking/Acts/FaserActsKalmanFilter/src/FaserActsKalmanFilterAlg.cxx b/Tracking/Acts/FaserActsKalmanFilter/src/FaserActsKalmanFilterAlg.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..7edff9fcd843ed8edbfdadab52ba8ed0c1f6c95a
--- /dev/null
+++ b/Tracking/Acts/FaserActsKalmanFilter/src/FaserActsKalmanFilterAlg.cxx
@@ -0,0 +1,1207 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "FaserActsKalmanFilter/FaserActsKalmanFilterAlg.h"
+
+// ATHENA
+#include "GaudiKernel/EventContext.h"
+#include "GaudiKernel/ISvcLocator.h"
+#include "GaudiKernel/PhysicalConstants.h"
+#include "TrackerReadoutGeometry/SCT_DetectorManager.h"
+#include "TrackerReadoutGeometry/SiDetectorDesign.h"
+#include "TrackerReadoutGeometry/SiLocalPosition.h"
+#include "TrackerReadoutGeometry/SiDetectorElement.h"
+#include "TrackerSpacePoint/FaserSCT_SpacePoint.h"
+#include "TrackerSpacePoint/SpacePointForSeedCollection.h"
+#include "TrackerIdentifier/FaserSCT_ID.h"
+#include "FaserDetDescr/FaserDetectorID.h"
+
+// ACTS
+#include "Acts/Fitter/GainMatrixSmoother.hpp"
+#include "Acts/Fitter/GainMatrixUpdater.hpp"
+#include "Acts/Geometry/GeometryID.hpp"
+#include "Acts/MagneticField/ConstantBField.hpp"
+#include "Acts/MagneticField/InterpolatedBFieldMap.hpp"
+#include "Acts/MagneticField/SharedBField.hpp"
+#include "Acts/MagneticField/MagneticFieldContext.hpp"
+#include "Acts/Propagator/EigenStepper.hpp"
+#include "Acts/Propagator/Navigator.hpp"
+#include "Acts/Propagator/Propagator.hpp"
+#include "Acts/Surfaces/Surface.hpp"
+#include "Acts/Surfaces/PlaneSurface.hpp"
+#include "Acts/Surfaces/PerigeeSurface.hpp"
+#include "Acts/Surfaces/RectangleBounds.hpp"
+#include "Acts/Utilities/Units.hpp"
+#include "Acts/Utilities/Logger.hpp"
+#include "Acts/Utilities/Helpers.hpp"
+#include "Acts/Utilities/detail/periodic.hpp"
+#include "Acts/Utilities/Definitions.hpp"
+#include "Acts/Utilities/ParameterDefinitions.hpp"
+#include "Acts/Utilities/CalibrationContext.hpp"
+#include "Acts/EventData/TrackParameters.hpp"
+#include "Acts/EventData/MultiTrajectoryHelpers.hpp"
+#include "Acts/EventData/Measurement.hpp"
+
+
+// PACKAGE
+#include "FaserActsGeometryInterfaces/IFaserActsTrackingGeometryTool.h"
+#include "ActsInterop/Logger.h"
+#include "FaserActsGeometry/FaserActsGeometryContext.h"
+#include "FaserActsGeometry/IFaserActsPropStepRootWriterSvc.h"
+#include "FaserActsGeometry/FaserActsDetectorElement.h"
+#include "FaserActsKalmanFilter/FaserActsRecSourceLink.h"
+#include "FaserActsKalmanFilter/FaserActsRecMultiTrajectory.h"
+
+//ROOT
+#include <TTree.h>
+
+// BOOST
+#include <boost/variant/variant.hpp>
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/variant/static_visitor.hpp>
+
+// STL
+#include <string>
+#include <fstream>
+#include <cmath>
+#include <random>
+
+using TrajectoryContainer = std::vector<FaserActsRecMultiTrajectory>;
+
+using namespace Acts::UnitLiterals;
+using Acts::VectorHelpers::eta;
+using Acts::VectorHelpers::perp;
+using Acts::VectorHelpers::phi;
+using Acts::VectorHelpers::theta;
+using Measurement = Acts::Measurement<RecSourceLink, Acts::BoundParametersIndices, Acts::ParDef::eLOC_0,
+                                      Acts::ParDef::eLOC_1>;
+
+namespace ActsExtrapolationDetail {
+  using VariantPropagatorBase = boost::variant<
+    Acts::Propagator<Acts::EigenStepper<FASERMagneticFieldWrapper>, Acts::Navigator>,
+    Acts::Propagator<Acts::EigenStepper<Acts::ConstantBField>, Acts::Navigator>
+  >;
+
+  class VariantPropagator : public VariantPropagatorBase
+  {
+  public:
+    using VariantPropagatorBase::VariantPropagatorBase;
+  };
+
+}
+
+using ActsExtrapolationDetail::VariantPropagator;
+
+
+FaserActsKalmanFilterAlg::FaserActsKalmanFilterAlg(const std::string& name,
+                                 ISvcLocator* pSvcLocator)
+    //: AthReentrantAlgorithm(name, pSvcLocator)
+    : AthAlgorithm(name, pSvcLocator)
+      , m_thistSvc("THistSvc", name)
+{
+}
+
+StatusCode FaserActsKalmanFilterAlg::initialize() {
+
+  ATH_MSG_DEBUG(name() << "::" << __FUNCTION__);
+
+  ATH_MSG_INFO("Initializing ACTS kalman filter");
+
+  ATH_CHECK( m_fieldCondObjInputKey.initialize() );
+
+  ATH_CHECK( m_extrapolationTool.retrieve() );
+
+  if ( m_seed_spcollectionKey.key().empty()){
+    ATH_MSG_FATAL( "SCTs selected and no name set for SCT clusters");
+    return StatusCode::FAILURE;
+  }
+
+  ATH_CHECK( m_seed_spcollectionKey.initialize() );
+
+  ATH_CHECK( m_mcEventKey.initialize() );
+
+  ATH_CHECK( m_sctMap.initialize());
+
+  ATH_CHECK(detStore()->retrieve(m_idHelper,"FaserSCT_ID"));
+	
+  ATH_CHECK(detStore()->retrieve(m_detManager, "SCT"));
+
+  ATH_CHECK(m_thistSvc.retrieve());
+
+  m_trackTree = new TTree("tracks", "");
+
+  ATH_CHECK(m_thistSvc->regTree("/KalmanTracks/tracks", m_trackTree));
+  
+  if (m_trackTree) {
+    initializeTree();
+  }
+  else {
+    ATH_MSG_ERROR("No tree found!");
+  }
+
+  ATH_MSG_INFO("ACTS kalman filter successfully initialized");
+  return StatusCode::SUCCESS;
+}
+
+//StatusCode FaserActsKalmanFilterAlg::execute(const EventContext& ctx) const
+StatusCode FaserActsKalmanFilterAlg::execute()
+{
+
+  ATH_MSG_VERBOSE(name() << "::" << __FUNCTION__);
+
+  m_eventNr++;
+
+  //SG::ReadHandle<SpacePointForSeedCollection> seed_spcollection( m_seed_spcollectionKey, ctx );
+  SG::ReadHandle<SpacePointForSeedCollection> seed_spcollection( m_seed_spcollectionKey );
+  if (!seed_spcollection.isValid()){
+    msg(MSG:: FATAL) << "Could not find the data object "<< seed_spcollection.name() << " !" << endmsg;
+    return StatusCode::RECOVERABLE;
+  }
+
+  const FaserActsGeometryContext& gctx
+      = m_extrapolationTool->trackingGeometryTool()->getNominalGeometryContext();
+  auto geoctx = gctx.any();
+  Acts::MagneticFieldContext magctx = getMagneticFieldContext();
+  Acts::CalibrationContext calctx;
+
+  std::shared_ptr<const Acts::TrackingGeometry> trackingGeometry
+      = m_extrapolationTool->trackingGeometryTool()->trackingGeometry();
+  const Acts::TrackingVolume* tVolume = trackingGeometry->highestTrackingVolume();
+
+  std::vector<RecSourceLink> sourceLinks;
+
+  std::shared_ptr<const Acts::Surface> pSurface;
+
+  // Get SiDetectorElements
+  const TrackerDD::SiDetectorElementCollection* elCollection{m_detManager->getDetectorElementCollection()};
+  if (elCollection == nullptr) {
+    ATH_MSG_FATAL("Null pointer is returned by getDetectorElementCollection()");
+    return StatusCode::FAILURE;
+  }
+
+
+	//!!!!!!!!!!!!!!!!!!!!
+    static const TrackerDD::SCT_DetectorManager     *s_sct;
+    if(detStore()->retrieve(s_sct,"SCT").isFailure()) s_sct = 0;
+	int N_1_0=0, N_1_1=0, N_1_2=0, N_2_0=0, N_2_1=0, N_2_2=0;
+  Acts::Vector3D pos1_0(0., 0., 0.);
+  Acts::Vector3D pos1_1(0., 0., 0.);
+  Acts::Vector3D pos1_2(0., 0., 0.);
+  Acts::Vector3D pos2_0(0., 0., 0.);
+  Acts::Vector3D pos2_1(0., 0., 0.);
+  Acts::Vector3D pos2_2(0., 0., 0.);
+        HepMC::FourVector truthmom;
+        HepMC::FourVector pv;
+	//!!!!!!!!!!!!!!!!!!!!
+
+  // Make the source links
+  SpacePointForSeedCollection::const_iterator it = seed_spcollection->begin();
+  SpacePointForSeedCollection::const_iterator itend = seed_spcollection->end();
+  for (; it != itend; ++it){
+    const SpacePointForSeed *seed_sp = &(**it);
+    const Trk::SpacePoint *sp = seed_sp->SpacePoint();
+    auto faserSp = (Tracker::FaserSCT_SpacePoint*)sp;
+        ATH_MSG_DEBUG("TruthSeededTrack: SapcePoint test");
+    faserSp->dump(msg(MSG::INFO));
+    // ATH_MSG_DEBUG("TruthSeededTrack: SapcePoint " << *sp);
+    const Identifier id = sp->clusterList().first->identify();
+
+    const TrackerDD::SiDetectorElement* siSpElement = m_detManager->getDetectorElement(id);
+    auto spElement = static_cast<const FaserActsDetectorElement>(siSpElement);
+
+	//!!!!!!!!!!!!!!!!!!!!
+	  // Get the truth position and momentum
+          //SG::ReadHandle<McEventCollection> h_mcEvents(m_mcEventKey, ctx);
+	  //SG::ReadHandle<TrackerSimDataCollection> h_collectionMap(m_sctMap, ctx);
+          SG::ReadHandle<McEventCollection> h_mcEvents(m_mcEventKey);
+	  SG::ReadHandle<TrackerSimDataCollection> h_collectionMap(m_sctMap);
+	  const auto& simdata = h_collectionMap->find(id)->second;
+	  const auto& deposits = simdata.getdeposits();
+	  for( const auto& depositPair : deposits)
+	  {
+		if (depositPair.first->pdg_id() == -13) {
+		pv = depositPair.first->production_vertex()->position();
+	        truthmom = depositPair.first->momentum();
+	        std::cout<<"!!!!!!!!!!!  production_vertex: ( "<<pv.x()<<",  "<<pv.y()<<",  "<<pv.z()<<" )  "<<std::endl;
+		}
+	  }
+
+	  // Get the measurements
+	Amg::Vector3D gloPos=sp->globalPosition();
+	int station = m_idHelper->station(id);
+	int plane = m_idHelper->layer(id);
+	if (station==1 && plane==0) { 
+		N_1_0++;
+	 pos1_0 = Acts::Vector3D(gloPos.x(), gloPos.y(), gloPos.z());
+           // Construct a plane surface as the target surface
+           const TrackerDD::SiDetectorDesign &design = siSpElement->design();
+           double hlX = design.width()/2. * 1_mm;
+           double hlY = design.length()/2. * 1_mm;
+           auto rectangleBounds = std::make_shared<const Acts::RectangleBounds>(hlX, hlY);
+	   Amg::Transform3D g2l = siSpElement->getMaterialGeom()->getDefAbsoluteTransform()
+			           * Amg::CLHEPTransformToEigen(siSpElement->recoToHitTransform());
+           pSurface = Acts::Surface::makeShared<Acts::PlaneSurface>(
+                           std::make_shared<const Acts::Transform3D>( g2l ), rectangleBounds );
+	   
+	}
+	if (station==1 && plane==1) {
+		N_1_1++;
+	 pos1_1 = Acts::Vector3D(gloPos.x(), gloPos.y(), gloPos.z());
+	}
+	if (station==1 && plane==2) {
+		N_1_2++;
+	 pos1_2 = Acts::Vector3D(gloPos.x(), gloPos.y(), gloPos.z());
+	}
+	if (station==2 && plane==0) {
+		N_2_0++;
+	 pos2_0 = Acts::Vector3D(gloPos.x(), gloPos.y(), gloPos.z());
+	}
+	if (station==2 && plane==1) {
+		N_2_1++;
+	 pos2_1 = Acts::Vector3D(gloPos.x(), gloPos.y(), gloPos.z());
+	}
+	if (station==2 && plane==2) {
+		N_2_2++;
+	 pos2_2 = Acts::Vector3D(gloPos.x(), gloPos.y(), gloPos.z());
+	}
+	//!!!!!!!!!!!!!!!!!!!!
+	
+  if (tVolume->confinedVolumes()) {
+    for (auto volume : tVolume->confinedVolumes()->arrayObjects()) {
+    if (volume->confinedLayers()) {
+      for (const auto& layer : volume->confinedLayers()->arrayObjects()) {
+        if (layer->layerType() == Acts::navigation) continue;
+        for (auto surface : layer->surfaceArray()->surfaces()) {
+          if (surface) {
+            const Acts::DetectorElementBase *detElement = surface->associatedDetectorElement();
+            const auto *faserDetElement = dynamic_cast<const FaserActsDetectorElement*>(detElement);
+            auto* tmp = const_cast<FaserActsDetectorElement*>(faserDetElement);
+            if (*tmp == spElement) {
+              sourceLinks.emplace_back(*const_cast<Acts::Surface*>(surface), *const_cast<Trk::SpacePoint*>(sp));
+            }
+          }
+        }
+      }
+    }
+  }
+  }
+ }
+
+  // Calculate the initial track parameters
+  if ( (N_1_0==1) && (N_1_1==1) && (N_1_2==1) && (N_2_0==1) && (N_2_1==1) && (N_2_2==1)) {
+  std::cout<<"!!!!!!!!!!!  pos1_0 = ("<<pos1_0.x()<<", "<<pos1_0.y()<<", "<<pos1_0.z()<<") "<<std::endl; 
+  std::cout<<"!!!!!!!!!!!  pos1_1 = ("<<pos1_1.x()<<", "<<pos1_1.y()<<", "<<pos1_1.z()<<") "<<std::endl;
+  std::cout<<"!!!!!!!!!!!  pos1_2 = ("<<pos1_2.x()<<", "<<pos1_2.y()<<", "<<pos1_2.z()<<") "<<std::endl;
+  std::cout<<"!!!!!!!!!!!  pos2_0 = ("<<pos2_0.x()<<", "<<pos2_0.y()<<", "<<pos2_0.z()<<") "<<std::endl; 
+  std::cout<<"!!!!!!!!!!!  pos2_1 = ("<<pos2_1.x()<<", "<<pos2_1.y()<<", "<<pos2_1.z()<<") "<<std::endl;
+  std::cout<<"!!!!!!!!!!!  pos2_2 = ("<<pos2_2.x()<<", "<<pos2_2.y()<<", "<<pos2_2.z()<<") "<<std::endl;
+  //@FIXME: change the hard codes in future 
+  double charge = 1;
+  double B = 0.55;
+  //const Acts::Vector3D pos = pos1_0;
+  const Acts::Vector3D pos(pos1_0.x(), pos1_0.y(), pos1_0.z()-1);
+  Acts::Vector3D d1 = pos1_2 - pos1_0;
+  Acts::Vector3D d2 = pos2_2 - pos2_0;
+  // the direction of momentum in the first station
+  Acts::Vector3D direct1 = d1.normalized();
+  // the direction of momentum in the second station
+  Acts::Vector3D direct2 = d2.normalized();
+  // the vector pointing from the center of circle to the particle at layer 2 in Y-Z plane
+  double R1_z = charge * direct1.y() / std::sqrt(direct1.y()*direct1.y() + direct1.z()*direct1.z());
+  // double R1_y = -charge * direct1.z() / std::sqrt(direct1.y()*direct1.y() + direct1.z()*direct1.z());
+  // the vector pointing from the center of circle to the particle at layer 3 in Y-Z plane
+  double R2_z = charge * direct2.y() / std::sqrt(direct2.y()*direct2.y() + direct2.z()*direct2.z());
+  // double R2_y = -charge * direct2.z() / std::sqrt(direct2.y()*direct2.y() + direct2.z()*direct2.z());
+  // the norm of radius
+  double R = (pos2_0.z() - pos1_2.z()) / (R2_z - R1_z);
+  // the norm of momentum in Y-Z plane
+  double p_yz = 0.3*B*R / 1000.0;  // R(mm), p(GeV), B(T)
+  double p_z = p_yz * direct1.z() / std::sqrt(direct1.y()*direct1.y() + direct1.z()*direct1.z());
+  double p_y = p_yz * direct1.y() / std::sqrt(direct1.y()*direct1.y() + direct1.z()*direct1.z());
+  double p_x = direct1.x() * p_z / direct1.z();
+  // total momentum at the layer 0
+  const Acts::Vector3D mom(p_x, p_y, p_z);
+  double p = mom.norm();
+  std::cout<<"!!!!!!!!!!!  InitTrack momentum on layer 0: ( "<<mom.x()*1000<<",  "<<mom.y()*1000<<",  "<<mom.z()*1000<<",  "<<p*1000<<")  "<<std::endl;
+  // build the track covariance matrix using the smearing sigmas
+  double sigmaU = 200_um;
+  double sigmaV = 200_um;
+  double sigmaPhi = 1_degree;
+  double sigmaTheta = 1_degree;
+  double sigmaQOverP = 0.01*p / (p*p);
+  double sigmaT0 = 1_ns;
+  Acts::BoundSymMatrix cov = Acts::BoundSymMatrix::Zero();
+  cov(Acts::eLOC_0, Acts::eLOC_0) = sigmaU * sigmaU;
+  cov(Acts::eLOC_1, Acts::eLOC_1) = sigmaV * sigmaV;
+  cov(Acts::ePHI, Acts::ePHI) = sigmaPhi * sigmaPhi;
+  cov(Acts::eTHETA, Acts::eTHETA) = sigmaTheta * sigmaTheta;
+  cov(Acts::eQOP, Acts::eQOP) = sigmaQOverP * sigmaQOverP;
+  cov(Acts::eT, Acts::eT) = sigmaT0 * sigmaT0;
+  double time =0;
+  //Acts::CurvilinearParameters InitTrackParam(std::make_optional(std::move(cov)), pos, mom, charge, time); // calculated initial parameters
+	 
+  // Smearing truth parameters as initial parameters
+  Acts::Vector3D pPos(pv.x(), pv.y(), pv.z());	 
+  Acts::Vector3D pMom(truthmom.x()/1000., truthmom.y()/1000., truthmom.z()/1000.);
+  std::random_device rd;
+  std::default_random_engine rng {rd()};
+  std::normal_distribution<> norm; // mu: 0 sigma: 1
+  Acts::Vector3D deltaPos(sigmaU*norm(rng), sigmaU*norm(rng), sigmaU*norm(rng));
+  auto theta = Acts::VectorHelpers::theta(pMom.normalized());
+  auto phi = Acts::VectorHelpers::phi(pMom.normalized());
+  auto angles = Acts::detail::ensureThetaBounds(phi + sigmaPhi*norm(rng), theta + sigmaTheta*norm(rng));
+  Acts::Vector3D dir(std::sin(angles.second) * std::cos(angles.first),
+                     std::sin(angles.second) * std::sin(angles.first),
+                     std::cos(angles.second));
+  const Acts::Vector3D deltaMom = ( pMom.norm()*(1 + 0.01*norm(rng)) ) * dir - pMom;
+  std::cout << "deltaPos: " << deltaPos << std::endl;
+  std::cout << "deltaMom: " << deltaMom << std::endl;
+  Acts::CurvilinearParameters InitTrackParam(std::make_optional(std::move(cov)), pPos+deltaPos, pMom+deltaMom, charge, time); 
+      
+  // the surface which the production point is bound to 
+  Acts::Vector3D center(0, 0, pPos.z());
+  Acts::Vector3D normal(0, 0, 1);
+  std::shared_ptr<const Acts::Surface> initSurface = Acts::Surface::makeShared<Acts::PlaneSurface>(center, normal);
+  // extrapolate the particle from production point to the first layer
+  Acts::BoundParameters startParameters(geoctx, std::nullopt, pPos, pMom, charge, time, initSurface);
+  auto truthParam = m_extrapolationTool->propagate(Gaudi::Hive::currentContext(), startParameters, *pSurface);
+  std::cout << "truth pos on 1st layer: " << truthParam->position() << std::endl;
+  std::cout << "truth mom on 1st layer: " << truthParam->momentum() << std::endl;
+  std::cout << "truth parameters on 1st layer: " << truthParam->parameters() << std::endl;
+
+
+  // Call the Acts Kalman Filter
+  // Prepare the output data with MultiTrajectory
+  TrajectoryContainer trajectories;
+  trajectories.reserve(1);
+
+  // Construct a perigee surface as the target surface
+  //auto pSurface = Acts::Surface::makeShared<Acts::PerigeeSurface>(
+  //                Acts::Vector3D{0., 0., 0.});
+
+  // Set the KalmanFitter options
+  std::unique_ptr<const Acts::Logger> logger = Acts::getDefaultLogger("KalmanFitter", Acts::Logging::VERBOSE);
+  Acts::KalmanFitterOptions<Acts::VoidOutlierFinder> kfOptions(
+           geoctx,
+           magctx,
+           calctx,
+           Acts::VoidOutlierFinder(),
+	   Acts::LoggerWrapper{*logger},
+           &(*pSurface),
+	   true, // scattering
+	   true, // energy loss
+	   false  // backward filtering
+	   );
+
+  ATH_MSG_DEBUG("Invoke fitter");
+  
+  Acts::Navigator     navigator(trackingGeometry);
+  navigator.resolvePassive   = false;
+  navigator.resolveMaterial  = true;
+  navigator.resolveSensitive = true;
+
+  ActsExtrapolationDetail::VariantPropagator* varProp {nullptr};
+
+  if (m_fieldMode == "FASER") {
+    ATH_MSG_INFO("Using FASER magnetic field service");
+    using BField_t = FASERMagneticFieldWrapper;
+    BField_t bField;
+    auto stepper = Acts::EigenStepper<BField_t>(std::move(bField));
+    auto propagator = Acts::Propagator<decltype(stepper), Acts::Navigator>(std::move(stepper),
+                                                                      std::move(navigator));
+    varProp = new VariantPropagator(propagator);
+  }
+  else if (m_fieldMode == "Constant") {
+    std::vector<double> constantFieldVector = m_constantFieldVector;
+    double Bx = constantFieldVector.at(0);
+    double By = constantFieldVector.at(1);
+    double Bz = constantFieldVector.at(2);
+    ATH_MSG_INFO("Using constant magnetic field: (Bx, By, Bz) = (" << Bx << ", " << By << ", " << Bz << ")");
+    using BField_t = Acts::ConstantBField;
+    BField_t bField(Bx, By, Bz);
+    auto stepper = Acts::EigenStepper<BField_t>(std::move(bField));
+    auto propagator = Acts::Propagator<decltype(stepper), Acts::Navigator>(std::move(stepper),
+                                                                      std::move(navigator));
+    varProp = new VariantPropagator(propagator);
+  }
+
+     auto fit = makeFitterFunction(varProp);
+     auto result = fit(sourceLinks, InitTrackParam, kfOptions);
+
+     ATH_MSG_VERBOSE("Size of sourceLinks: " << sourceLinks.size());
+
+     int itrack = 0;
+     if (result.ok()) {
+       // Get the fit output object
+       const auto& fitOutput = result.value();
+       
+       // The track entry indices container. One element here.
+       std::vector<size_t> trackTips;
+       trackTips.reserve(1);
+       trackTips.emplace_back(fitOutput.trackTip);
+       // The fitted parameters container. One element (at most) here.
+       IndexedParams indexedParams;
+
+       if (fitOutput.fittedParameters) {
+         const auto& params = fitOutput.fittedParameters.value();
+         ATH_MSG_VERBOSE("Fitted paramemeters for track " << itrack);
+         ATH_MSG_VERBOSE("  parameters: " << params);
+	 ATH_MSG_VERBOSE("  position: " << params.position().transpose());
+	 ATH_MSG_VERBOSE("  momentum: " << params.momentum().transpose());
+	 // Push the fitted parameters to the container
+	 indexedParams.emplace(fitOutput.trackTip, std::move(params));
+        } else {
+          ATH_MSG_DEBUG("No fitted paramemeters for track " << itrack);
+        }
+        // Create a SimMultiTrajectory
+	trajectories.emplace_back(std::move(fitOutput.fittedStates),
+	                          std::move(trackTips), std::move(indexedParams));
+      } else {
+            ATH_MSG_WARNING("Fit failed for track " << itrack << " with error"
+               << result.error());
+            // Fit failed, but still create a empty truth fit track
+            trajectories.push_back(FaserActsRecMultiTrajectory());
+      }
+  
+
+  fillFitResult(geoctx, trajectories, *truthParam);
+
+  }
+  return StatusCode::SUCCESS;
+}
+
+StatusCode FaserActsKalmanFilterAlg::finalize() 
+{
+  return StatusCode::SUCCESS;
+}
+
+
+template <typename Fitter>
+struct FitterFunctionImpl
+  {
+    Fitter fitter;
+
+    FitterFunctionImpl(Fitter&& f) : fitter(std::move(f)) {}
+
+    FaserActsKalmanFilterAlg::FitterResult
+    operator()(
+      const std::vector<RecSourceLink>&    sourceLinks,
+      const Acts::CurvilinearParameters&   initialParameters,
+      const Acts::KalmanFitterOptions<Acts::VoidOutlierFinder>& options) const
+    {
+        return fitter.fit(sourceLinks, initialParameters, options);
+    };
+  };
+
+FaserActsKalmanFilterAlg::FitterFunction
+FaserActsKalmanFilterAlg::makeFitterFunction(
+     ActsExtrapolationDetail::VariantPropagator* varProp)
+{
+
+  return boost::apply_visitor([&](const auto& propagator) -> FitterFunction {
+    using Updater  = Acts::GainMatrixUpdater;
+    using Smoother = Acts::GainMatrixSmoother;
+    using Fitter        = Acts::KalmanFitter<typename std::decay_t<decltype(propagator)>, Updater, Smoother>;
+
+    Fitter     fitter(std::move(propagator));
+    // build the fitter functions. owns the fitter object.
+    return FitterFunctionImpl<Fitter>(std::move(fitter));
+    }, *varProp);
+
+}
+
+//Acts::MagneticFieldContext FaserActsKalmanFilterAlg::getMagneticFieldContext(const EventContext& ctx) const {
+  //SG::ReadCondHandle<FaserFieldCacheCondObj> readHandle{m_fieldCondObjInputKey, ctx};
+Acts::MagneticFieldContext FaserActsKalmanFilterAlg::getMagneticFieldContext() const {
+  SG::ReadCondHandle<FaserFieldCacheCondObj> readHandle{m_fieldCondObjInputKey};
+  if (!readHandle.isValid()) {
+     std::stringstream msg;
+     msg << "Failed to retrieve magnetic field condition data " << m_fieldCondObjInputKey.key() << ".";
+     throw std::runtime_error(msg.str());
+  }
+  const FaserFieldCacheCondObj* fieldCondObj{*readHandle};
+
+  return Acts::MagneticFieldContext(fieldCondObj);
+}
+
+void FaserActsKalmanFilterAlg::initializeTree()
+{
+  m_trackTree->Branch("event_nr", &m_eventNr);
+  m_trackTree->Branch("traj_nr", &m_trajNr);
+  m_trackTree->Branch("track_nr", &m_trackNr);
+  m_trackTree->Branch("t_barcode", &m_t_barcode, "t_barcode/l");
+  m_trackTree->Branch("t_charge", &m_t_charge);
+  m_trackTree->Branch("t_eT", &m_t_eT);
+  m_trackTree->Branch("t_eLOC0", &m_t_eLOC0);
+  m_trackTree->Branch("t_eLOC1", &m_t_eLOC1);
+  m_trackTree->Branch("t_x", &m_t_x);
+  m_trackTree->Branch("t_y", &m_t_y);
+  m_trackTree->Branch("t_z", &m_t_z);
+  m_trackTree->Branch("t_px", &m_t_px);
+  m_trackTree->Branch("t_py", &m_t_py);
+  m_trackTree->Branch("t_pz", &m_t_pz);
+  m_trackTree->Branch("t_eTHETA", &m_t_eTHETA);
+  m_trackTree->Branch("t_ePHI", &m_t_ePHI);
+  m_trackTree->Branch("t_eQOP", &m_t_eQOP);
+
+  m_trackTree->Branch("hasFittedParams", &m_hasFittedParams);
+  m_trackTree->Branch("chi2_fit", &m_chi2_fit);
+  m_trackTree->Branch("ndf_fit", &m_ndf_fit);
+  m_trackTree->Branch("eLOC0_fit", &m_eLOC0_fit);
+  m_trackTree->Branch("eLOC1_fit", &m_eLOC1_fit);
+  m_trackTree->Branch("ePHI_fit", &m_ePHI_fit);
+  m_trackTree->Branch("eTHETA_fit", &m_eTHETA_fit);
+  m_trackTree->Branch("eQOP_fit", &m_eQOP_fit);
+  m_trackTree->Branch("eT_fit", &m_eT_fit);
+  m_trackTree->Branch("charge_fit", &m_charge_fit);
+  m_trackTree->Branch("err_eLOC0_fit", &m_err_eLOC0_fit);
+  m_trackTree->Branch("err_eLOC1_fit", &m_err_eLOC1_fit);
+  m_trackTree->Branch("err_ePHI_fit", &m_err_ePHI_fit);
+  m_trackTree->Branch("err_eTHETA_fit", &m_err_eTHETA_fit);
+  m_trackTree->Branch("err_eQOP_fit", &m_err_eQOP_fit);
+  m_trackTree->Branch("err_eT_fit", &m_err_eT_fit);
+  m_trackTree->Branch("g_px_fit", &m_px_fit);
+  m_trackTree->Branch("g_py_fit", &m_py_fit);
+  m_trackTree->Branch("g_pz_fit", &m_pz_fit);
+  m_trackTree->Branch("g_x_fit" , &m_x_fit);
+  m_trackTree->Branch("g_y_fit" , &m_y_fit);
+  m_trackTree->Branch("g_z_fit" , &m_z_fit);
+
+  m_trackTree->Branch("nHoles", &m_nHoles);
+  m_trackTree->Branch("nOutliers", &m_nOutliers);
+  m_trackTree->Branch("nStates", &m_nStates);
+  m_trackTree->Branch("nMeasurements", &m_nMeasurements);
+  m_trackTree->Branch("volume_id", &m_volumeID);
+  m_trackTree->Branch("layer_id", &m_layerID);
+  m_trackTree->Branch("module_id", &m_moduleID);
+  m_trackTree->Branch("l_x_hit", &m_lx_hit);
+  m_trackTree->Branch("l_y_hit", &m_ly_hit);
+  m_trackTree->Branch("g_x_hit", &m_x_hit);
+  m_trackTree->Branch("g_y_hit", &m_y_hit);
+  m_trackTree->Branch("g_z_hit", &m_z_hit);
+  m_trackTree->Branch("res_x_hit", &m_res_x_hit);
+  m_trackTree->Branch("res_y_hit", &m_res_y_hit);
+  m_trackTree->Branch("err_x_hit", &m_err_x_hit);
+  m_trackTree->Branch("err_y_hit", &m_err_y_hit);
+  m_trackTree->Branch("pull_x_hit", &m_pull_x_hit);
+  m_trackTree->Branch("pull_y_hit", &m_pull_y_hit);
+  m_trackTree->Branch("dim_hit", &m_dim_hit);
+
+  m_trackTree->Branch("nPredicted", &m_nPredicted);
+  m_trackTree->Branch("predicted", &m_prt);
+  m_trackTree->Branch("eLOC0_prt", &m_eLOC0_prt);
+  m_trackTree->Branch("eLOC1_prt", &m_eLOC1_prt);
+  m_trackTree->Branch("ePHI_prt", &m_ePHI_prt);
+  m_trackTree->Branch("eTHETA_prt", &m_eTHETA_prt);
+  m_trackTree->Branch("eQOP_prt", &m_eQOP_prt);
+  m_trackTree->Branch("eT_prt", &m_eT_prt);
+  m_trackTree->Branch("res_eLOC0_prt", &m_res_eLOC0_prt);
+  m_trackTree->Branch("res_eLOC1_prt", &m_res_eLOC1_prt);
+  m_trackTree->Branch("err_eLOC0_prt", &m_err_eLOC0_prt);
+  m_trackTree->Branch("err_eLOC1_prt", &m_err_eLOC1_prt);
+  m_trackTree->Branch("err_ePHI_prt", &m_err_ePHI_prt);
+  m_trackTree->Branch("err_eTHETA_prt", &m_err_eTHETA_prt);
+  m_trackTree->Branch("err_eQOP_prt", &m_err_eQOP_prt);
+  m_trackTree->Branch("err_eT_prt", &m_err_eT_prt);
+  m_trackTree->Branch("pull_eLOC0_prt", &m_pull_eLOC0_prt);
+  m_trackTree->Branch("pull_eLOC1_prt", &m_pull_eLOC1_prt);
+  m_trackTree->Branch("g_x_prt", &m_x_prt);
+  m_trackTree->Branch("g_y_prt", &m_y_prt);
+  m_trackTree->Branch("g_z_prt", &m_z_prt);
+  m_trackTree->Branch("px_prt", &m_px_prt);
+  m_trackTree->Branch("py_prt", &m_py_prt);
+  m_trackTree->Branch("pz_prt", &m_pz_prt);
+  m_trackTree->Branch("eta_prt", &m_eta_prt);
+  m_trackTree->Branch("pT_prt", &m_pT_prt);
+
+  m_trackTree->Branch("nFiltered", &m_nFiltered);
+  m_trackTree->Branch("filtered", &m_flt);
+  m_trackTree->Branch("eLOC0_flt", &m_eLOC0_flt);
+  m_trackTree->Branch("eLOC1_flt", &m_eLOC1_flt);
+  m_trackTree->Branch("ePHI_flt", &m_ePHI_flt);
+  m_trackTree->Branch("eTHETA_flt", &m_eTHETA_flt);
+  m_trackTree->Branch("eQOP_flt", &m_eQOP_flt);
+  m_trackTree->Branch("eT_flt", &m_eT_flt);
+  m_trackTree->Branch("res_eLOC0_flt", &m_res_eLOC0_flt);
+  m_trackTree->Branch("res_eLOC1_flt", &m_res_eLOC1_flt);
+  m_trackTree->Branch("err_eLOC0_flt", &m_err_eLOC0_flt);
+  m_trackTree->Branch("err_eLOC1_flt", &m_err_eLOC1_flt);
+  m_trackTree->Branch("err_ePHI_flt", &m_err_ePHI_flt);
+  m_trackTree->Branch("err_eTHETA_flt", &m_err_eTHETA_flt);
+  m_trackTree->Branch("err_eQOP_flt", &m_err_eQOP_flt);
+  m_trackTree->Branch("err_eT_flt", &m_err_eT_flt);
+  m_trackTree->Branch("pull_eLOC0_flt", &m_pull_eLOC0_flt);
+  m_trackTree->Branch("pull_eLOC1_flt", &m_pull_eLOC1_flt);
+  m_trackTree->Branch("g_x_flt", &m_x_flt);
+  m_trackTree->Branch("g_y_flt", &m_y_flt);
+  m_trackTree->Branch("g_z_flt", &m_z_flt);
+  m_trackTree->Branch("px_flt", &m_px_flt);
+  m_trackTree->Branch("py_flt", &m_py_flt);
+  m_trackTree->Branch("pz_flt", &m_pz_flt);
+  m_trackTree->Branch("eta_flt", &m_eta_flt);
+  m_trackTree->Branch("pT_flt", &m_pT_flt);
+  m_trackTree->Branch("chi2", &m_chi2);
+
+  m_trackTree->Branch("nSmoothed", &m_nSmoothed);
+  m_trackTree->Branch("smoothed", &m_smt);
+  m_trackTree->Branch("eLOC0_smt", &m_eLOC0_smt);
+  m_trackTree->Branch("eLOC1_smt", &m_eLOC1_smt);
+  m_trackTree->Branch("ePHI_smt", &m_ePHI_smt);
+  m_trackTree->Branch("eTHETA_smt", &m_eTHETA_smt);
+  m_trackTree->Branch("eQOP_smt", &m_eQOP_smt);
+  m_trackTree->Branch("eT_smt", &m_eT_smt);
+  m_trackTree->Branch("res_eLOC0_smt", &m_res_eLOC0_smt);
+  m_trackTree->Branch("res_eLOC1_smt", &m_res_eLOC1_smt);
+  m_trackTree->Branch("err_eLOC0_smt", &m_err_eLOC0_smt);
+  m_trackTree->Branch("err_eLOC1_smt", &m_err_eLOC1_smt);
+  m_trackTree->Branch("err_ePHI_smt", &m_err_ePHI_smt);
+  m_trackTree->Branch("err_eTHETA_smt", &m_err_eTHETA_smt);
+  m_trackTree->Branch("err_eQOP_smt", &m_err_eQOP_smt);
+  m_trackTree->Branch("err_eT_smt", &m_err_eT_smt);
+  m_trackTree->Branch("pull_eLOC0_smt", &m_pull_eLOC0_smt);
+  m_trackTree->Branch("pull_eLOC1_smt", &m_pull_eLOC1_smt);
+  m_trackTree->Branch("g_x_smt", &m_x_smt);
+  m_trackTree->Branch("g_y_smt", &m_y_smt);
+  m_trackTree->Branch("g_z_smt", &m_z_smt);
+  m_trackTree->Branch("px_smt", &m_px_smt);
+  m_trackTree->Branch("py_smt", &m_py_smt);
+  m_trackTree->Branch("pz_smt", &m_pz_smt);
+  m_trackTree->Branch("eta_smt", &m_eta_smt);
+  m_trackTree->Branch("pT_smt", &m_pT_smt);
+}
+
+void FaserActsKalmanFilterAlg::fillFitResult(
+		const Acts::GeometryContext& geoctx,
+		const TrajectoryContainer& trajectories, 
+		const Acts::BoundParameters& truthParam
+		)
+{
+  m_t_eLOC0 = truthParam.parameters()[Acts::ParDef::eLOC_0];
+  m_t_eLOC1 = truthParam.parameters()[Acts::ParDef::eLOC_1];
+  m_t_ePHI = truthParam.parameters()[Acts::ParDef::ePHI];
+  m_t_eTHETA = truthParam.parameters()[Acts::ParDef::eTHETA];
+  m_t_eQOP = truthParam.parameters()[Acts::ParDef::eQOP];
+  m_t_eT = truthParam.parameters()[Acts::ParDef::eT];
+  m_t_x = truthParam.position()(0);
+  m_t_y = truthParam.position()(1);
+  m_t_z = truthParam.position()(2);
+  m_t_px = truthParam.momentum()(0);
+  m_t_py = truthParam.momentum()(1);
+  m_t_pz = truthParam.momentum()(2);
+  std::cout<<"truth global position on the first layer = "<<m_t_x<<"  "<<m_t_y<<"  "<<m_t_z<<"  "<<std::endl;
+  std::cout<<"truth momentum on the first layer = "<<m_t_px<<"  "<<m_t_py<<"  "<<m_t_pz<<"  "<<std::endl;
+  std::cout<<"truth local parameters on the first layer = "<<m_t_eLOC0<<"  "<<m_t_eLOC1<<"  "<<m_t_ePHI<<"  "<<m_t_eTHETA<<"  "<<m_t_eQOP<<"  "<<std::endl;
+
+  // Loop over the trajectories
+  int iTraj = 0;
+  for (const auto& traj : trajectories) {
+    m_trajNr = iTraj;
+
+    // The trajectory entry indices and the multiTrajectory
+    const auto& [trackTips, mj] = traj.trajectory();
+    if (trackTips.empty()) {
+      ATH_MSG_WARNING("Empty multiTrajectory.");
+      continue;
+    }
+
+    // Get the entry index for the single trajectory
+    auto& trackTip = trackTips.front();
+    std::cout<<"trackTip = "<<trackTip<<std::endl;
+
+    // Collect the trajectory summary info
+    auto trajState =
+        Acts::MultiTrajectoryHelpers::trajectoryState(mj, trackTip);
+
+    m_nMeasurements = trajState.nMeasurements;
+    m_nStates = trajState.nStates;
+    m_nOutliers = trajState.nOutliers;
+    m_nHoles = trajState.nHoles;
+    m_chi2_fit = trajState.chi2Sum;
+    m_ndf_fit = trajState.NDF;
+    std::cout << "Track has " << trajState.nMeasurements
+	      << " measurements and " << trajState.nHoles
+	      << " holes and " << trajState.nOutliers 
+	      << " outliers and " << trajState.nStates
+	      << " states " << std::endl;
+  
+  /// If it has track parameters, fill the values
+  if (traj.hasTrackParameters(trackTip))
+  {
+    m_hasFittedParams = true;
+    const auto &boundParam = traj.trackParameters(trackTip);
+    const auto &parameter = boundParam.parameters();
+    const auto &covariance = *boundParam.covariance();
+    m_charge_fit = boundParam.charge();
+    m_eLOC0_fit = parameter[Acts::ParDef::eLOC_0];
+    m_eLOC1_fit = parameter[Acts::ParDef::eLOC_1];
+    m_ePHI_fit = parameter[Acts::ParDef::ePHI];
+    m_eTHETA_fit = parameter[Acts::ParDef::eTHETA];
+    m_eQOP_fit = parameter[Acts::ParDef::eQOP];
+    m_eT_fit = parameter[Acts::ParDef::eT];
+    m_err_eLOC0_fit =
+        sqrt(covariance(Acts::ParDef::eLOC_0, Acts::ParDef::eLOC_0));
+    m_err_eLOC1_fit =
+        sqrt(covariance(Acts::ParDef::eLOC_1, Acts::ParDef::eLOC_1));
+    m_err_ePHI_fit = sqrt(covariance(Acts::ParDef::ePHI, Acts::ParDef::ePHI));
+    m_err_eTHETA_fit =
+        sqrt(covariance(Acts::ParDef::eTHETA, Acts::ParDef::eTHETA));
+    m_err_eQOP_fit = sqrt(covariance(Acts::ParDef::eQOP, Acts::ParDef::eQOP));
+    m_err_eT_fit = sqrt(covariance(Acts::ParDef::eT, Acts::ParDef::eT));
+
+    m_px_fit = boundParam.momentum()(0);
+    m_py_fit = boundParam.momentum()(1);
+    m_pz_fit = boundParam.momentum()(2);
+    m_x_fit  = boundParam.position()(0);
+    m_y_fit  = boundParam.position()(1);
+    m_z_fit  = boundParam.position()(2);
+  }
+   
+  m_nPredicted = 0; 
+  m_nFiltered = 0; 
+  m_nSmoothed = 0; 
+
+  mj.visitBackwards(trackTip, [&](const auto &state) {
+    /// Only fill the track states with non-outlier measurement
+    auto typeFlags = state.typeFlags();
+    if (not typeFlags.test(Acts::TrackStateFlag::MeasurementFlag))
+    {
+      return true;
+    }
+
+    /// Get the geometry ID
+    auto geoID = state.referenceSurface().geoID();
+    m_volumeID.push_back(geoID.volume());
+    m_layerID.push_back(geoID.layer());
+    m_moduleID.push_back(geoID.sensitive());
+
+    auto meas = std::get<Measurement>(*state.uncalibrated());
+
+    /// Get local position
+    Acts::Vector2D local(meas.parameters()[Acts::ParDef::eLOC_0],
+                         meas.parameters()[Acts::ParDef::eLOC_1]);
+    /// Get global position
+    Acts::Vector3D global(0, 0, 0);
+    /// This is an arbitrary vector. Doesn't matter in coordinate transformation
+    /// in Acts code
+    Acts::Vector3D mom(1, 1, 1);
+    meas.referenceObject().localToGlobal(geoctx,
+                                          local, mom, global);
+
+    /// Get measurement covariance
+    auto cov = meas.covariance();
+
+    m_lx_hit.push_back(local.x());
+    m_ly_hit.push_back(local.y());
+    m_x_hit.push_back(global.x());
+    m_y_hit.push_back(global.y());
+    m_z_hit.push_back(global.z());
+
+    /// Get the predicted parameter for this state
+    bool predicted = false;
+    if (state.hasPredicted())
+    {
+      predicted = true;
+      m_nPredicted++;
+      Acts::BoundParameters parameter(
+          geoctx,
+          state.predictedCovariance(),
+          state.predicted(),
+          state.referenceSurface().getSharedPtr());
+      auto covariance = state.predictedCovariance();
+
+      /// Local hit residual info
+      auto H = meas.projector();
+      auto resCov = cov + H * covariance * H.transpose();
+      auto residual = meas.residual(parameter);
+
+      /// Predicted residual
+      m_res_eLOC0_prt.push_back(residual(Acts::ParDef::eLOC_0));
+      m_res_eLOC1_prt.push_back(residual(Acts::ParDef::eLOC_1));
+
+      /// Predicted parameter pulls
+      m_pull_eLOC0_prt.push_back(
+          residual(Acts::ParDef::eLOC_0) /
+          sqrt(resCov(Acts::ParDef::eLOC_0, Acts::ParDef::eLOC_0)));
+      m_pull_eLOC1_prt.push_back(
+          residual(Acts::ParDef::eLOC_1) /
+          sqrt(resCov(Acts::ParDef::eLOC_1, Acts::ParDef::eLOC_1)));
+
+
+      /// Predicted parameter
+      m_eLOC0_prt.push_back(parameter.parameters()[Acts::ParDef::eLOC_0]);
+      m_eLOC1_prt.push_back(parameter.parameters()[Acts::ParDef::eLOC_1]);
+      m_ePHI_prt.push_back(parameter.parameters()[Acts::ParDef::ePHI]);
+      m_eTHETA_prt.push_back(parameter.parameters()[Acts::ParDef::eTHETA]);
+      m_eQOP_prt.push_back(parameter.parameters()[Acts::ParDef::eQOP]);
+      m_eT_prt.push_back(parameter.parameters()[Acts::ParDef::eT]);
+
+      /// Predicted parameter Uncertainties
+      m_err_eLOC0_prt.push_back(
+          sqrt(covariance(Acts::ParDef::eLOC_0, Acts::ParDef::eLOC_0)));
+      m_err_eLOC1_prt.push_back(
+          sqrt(covariance(Acts::ParDef::eLOC_1, Acts::ParDef::eLOC_1)));
+      m_err_ePHI_prt.push_back(
+          sqrt(covariance(Acts::ParDef::ePHI, Acts::ParDef::ePHI)));
+      m_err_eTHETA_prt.push_back(
+          sqrt(covariance(Acts::ParDef::eTHETA, Acts::ParDef::eTHETA)));
+      m_err_eQOP_prt.push_back(
+          sqrt(covariance(Acts::ParDef::eQOP, Acts::ParDef::eQOP)));
+      m_err_eT_prt.push_back(
+          sqrt(covariance(Acts::ParDef::eT, Acts::ParDef::eT)));
+
+      m_x_prt.push_back(parameter.position().x());
+      m_y_prt.push_back(parameter.position().y());
+      m_z_prt.push_back(parameter.position().z());
+      m_px_prt.push_back(parameter.momentum().x());
+      m_py_prt.push_back(parameter.momentum().y());
+      m_pz_prt.push_back(parameter.momentum().z());
+      m_pT_prt.push_back(parameter.pT());
+      m_eta_prt.push_back(eta(parameter.position()));
+    }
+    else
+    {
+      /// Push bad values if no predicted parameter
+      m_eLOC0_prt.push_back(-9999);
+      m_eLOC1_prt.push_back(-9999);
+      m_ePHI_prt.push_back(-9999);
+      m_eTHETA_prt.push_back(-9999);
+      m_eQOP_prt.push_back(-9999);
+      m_eT_prt.push_back(-9999);
+      m_res_eLOC0_prt.push_back(-9999);
+      m_res_eLOC1_prt.push_back(-9999);
+      m_err_eLOC0_prt.push_back(-9999);
+      m_err_eLOC1_prt.push_back(-9999);
+      m_err_ePHI_prt.push_back(-9999);
+      m_err_eTHETA_prt.push_back(-9999);
+      m_err_eQOP_prt.push_back(-9999);
+      m_err_eT_prt.push_back(-9999);
+      m_pull_eLOC0_prt.push_back(-9999);
+      m_pull_eLOC1_prt.push_back(-9999);
+      m_x_prt.push_back(-9999);
+      m_y_prt.push_back(-9999);
+      m_z_prt.push_back(-9999);
+      m_px_prt.push_back(-9999);
+      m_py_prt.push_back(-9999);
+      m_pz_prt.push_back(-9999);
+      m_pT_prt.push_back(-9999);
+      m_eta_prt.push_back(-9999);
+    }
+
+    bool filtered = false;
+    if (state.hasFiltered())
+    {
+      filtered = true;
+      m_nFiltered++;
+      Acts::BoundParameters parameter(
+          geoctx,
+          state.filteredCovariance(), state.filtered(),
+          state.referenceSurface().getSharedPtr());
+      auto covariance = state.filteredCovariance();
+
+      /// Local hit residual info
+      auto H = meas.projector();
+      auto resCov = cov + H * covariance * H.transpose();
+      auto residual = meas.residual(parameter);
+
+      /// Filtered residual
+      m_res_eLOC0_flt.push_back(residual(Acts::ParDef::eLOC_0));
+      m_res_eLOC1_flt.push_back(residual(Acts::ParDef::eLOC_1));
+
+      /// Filtered parameter pulls
+      m_pull_eLOC0_flt.push_back(
+          residual(Acts::ParDef::eLOC_0) /
+          sqrt(resCov(Acts::ParDef::eLOC_0, Acts::ParDef::eLOC_0)));
+      m_pull_eLOC1_flt.push_back(
+          residual(Acts::ParDef::eLOC_1) /
+          sqrt(resCov(Acts::ParDef::eLOC_1, Acts::ParDef::eLOC_1)));
+
+      /// Filtered parameter
+      m_eLOC0_flt.push_back(parameter.parameters()[Acts::ParDef::eLOC_0]);
+      m_eLOC1_flt.push_back(parameter.parameters()[Acts::ParDef::eLOC_1]);
+      m_ePHI_flt.push_back(parameter.parameters()[Acts::ParDef::ePHI]);
+      m_eTHETA_flt.push_back(parameter.parameters()[Acts::ParDef::eTHETA]);
+      m_eQOP_flt.push_back(parameter.parameters()[Acts::ParDef::eQOP]);
+      m_eT_flt.push_back(parameter.parameters()[Acts::ParDef::eT]);
+
+      /// Filtered parameter uncertainties
+      m_err_eLOC0_flt.push_back(
+          sqrt(covariance(Acts::ParDef::eLOC_0, Acts::ParDef::eLOC_0)));
+      m_err_eLOC1_flt.push_back(
+          sqrt(covariance(Acts::ParDef::eLOC_1, Acts::ParDef::eLOC_1)));
+      m_err_ePHI_flt.push_back(
+          sqrt(covariance(Acts::ParDef::ePHI, Acts::ParDef::ePHI)));
+      m_err_eTHETA_flt.push_back(
+          sqrt(covariance(Acts::ParDef::eTHETA, Acts::ParDef::eTHETA)));
+      m_err_eQOP_flt.push_back(
+          sqrt(covariance(Acts::ParDef::eQOP, Acts::ParDef::eQOP)));
+      m_err_eT_flt.push_back(
+          sqrt(covariance(Acts::ParDef::eT, Acts::ParDef::eT)));
+
+      /// Other filtered parameter info
+      m_x_flt.push_back(parameter.position().x());
+      m_y_flt.push_back(parameter.position().y());
+      m_z_flt.push_back(parameter.position().z());
+      m_px_flt.push_back(parameter.momentum().x());
+      m_py_flt.push_back(parameter.momentum().y());
+      m_pz_flt.push_back(parameter.momentum().z());
+      m_pT_flt.push_back(parameter.pT());
+      m_eta_flt.push_back(eta(parameter.position()));
+      m_chi2.push_back(state.chi2());
+      
+    }
+    else
+    {
+      /// Push bad values if no filtered parameter
+      m_eLOC0_flt.push_back(-9999);
+      m_eLOC1_flt.push_back(-9999);
+      m_ePHI_flt.push_back(-9999);
+      m_eTHETA_flt.push_back(-9999);
+      m_eQOP_flt.push_back(-9999);
+      m_eT_flt.push_back(-9999);
+      m_res_eLOC0_flt.push_back(-9999);
+      m_res_eLOC1_flt.push_back(-9999);
+      m_err_eLOC0_flt.push_back(-9999);
+      m_err_eLOC1_flt.push_back(-9999);
+      m_err_ePHI_flt.push_back(-9999);
+      m_err_eTHETA_flt.push_back(-9999);
+      m_err_eQOP_flt.push_back(-9999);
+      m_err_eT_flt.push_back(-9999);
+      m_pull_eLOC0_flt.push_back(-9999);
+      m_pull_eLOC1_flt.push_back(-9999);
+      m_x_flt.push_back(-9999);
+      m_y_flt.push_back(-9999);
+      m_z_flt.push_back(-9999);
+      m_py_flt.push_back(-9999);
+      m_pz_flt.push_back(-9999);
+      m_pT_flt.push_back(-9999);
+      m_eta_flt.push_back(-9999);
+      m_chi2.push_back(-9999);
+    }
+  
+    bool smoothed = false;
+    if (state.hasSmoothed())
+    {
+      smoothed = true;
+      m_nSmoothed++;
+      Acts::BoundParameters parameter(
+          geoctx,
+          state.smoothedCovariance(), state.smoothed(),
+          state.referenceSurface().getSharedPtr());
+      auto covariance = state.smoothedCovariance();
+
+      /// Local hit residual info
+      auto H = meas.projector();
+      auto resCov = cov + H * covariance * H.transpose();
+      auto residual = meas.residual(parameter);
+
+      m_res_x_hit.push_back(residual(Acts::ParDef::eLOC_0));
+      m_res_y_hit.push_back(residual(Acts::ParDef::eLOC_1));
+      m_err_x_hit.push_back(
+          sqrt(resCov(Acts::ParDef::eLOC_0, Acts::ParDef::eLOC_0)));
+      m_err_y_hit.push_back(
+          sqrt(resCov(Acts::ParDef::eLOC_1, Acts::ParDef::eLOC_1)));
+      m_pull_x_hit.push_back(
+          residual(Acts::ParDef::eLOC_0) /
+          sqrt(resCov(Acts::ParDef::eLOC_0, Acts::ParDef::eLOC_0)));
+      m_pull_y_hit.push_back(
+          residual(Acts::ParDef::eLOC_1) /
+          sqrt(resCov(Acts::ParDef::eLOC_1, Acts::ParDef::eLOC_1)));
+      m_dim_hit.push_back(state.calibratedSize());
+
+      /// Smoothed residual
+      m_res_eLOC0_smt.push_back(residual(Acts::ParDef::eLOC_0));
+      m_res_eLOC1_smt.push_back(residual(Acts::ParDef::eLOC_1));
+
+      /// Smoothed parameter pulls
+      m_pull_eLOC0_smt.push_back(
+          residual(Acts::ParDef::eLOC_0) /
+          sqrt(resCov(Acts::ParDef::eLOC_0, Acts::ParDef::eLOC_0)));
+      m_pull_eLOC1_smt.push_back(
+          residual(Acts::ParDef::eLOC_1) /
+          sqrt(resCov(Acts::ParDef::eLOC_1, Acts::ParDef::eLOC_1)));
+
+      /// Smoothed parameter
+      m_eLOC0_smt.push_back(parameter.parameters()[Acts::ParDef::eLOC_0]);
+      m_eLOC1_smt.push_back(parameter.parameters()[Acts::ParDef::eLOC_1]);
+      m_ePHI_smt.push_back(parameter.parameters()[Acts::ParDef::ePHI]);
+      m_eTHETA_smt.push_back(parameter.parameters()[Acts::ParDef::eTHETA]);
+      m_eQOP_smt.push_back(parameter.parameters()[Acts::ParDef::eQOP]);
+      m_eT_smt.push_back(parameter.parameters()[Acts::ParDef::eT]);
+
+      /// Smoothed parameter uncertainties
+      m_err_eLOC0_smt.push_back(
+          sqrt(covariance(Acts::ParDef::eLOC_0, Acts::ParDef::eLOC_0)));
+      m_err_eLOC1_smt.push_back(
+          sqrt(covariance(Acts::ParDef::eLOC_1, Acts::ParDef::eLOC_1)));
+      m_err_ePHI_smt.push_back(
+          sqrt(covariance(Acts::ParDef::ePHI, Acts::ParDef::ePHI)));
+      m_err_eTHETA_smt.push_back(
+          sqrt(covariance(Acts::ParDef::eTHETA, Acts::ParDef::eTHETA)));
+      m_err_eQOP_smt.push_back(
+          sqrt(covariance(Acts::ParDef::eQOP, Acts::ParDef::eQOP)));
+      m_err_eT_smt.push_back(
+          sqrt(covariance(Acts::ParDef::eT, Acts::ParDef::eT)));
+
+      m_x_smt.push_back(parameter.position().x());
+      m_y_smt.push_back(parameter.position().y());
+      m_z_smt.push_back(parameter.position().z());
+      m_px_smt.push_back(parameter.momentum().x());
+      m_py_smt.push_back(parameter.momentum().y());
+      m_pz_smt.push_back(parameter.momentum().z());
+      m_pT_smt.push_back(parameter.pT());
+      m_eta_smt.push_back(eta(parameter.position()));
+    }
+    else
+    {
+      /// Push bad values if no smoothed parameter
+      m_eLOC0_smt.push_back(-9999);
+      m_eLOC1_smt.push_back(-9999);
+      m_ePHI_smt.push_back(-9999);
+      m_eTHETA_smt.push_back(-9999);
+      m_eQOP_smt.push_back(-9999);
+      m_eT_smt.push_back(-9999);
+      m_res_eLOC0_smt.push_back(-9999);
+      m_res_eLOC1_smt.push_back(-9999);
+      m_err_eLOC0_smt.push_back(-9999);
+      m_err_eLOC1_smt.push_back(-9999);
+      m_err_ePHI_smt.push_back(-9999);
+      m_err_eTHETA_smt.push_back(-9999);
+      m_err_eQOP_smt.push_back(-9999);
+      m_err_eT_smt.push_back(-9999);
+      m_pull_eLOC0_smt.push_back(-9999);
+      m_pull_eLOC1_smt.push_back(-9999);
+      m_x_smt.push_back(-9999);
+      m_y_smt.push_back(-9999);
+      m_z_smt.push_back(-9999);
+      m_px_smt.push_back(-9999);
+      m_py_smt.push_back(-9999);
+      m_pz_smt.push_back(-9999);
+      m_pT_smt.push_back(-9999);
+      m_eta_smt.push_back(-9999);
+      m_res_x_hit.push_back(-9999);
+      m_res_y_hit.push_back(-9999);
+      m_err_x_hit.push_back(-9999);
+      m_err_y_hit.push_back(-9999);
+      m_pull_x_hit.push_back(-9999);
+      m_pull_y_hit.push_back(-9999);
+      m_dim_hit.push_back(-9999);
+    }
+
+    /// Save whether or not states had various KF steps
+    m_prt.push_back(predicted);
+    m_flt.push_back(filtered);
+    m_smt.push_back(smoothed);
+
+    return true;
+  }   /// Finish lambda function
+  );  /// Finish multi trajectory visitBackwards call
+
+    iTraj++;
+
+  }  // all trajectories
+
+  m_trackTree->Fill();
+
+  clearTrackVariables();
+}
+
+void FaserActsKalmanFilterAlg::clearTrackVariables()
+{
+  m_volumeID.clear();
+  m_layerID.clear();
+  m_moduleID.clear();
+  m_lx_hit.clear();
+  m_ly_hit.clear();
+  m_x_hit.clear();
+  m_y_hit.clear();
+  m_z_hit.clear();
+  m_res_x_hit.clear();
+  m_res_y_hit.clear();
+  m_err_x_hit.clear();
+  m_err_y_hit.clear();
+  m_pull_x_hit.clear();
+  m_pull_y_hit.clear();
+  m_dim_hit.clear();
+
+  m_prt.clear();
+  m_eLOC0_prt.clear();
+  m_eLOC1_prt.clear();
+  m_ePHI_prt.clear();
+  m_eTHETA_prt.clear();
+  m_eQOP_prt.clear();
+  m_eT_prt.clear();
+  m_res_eLOC0_prt.clear();
+  m_res_eLOC1_prt.clear();
+  m_err_eLOC0_prt.clear();
+  m_err_eLOC1_prt.clear();
+  m_err_ePHI_prt.clear();
+  m_err_eTHETA_prt.clear();
+  m_err_eQOP_prt.clear();
+  m_err_eT_prt.clear();
+  m_pull_eLOC0_prt.clear();
+  m_pull_eLOC1_prt.clear();
+  m_x_prt.clear();
+  m_y_prt.clear();
+  m_z_prt.clear();
+  m_px_prt.clear();
+  m_py_prt.clear();
+  m_pz_prt.clear();
+  m_eta_prt.clear();
+  m_pT_prt.clear();
+
+  m_flt.clear();
+  m_eLOC0_flt.clear();
+  m_eLOC1_flt.clear();
+  m_ePHI_flt.clear();
+  m_eTHETA_flt.clear();
+  m_eQOP_flt.clear();
+  m_eT_flt.clear();
+  m_res_eLOC0_flt.clear();
+  m_res_eLOC1_flt.clear();
+  m_err_eLOC0_flt.clear();
+  m_err_eLOC1_flt.clear();
+  m_err_ePHI_flt.clear();
+  m_err_eTHETA_flt.clear();
+  m_err_eQOP_flt.clear();
+  m_err_eT_flt.clear();
+  m_pull_eLOC0_flt.clear();
+  m_pull_eLOC1_flt.clear();
+  m_x_flt.clear();
+  m_y_flt.clear();
+  m_z_flt.clear();
+  m_px_flt.clear();
+  m_py_flt.clear();
+  m_pz_flt.clear();
+  m_eta_flt.clear();
+  m_pT_flt.clear();
+  m_chi2.clear();
+
+  m_smt.clear();
+  m_eLOC0_smt.clear();
+  m_eLOC1_smt.clear();
+  m_ePHI_smt.clear();
+  m_eTHETA_smt.clear();
+  m_eQOP_smt.clear();
+  m_eT_smt.clear();
+  m_res_eLOC0_smt.clear();
+  m_res_eLOC1_smt.clear();
+  m_err_eLOC0_smt.clear();
+  m_err_eLOC1_smt.clear();
+  m_err_ePHI_smt.clear();
+  m_err_eTHETA_smt.clear();
+  m_err_eQOP_smt.clear();
+  m_err_eT_smt.clear();
+  m_pull_eLOC0_smt.clear();
+  m_pull_eLOC1_smt.clear();
+  m_x_smt.clear();
+  m_y_smt.clear();
+  m_z_smt.clear();
+  m_px_smt.clear();
+  m_py_smt.clear();
+  m_pz_smt.clear();
+  m_eta_smt.clear();
+  m_pT_smt.clear();
+
+  return;
+}
diff --git a/Tracking/Acts/FaserActsKalmanFilter/src/components/FaserActsKalmanFilter_entries.cxx b/Tracking/Acts/FaserActsKalmanFilter/src/components/FaserActsKalmanFilter_entries.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..59a385596f4fad95415b5d6291ab3901482e7b1f
--- /dev/null
+++ b/Tracking/Acts/FaserActsKalmanFilter/src/components/FaserActsKalmanFilter_entries.cxx
@@ -0,0 +1,8 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "FaserActsKalmanFilter/FaserActsKalmanFilterAlg.h"
+
+
+DECLARE_COMPONENT( FaserActsKalmanFilterAlg )
diff --git a/Tracking/Acts/FaserActsKalmanFilter/src/components/KalmanFilter_entries.cxx b/Tracking/Acts/FaserActsKalmanFilter/src/components/KalmanFilter_entries.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..4634ae05271a0d4b4dbbb6c24d39d313b60a8ba6
--- /dev/null
+++ b/Tracking/Acts/FaserActsKalmanFilter/src/components/KalmanFilter_entries.cxx
@@ -0,0 +1,3 @@
+#include "FaserActsKalmanFilter/FaserActsKalmanFilterAlg.h"
+
+DECLARE_COMPONENT( FaserActsKalmanFilterAlg )
\ No newline at end of file
diff --git a/Tracking/Acts/FaserActsKalmanFilter/test/FaserActsKalmanFilterAlg.py b/Tracking/Acts/FaserActsKalmanFilter/test/FaserActsKalmanFilterAlg.py
new file mode 100644
index 0000000000000000000000000000000000000000..20e97d74555122d99e0857e3f75f468532fba111
--- /dev/null
+++ b/Tracking/Acts/FaserActsKalmanFilter/test/FaserActsKalmanFilterAlg.py
@@ -0,0 +1,53 @@
+#!/usr/bin/env python
+
+import sys
+from AthenaCommon.Logging import log, logging
+from AthenaCommon.Constants import DEBUG, VERBOSE, INFO
+from AthenaCommon.Configurable import Configurable
+from CalypsoConfiguration.AllConfigFlags import ConfigFlags
+from AthenaConfiguration.TestDefaults import defaultTestFiles
+from AthenaConfiguration.MainServicesConfig import MainServicesCfg
+from AthenaPoolCnvSvc.PoolReadConfig import PoolReadCfg
+from AthenaPoolCnvSvc.PoolWriteConfig import PoolWriteCfg
+from OutputStreamAthenaPool.OutputStreamConfig import OutputStreamCfg
+from TrackerPrepRawDataFormation.TrackerPrepRawDataFormationConfig import FaserSCT_ClusterizationCfg
+from TrackerSpacePointFormation.TrackerSpacePointFormationConfig import TrackerSpacePointFinderCfg
+from TruthSeededTrackFinder.TruthSeededTrackFinderConfig import TruthSeededTrackFinderCfg
+from FaserActsKalmanFilter.FaserActsKalmanFilterConfig import FaserActsKalmanFilterCfg
+
+
+log.setLevel(DEBUG)
+Configurable.configurableRun3Behavior = True
+
+# Configure
+ConfigFlags.Input.Files = ['my.RDO.pool.root']
+ConfigFlags.Output.ESDFileName = "tmp.root"
+ConfigFlags.IOVDb.GlobalTag = "OFLCOND-XXXX-XXX-XX"
+ConfigFlags.GeoModel.Align.Dynamic = False
+ConfigFlags.Beam.NumberOfCollisions = 0.
+#ConfigFlags.Concurrency.NumThreads = 1
+ConfigFlags.lock()
+
+# Core components
+acc = MainServicesCfg(ConfigFlags)
+acc.merge(PoolReadCfg(ConfigFlags))
+
+# Inner Detector
+acc.merge(FaserSCT_ClusterizationCfg(ConfigFlags))
+acc.merge(TrackerSpacePointFinderCfg(ConfigFlags))
+acc.merge(TruthSeededTrackFinderCfg(ConfigFlags))
+acc.merge(FaserActsKalmanFilterCfg(ConfigFlags))
+
+logging.getLogger('forcomps').setLevel(VERBOSE)
+acc.foreach_component("*").OutputLevel = VERBOSE
+acc.foreach_component("*ClassID*").OutputLevel = INFO
+acc.getService("StoreGateSvc").Dump = True
+acc.getService("ConditionStore").Dump = True
+acc.printConfig(withDetails=True)
+ConfigFlags.dump()
+
+# Execute and finish
+sc = acc.run(maxEvents=-1)
+
+# Success should be 0
+sys.exit(not sc.isSuccess())
diff --git a/Tracking/Acts/README.md b/Tracking/Acts/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..2a0874fce87ed08d42fa4ac7c77d0226d430e318
--- /dev/null
+++ b/Tracking/Acts/README.md
@@ -0,0 +1,8 @@
+
+1) Go to the installation (run) directory
+
+2) source ./setup.sh
+
+3) To write the tracking geometry, type the command: FaserActsWriteTrackingGeometry.py
+
+4) To run the extrapolator, type the command: FaserActsExtrapolationAlg.py