diff --git a/MuonSpectrometer/MuonPhaseII/MuonDetDescr/ActsMuonDetectorTest/CMakeLists.txt b/MuonSpectrometer/MuonPhaseII/MuonDetDescr/ActsMuonDetectorTest/CMakeLists.txt
index 4081f78700e8f78d57f39384fa2e0932aa88a844..acdd9f1b1e1c3f04ad3ede8a8e82310d589b2e55 100644
--- a/MuonSpectrometer/MuonPhaseII/MuonDetDescr/ActsMuonDetectorTest/CMakeLists.txt
+++ b/MuonSpectrometer/MuonPhaseII/MuonDetDescr/ActsMuonDetectorTest/CMakeLists.txt
@@ -9,11 +9,11 @@ atlas_subdir( ActsMuonDetectorTest )
 atlas_add_component( ActsMuonDetectorTest
                      src/components/*.cxx src/*.cxx
                      LINK_LIBRARIES AthenaKernel StoreGateLib GeoModelUtilities MuonTesterTreeLib
-                                    GaudiKernel MuonReadoutGeometryR4 MuonGeoModelR4Lib ActsGeometryLib AthenaPoolUtilities
-                                    xAODTruth xAODMuonSimHit CxxUtils TruthUtils)
+                                    GaudiKernel MuonReadoutGeometryR4 MuonGeoModelR4Lib ActsGeometryLib AthenaPoolUtilities MuonTruthHelpers
+                                    xAODTruth xAODMuonSimHit TrkExInterfaces CxxUtils ActsInteropLib)
 
 atlas_add_test( testMuonDetectorNav
-                SCRIPT python -m ActsMuonDetectorTest.testMuonDetector
+                SCRIPT python -m ActsMuonDetectorTest.testMuonDetector 
                 PROPERTIES TIMEOUT 600
                 PRIVATE_WORKING_DIRECTORY
                 POST_EXEC_SCRIPT nopost.sh)
diff --git a/MuonSpectrometer/MuonPhaseII/MuonDetDescr/ActsMuonDetectorTest/python/testMuonDetector.py b/MuonSpectrometer/MuonPhaseII/MuonDetDescr/ActsMuonDetectorTest/python/testMuonDetector.py
index 0fc2cb56c38339063327a32c39435b199b1c612d..abf31514aee7f90f12aa7eb2ef6b2b9c59f65d08 100644
--- a/MuonSpectrometer/MuonPhaseII/MuonDetDescr/ActsMuonDetectorTest/python/testMuonDetector.py
+++ b/MuonSpectrometer/MuonPhaseII/MuonDetDescr/ActsMuonDetectorTest/python/testMuonDetector.py
@@ -15,8 +15,24 @@ def MuonDetectorNavTestCfg(flags, name = "MuonDetectorNavTest", **kwargs):
     if flags.Detector.EnableTGC:
         containerNames+=["xTgcSimHits"]
     if flags.Detector.EnablesTGC:
-        containerNames+=["xStgcSimHits"] 
-    kwargs.setdefault("SimHitKeys", containerNames)
+        containerNames+=["xStgcSimHits"]
+    
+    from MuonTruthAlgsR4.MuonTruthAlgsConfig import TruthSegmentMakerCfg, TruthSegmentToTruthPartAssocCfg, SdoMultiTruthMakerCfg
+
+    from MuonConfig.MuonTruthAlgsConfig import MuonTruthClassificationAlgCfg, MuonTruthHitCountsAlgCfg
+
+    result.merge(MuonTruthClassificationAlgCfg(flags, pdgIds=[13,998,999]))
+    result.merge(MuonTruthHitCountsAlgCfg(flags))
+    result.merge(TruthSegmentToTruthPartAssocCfg(flags))
+    result.merge(SdoMultiTruthMakerCfg(flags))
+
+    result.merge(TruthSegmentMakerCfg(flags, SimHitKeys=containerNames, useOnlyMuonHits = False))
+    kwargs.setdefault("StartFromFirstHit", True)
+    
+    from TrkConfig.AtlasExtrapolatorConfig import AtlasExtrapolatorCfg
+    extp = result.popToolsAndMerge(AtlasExtrapolatorCfg(flags))
+    extp.ApplyMaterialEffects = False
+    kwargs.setdefault("Extrapolator", extp)
 
     the_alg = CompFactory.ActsTrk.MuonDetectorNavTest(name, **kwargs)
     result.addEventAlgo(the_alg, primary = True)
@@ -26,7 +42,7 @@ if __name__=="__main__":
     from MuonGeoModelTestR4.testGeoModel import setupGeoR4TestCfg, SetupArgParser, executeTest,setupHistSvcCfg
     parser = SetupArgParser()
     parser.set_defaults(inputFile=["/cvmfs/atlas-nightlies.cern.ch/repo/data/data-art/MuonGeomRTT/R3SimHits.pool.root"])
-    parser.set_defaults(outRootFile="MuonNavigationTestR4.root")
+    parser.set_defaults(outRootFile="MuonNavigationTestR4_NewMaterial_Passive.root")
     parser.set_defaults(nEvents=10)
     parser.add_argument("--dumpDetector", help="Save dump detector visualization", action='store_true', default=False )
     parser.add_argument("--dumpPassive", help="Save  detector visualization", action='store_true', default=False )
@@ -34,7 +50,6 @@ if __name__=="__main__":
     parser.add_argument("--noSensitives", help="Do not use sensitive detectors", action='store_true', default=False )
     parser.add_argument("--dumpMaterialSurfaces", help="Save material surfaces visualization", action='store_true', default=False )
 
-
     args = parser.parse_args()
     from AthenaConfiguration.AllConfigFlags import initConfigFlags
     flags = initConfigFlags()
@@ -52,4 +67,5 @@ if __name__=="__main__":
     cfg.getPublicTool("MuonDetectorBuilderTool").dumpDetectorVolumes = args.dumpDetectorVolumes
     cfg.getPublicTool("MuonDetectorBuilderTool").BuildSensitives = not args.noSensitives
     cfg.getPublicTool("MuonDetectorBuilderTool").dumpMaterialSurfaces = args.dumpMaterialSurfaces
+
     executeTest(cfg)
diff --git a/MuonSpectrometer/MuonPhaseII/MuonDetDescr/ActsMuonDetectorTest/src/MuonDetectorNavTest.cxx b/MuonSpectrometer/MuonPhaseII/MuonDetDescr/ActsMuonDetectorTest/src/MuonDetectorNavTest.cxx
index a4a81b9e687b438edab135d00e2ce967fee103a8..2ff1da9ec01d9c22da918eee6f48d28b4dbc7b4b 100644
--- a/MuonSpectrometer/MuonPhaseII/MuonDetDescr/ActsMuonDetectorTest/src/MuonDetectorNavTest.cxx
+++ b/MuonSpectrometer/MuonPhaseII/MuonDetDescr/ActsMuonDetectorTest/src/MuonDetectorNavTest.cxx
@@ -1,5 +1,5 @@
 /*
-	Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
+Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
 */
 
 #include "MuonDetectorNavTest.h"
@@ -12,246 +12,363 @@
 #include "Acts/Propagator/Propagator.hpp"
 #include "Acts/Propagator/MaterialInteractor.hpp"
 #include "Acts/Propagator/EigenStepper.hpp"
+#include "Acts/Propagator/AtlasStepper.hpp"
 #include "Acts/Utilities/VectorHelpers.hpp"
 #include "Acts/Visualization/ObjVisualization3D.hpp"
 #include "Acts/Visualization/GeometryView3D.hpp"
+#include "Acts/EventData/ParticleHypothesis.hpp"
+#include "Acts/Propagator/detail/SteppingLogger.hpp"
 
+#include "xAODMuon/MuonSegmentContainer.h"
 #include "xAODTruth/TruthVertex.h"
-
+#include "MuonTruthHelpers/MuonSimHitHelpers.h"
 #include "TruthUtils/HepMCHelpers.h"
-
+#include "MuonReadoutGeometry/MuonReadoutElement.h"
+#include "TruthUtils/HepMCHelpers.h"
+#include "ActsInterop/LoggerUtils.h"
 #include <fstream>
 
 using namespace Acts::UnitLiterals;
 
-//Struct that is passed as an actor to ACTS that records all state information during propagation
-//Contains the information at the following link: https://github.com/acts-project/acts/blob/main/Core/include/Acts/Navigation/NavigationState.hpp
-struct StateRecorder {
-	using result_type = std::vector<Acts::Experimental::DetectorNavigator::State>;
-
-	template <typename propagator_state_t, typename stepper_t, typename navigator_t>
-	void act(propagator_state_t& state, const stepper_t& /*stepper*/,
-			const navigator_t& /*navigator*/, result_type& result,
-			const Acts::Logger& /*logger*/) const {
-
-		result.push_back(state.navigation);
-	}
-
-	template <typename propagator_state_t, typename stepper_t, typename navigator_t>
-	bool checkAbort(propagator_state_t& /*state*/, const stepper_t& /*stepper*/,
-					const navigator_t& /*navigator*/, result_type& /*result*/,
-					const Acts::Logger& /*logger*/) const {
-		return false;
-	}
-};
+namespace {
 
-//Function to write out every step taken during propagation to obj format for visualization
-void writeStepsToObj(const StateRecorder::result_type& states, const size_t& eventNumber){
-	std::ofstream os("event_" + std::to_string(eventNumber) + "_Steps.obj");
-	size_t vCounter = 0;
-	//Require at least 3 steps to draw a line
-	if(states.size() > 2){
-		++vCounter;
-		for(const auto& state : states){
-			os << "v " << state.position.x() << " " << state.position.y() << " " << state.position.z() << '\n';
-		}
-		std::size_t vBreak = vCounter + states.size() - 1;
-		for(; vCounter < vBreak; ++vCounter){
-			os << "l " << vCounter << " " << vCounter + 1 << '\n';
-		}
-	}
+using SegLink_t = std::vector<ElementLink<xAOD::MuonSegmentContainer>>;
+static const SG::ConstAccessor<SegLink_t> segAcc{"truthSegLinks"};
+static const Amg::Vector3D dummyPos{100.*Gaudi::Units::m, 100.*Gaudi::Units::m, 100.*Gaudi::Units::m};
+struct PropagatorRecorder{
+    /// @brief Position obtained by the ACTS propagator
+    Amg::Vector3D actsPropPos{Amg::Vector3D::Zero()};
+    /// @brief Direction obtained by the ACTS propgator
+    Amg::Vector3D actsPropDir{Amg::Vector3D::Zero()};
+    /// @brief Position obtained by the ATLAS extrapolator
+    Amg::Vector3D atlasPropPos{dummyPos};
+    /// @brief Direction obtained by the ATLAS extrapolator
+    Amg::Vector3D atlasPropDir{Amg::Vector3D::Zero()};
+    /// @Identifier of the state
+    Identifier id{};
+    /// @brief Momentum obtained by the ATLAS extrapolator
+    double atlasPropabsMomentum{0.};
+    /// @brief Momentum obtained by the ACTS propagator
+    double actsPropabsMomentum{0.};
+};
 }
 
+
 namespace ActsTrk {
-	MuonDetectorNavTest::MuonDetectorNavTest(const std::string& name, ISvcLocator* pSvcLocator):
-		AthHistogramAlgorithm(name, pSvcLocator){}
-
-	Amg::Transform3D MuonDetectorNavTest::toGlobalTrf(const ActsGeometryContext& gctx, const Identifier& hitId) const {
-		const MuonGMR4::MuonReadoutElement* reElement = m_r4DetMgr->getReadoutElement(hitId);
-		const IdentifierHash trfHash = reElement->detectorType() == ActsTrk::DetectorType::Mdt ?
-									   reElement->measurementHash(hitId) : reElement->layerHash(hitId);            
-		return reElement->localToGlobalTrans(gctx, trfHash);
-	}
-
-	StatusCode MuonDetectorNavTest::initialize() {
-		ATH_CHECK(m_idHelperSvc.retrieve());
-		ATH_CHECK(m_geoCtxKey.initialize());
-		ATH_CHECK(m_fieldCacheCondObjInputKey.initialize());
-		ATH_CHECK(m_truthParticleKey.initialize());
-		ATH_CHECK(m_inSimHitKeys.initialize());
-		ATH_CHECK(m_detVolSvc.retrieve());
-		ATH_CHECK(detStore()->retrieve(m_r4DetMgr));
-		ATH_CHECK(m_tree.init(this));
-		ATH_CHECK(book(TH1D("distanceBetweenHits", "distanceBetweenHits", 250, 0., 500.), "MuonNavigationTestR4", "MuonNavigationTestR4"));
-
-		ATH_MSG_VERBOSE("Successfully initialized MuonDetectorNavTest");
-		return StatusCode::SUCCESS;
-	}
-
-	StatusCode MuonDetectorNavTest::finalize() {
-		ATH_MSG_VERBOSE("Finalizing MuonDetectorNavTest");
-		ATH_CHECK(m_tree.write());
-		hist("distanceBetweenHits")->GetXaxis()->SetTitle("Distance between hits [mm]");
-		return StatusCode::SUCCESS;
-	}
-
-	StatusCode MuonDetectorNavTest::execute() {
-		ATH_MSG_INFO("Executing MuonDetectorNavTest");
-		const EventContext& ctx{Gaudi::Hive::currentContext()};
-		SG::ReadHandle<ActsGeometryContext> gctx{m_geoCtxKey, ctx};
-		SG::ReadHandle<xAOD::TruthParticleContainer> truthParticles{m_truthParticleKey, ctx};
-		SG::ReadCondHandle<AtlasFieldCacheCondObj> magFieldHandle{m_fieldCacheCondObjInputKey, ctx};
-		if (!gctx.isValid() or !truthParticles.isValid() or !magFieldHandle.isValid()) {
-			ATH_MSG_FATAL("Failed to retrieve either the geometry context, truth particles or magnetic field");
-			return StatusCode::FAILURE;
-		}
-		auto simHitCollections = m_inSimHitKeys.makeHandles(ctx);
-		Acts::GeometryContext geoContext = gctx->context();
-		Acts::MagneticFieldContext mfContext = Acts::MagneticFieldContext(*magFieldHandle);
-
-		std::vector<std::pair<Identifier, Amg::Vector3D>> propagatedHits;
-		std::vector<std::pair<Identifier, Amg::Vector3D>> propagatedHitsGlobal;
-		std::vector<std::pair<Identifier, Amg::Vector3D>> truthHits;
-
-		for(auto& simHitCollection : simHitCollections){
-			for(const xAOD::MuonSimHit* simHit : *simHitCollection){
-				if(simHit->pdgId() != 13) continue;
-				const Identifier ID = simHit->identify();
-				const Amg::Vector3D localPos = xAOD::toEigen(simHit->localPosition());
-				// const Amg::Vector3D globalDir = toGlobalTrf(*gctx, ID).rotation() * xAOD::toEigen(simHit->localDirection());
-				ATH_MSG_DEBUG("Local direction for hit ID " << m_idHelperSvc->toString(ID) << ": " << Amg::toString(xAOD::toEigen(simHit->localDirection())));
-				truthHits.emplace_back(ID, localPos);
-			}
-		}
-
-		using Stepper = Acts::EigenStepper<>;
-		using Navigator = Acts::Experimental::DetectorNavigator;
-		using Propagator = Acts::Propagator<Stepper,Navigator>;
-		using ActorList = Acts::ActorList<StateRecorder, Acts::MaterialInteractor, Acts::EndOfWorldReached>;
-		using PropagatorOptions = Propagator::Options<ActorList>;
-
-		auto bField = std::make_shared<ATLASMagneticFieldWrapper>();
-		auto stepper = Stepper(std::move(bField));
-
-		PropagatorOptions options(geoContext, mfContext);
-
-		options.pathLimit = 23_m;
-		options.stepping.maxStepSize = 0.5_m;
-
-		//Configure the material collector
-		auto& materialInteractor = options.actorList.get<Acts::MaterialInteractor>();
-		materialInteractor.energyLoss = true;
-		materialInteractor.multipleScattering = true;
-		materialInteractor.recordInteractions = true;
-		
-		const Acts::Experimental::Detector* detector = m_detVolSvc->detector().get();
-		for(const auto truthParticle : *truthParticles){
-			//Require that we only propagate on muons, and of status 1
-                  if(MC::isStable(truthParticle) and truthParticle->pdgId() == MC::MUON){ // FIXME not antimuons?
-				const auto& particle = truthParticle->p4();
-				const auto& prodVertex = (!truthParticle->hasProdVtx()) ? nullptr : truthParticle->prodVtx();
-				double x = prodVertex ? prodVertex->x() : 0.;
-				double y = prodVertex ? prodVertex->y() : 0.;
-				double z = prodVertex ? prodVertex->z() : 0.;
-
-				Acts::CurvilinearTrackParameters start(
-					Acts::VectorHelpers::makeVector4(Acts::Vector3(x, y, z), 0.),
-					Acts::Vector3(particle.Px(), particle.Py(), particle.Pz()).normalized(),
-					truthParticle->charge() / particle.P(),
-					std::nullopt,
-					Acts::ParticleHypothesis::muon());
-
-				Acts::Experimental::DetectorNavigator::Config navCfg;
-				navCfg.detector = detector;
-				navCfg.resolvePassive = true;
-
-				Acts::Experimental::DetectorNavigator navigator(navCfg, Acts::getDefaultLogger("DetectorNavigator", Acts::Logging::Level::INFO));
-				Acts::Propagator<Stepper, Acts::Experimental::DetectorNavigator> propagator(
-					std::move(stepper), std::move(navigator),
-					Acts::getDefaultLogger("Propagator", Acts::Logging::Level::INFO));
-
-				auto result = propagator.propagate(start, options).value();
-				const StateRecorder::result_type state = result.get<StateRecorder::result_type>();
-				const Acts::MaterialInteractor::result_type material = result.get<Acts::MaterialInteractor::result_type>();
-				ATH_MSG_DEBUG("Material interactions: " << material.materialInteractions.size());
-				ATH_MSG_DEBUG("material in x0: " << material.materialInX0);
-				ATH_MSG_DEBUG("material in L0: " << material.materialInL0);
-				std::vector<Acts::MaterialInteraction> interactions = material.materialInteractions;
-				for(const Acts::MaterialInteraction& interaction : interactions){
-					ATH_MSG_DEBUG("Path Correction: " << interaction.pathCorrection);
-					ATH_MSG_DEBUG("Momentum change: " << interaction.deltaP);
-				}
-				// loop through the states drawing each surface or portal
-				Acts::ObjVisualization3D helper{};
-				for (const auto& s : state) {
-					if(s.currentSurface) Acts::GeometryView3D::drawSurface(helper, *s.currentSurface, geoContext);
-				}
-				helper.write("event_" + std::to_string(ctx.evt() + 1) +"_Hits.obj");
-				helper.clear();
-				writeStepsToObj(state, ctx.evt() + 1);
-				ATH_MSG_VERBOSE("Number of propagated steps : " << state.size());
-				for(const auto& state: state){
-					if(state.currentSurface){
-						const SurfaceCache* sCache = dynamic_cast<const SurfaceCache *>(state.currentSurface->associatedDetectorElement());
-						if(!sCache){
-							ATH_MSG_VERBOSE("Surface found but it's a portal, continuing..");
-							continue;
-						}
-						const Identifier ID = sCache->identify();
-						const Amg::Transform3D localTrf = sCache->transform(geoContext).inverse();
-						const Amg::Vector3D localPos{localTrf * state.position};
-						ATH_MSG_DEBUG("Identify hit " << m_idHelperSvc->toString(ID) << " with hit at " << Amg::toString(localPos));
-						propagatedHits.emplace_back(ID, localPos);
-						propagatedHitsGlobal.emplace_back(ID, state.position);
-					}
-				}
-			}
-		}
-		//compare the hits
-		for(const auto& truthHit : truthHits){
-			bool hitFound = false;
-			for(const auto& propagatedHit : propagatedHits){
-				if(truthHit.first == propagatedHit.first){
-					hitFound = true;
-					break;
-				}
-			}
-			if(!hitFound) ATH_MSG_VERBOSE("Truth hit not found, ID: " << m_idHelperSvc->toString(truthHit.first) << " at " << Amg::toString(truthHit.second));
-			
-		}
-		//Check if all propagated hits are found
-		for(const auto& propagatedHit : propagatedHits){
-			bool hitFound = false;
-			for(const auto& truthHit : truthHits){
-				if(truthHit.first == propagatedHit.first){
-					hitFound = true;
-					break;
-				}
-			}
-			if(!hitFound){
-				ATH_MSG_VERBOSE("Propagated hit not found, ID: " << m_idHelperSvc->toString(propagatedHit.first) << " at " << Amg::toString(propagatedHit.second));
-			}
-		}
-
-		//For one final check, put all hits into the global frame, and find which hits are closest to one another
-		for(const auto& propagatedHit: propagatedHitsGlobal){
-			double minDistance = std::numeric_limits<double>::max();
-			Identifier closestID{};
-			for(const auto& truthHit: truthHits){
-				const double distance = (propagatedHit.second - toGlobalTrf(*gctx, truthHit.first) * truthHit.second).norm();
-				if(distance < minDistance){
-					minDistance = distance;
-					closestID = truthHit.first;
-				}
-			}
-			ATH_MSG_VERBOSE("Closest hit to propagated hit " << m_idHelperSvc->toString(propagatedHit.first) << " is " << m_idHelperSvc->toString(closestID) << " with distance " << minDistance);
-			m_distanceBetweenHits = minDistance;
-			m_propagatedIdentifier = m_idHelperSvc->toString(propagatedHit.first);
-			m_truthIdentifier = m_idHelperSvc->toString(closestID);
-			hist("distanceBetweenHits")->Fill(minDistance);
-			m_tree.fill(ctx);
-		}
-
-		return StatusCode::SUCCESS;
-	}
+
+Amg::Transform3D MuonDetectorNavTest::toGlobalTrf(const ActsGeometryContext& gctx, const Identifier& hitId) const {
+    const MuonGMR4::MuonReadoutElement* reElement = m_r4DetMgr->getReadoutElement(hitId);
+    const IdentifierHash trfHash = reElement->detectorType() == ActsTrk::DetectorType::Mdt ?
+                                    reElement->measurementHash(hitId) : reElement->layerHash(hitId);            
+    return reElement->localToGlobalTrans(gctx, trfHash);
 }
+//get the transformation to the readout element's local frame - first measurement plane
+Amg::Transform3D MuonDetectorNavTest::toLocalTrf(const ActsGeometryContext& gctx, const Identifier& hitId) const {
+    const MuonGMR4::MuonReadoutElement* reElement = m_r4DetMgr->getReadoutElement(hitId);          
+    return reElement->globalToLocalTrans(gctx, reElement->layerHash(hitId));
+}
+
+
+IdentifierHash MuonDetectorNavTest::layerHash(const Identifier& id) const {
+    return m_r4DetMgr->getReadoutElement(id)->layerHash(id);
+}
+
+StatusCode MuonDetectorNavTest::initialize() {
+    ATH_CHECK(m_idHelperSvc.retrieve());
+    ATH_CHECK(m_geoCtxKey.initialize());
+    ATH_CHECK(m_fieldCacheCondObjInputKey.initialize());
+    ATH_CHECK(m_truthParticleKey.initialize());
+    ATH_CHECK(m_truthSegLinkKey.initialize());
+    ATH_CHECK(m_detVolSvc.retrieve());
+    ATH_CHECK(m_extrapolator.retrieve());
+    ATH_CHECK(m_detMgrKey.initialize());
+    ATH_CHECK(m_truthSegLinkKey.initialize());
+    ATH_CHECK(detStore()->retrieve(m_r4DetMgr));
+    ATH_CHECK(m_tree.init(this));
+
+    ATH_MSG_VERBOSE("Successfully initialized MuonDetectorNavTest");
+    return StatusCode::SUCCESS;
+}
+
+StatusCode MuonDetectorNavTest::finalize() {
+    ATH_MSG_VERBOSE("Finalizing MuonDetectorNavTest");
+    ATH_CHECK(m_tree.write());
+    return StatusCode::SUCCESS;
+}
+
+StatusCode MuonDetectorNavTest::execute() {
+    const EventContext& ctx{Gaudi::Hive::currentContext()};
+    ATH_MSG_DEBUG("Execute in event "<<ctx.eventID().event_number());
+    m_event = ctx.eventID().event_number();
+    SG::ReadHandle<ActsGeometryContext> gctx{m_geoCtxKey, ctx};
+    SG::ReadHandle<xAOD::TruthParticleContainer> truthParticles{m_truthParticleKey, ctx};
+    SG::ReadCondHandle<AtlasFieldCacheCondObj> magFieldHandle{m_fieldCacheCondObjInputKey, ctx};
+    if (!gctx.isValid() or !truthParticles.isValid() or !magFieldHandle.isValid()) {
+        ATH_MSG_FATAL("Failed to retrieve either the geometry context, truth particles or magnetic field");
+        return StatusCode::FAILURE;
+    }
+    SG::ReadCondHandle detMgr{m_detMgrKey, ctx};
+
+
+    const Acts::GeometryContext geoContext = gctx->context();
+    const AtlasFieldCacheCondObj* fieldCondObj{*magFieldHandle};
+    Acts::MagneticFieldContext mfContext = Acts::MagneticFieldContext(fieldCondObj);
+
+
+    using Stepper = Acts::EigenStepper<>;
+    //using Stepper = Acts::AtlasStepper;
+    using Navigator = Acts::Experimental::DetectorNavigator;
+    using Propagator = Acts::Propagator<Stepper,Navigator>;
+    using ActorList = Acts::ActorList<Acts::detail::SteppingLogger, Acts::MaterialInteractor, Acts::EndOfWorldReached>;
+    using PropagatorOptions = Propagator::Options<ActorList>;
+
+    
+    PropagatorOptions options(geoContext, mfContext);
+
+    options.pathLimit = m_pathLimit;
+    options.stepping.maxStepSize = m_maxStepSize;
+    options.stepping.stepTolerance = m_stepTolerance;
+    options.maxSteps = m_maxSteps;
+    options.maxTargetSkipping = m_maxTargetSkipping;
+
+    //Configure the material collector
+    auto& materialInteractor = options.actorList.get<Acts::MaterialInteractor>();
+    materialInteractor.energyLoss = false;
+    materialInteractor.multipleScattering = false;
+    materialInteractor.recordInteractions = false;
+    
+    const Acts::Experimental::Detector* detector = m_detVolSvc->detector().get();
+
+    Acts::Experimental::DetectorNavigator::Config navCfg;
+    navCfg.detector = detector;
+    navCfg.resolvePassive = true;
+
+    auto bField = std::make_shared<ATLASMagneticFieldWrapper>();
+    auto bfieldCache = bField->makeCache(mfContext);
+    auto stepper = Stepper(bField);
+    
+
+    Acts::Experimental::DetectorNavigator navigator(navCfg, Acts::getDefaultLogger("DetectorNavigator", ActsTrk::actsLevelVector(msgLevel())));               
+    Acts::Propagator<Stepper, Acts::Experimental::DetectorNavigator> propagator(
+        std::move(stepper), std::move(navigator),
+        Acts::getDefaultLogger("Propagator", ActsTrk::actsLevelVector(msgLevel())));
+
+    
+    for(const xAOD::TruthParticle* truthParticle : *truthParticles){
+        
+        ATH_MSG_DEBUG("Consider truth particle "<<truthParticle->pt()<<", "<<truthParticle->p4().P()<<", "<<truthParticle->eta()<<", "<<truthParticle->phi()
+                        <<", pdgId: "<<truthParticle->pdgId()<<", status: "<<truthParticle->status()
+                    <<", unique id:"<<truthParticle->id());
+        
+            //propagated and truth hits expressed in the local frame of the measurement layer           
+        std::vector<PropagatorRecorder> propagatedHits;
+        std::vector<std::pair<Identifier, Amg::Vector3D>> truthHits;
+        
+        //the particle hypothesis
+        Acts::ParticleHypothesis particleHypothesis(static_cast<Acts::PdgParticle>(truthParticle->absPdgId()), truthParticle->m(), truthParticle->charge());
+        
+        std::vector<std::pair<const xAOD::MuonSegment*, std::vector<const xAOD::MuonSimHit*>>> muonSegmentWithSimHits;
+        for (const auto& truthSegLink : segAcc(*truthParticle)){
+            const xAOD::MuonSegment* seg{*truthSegLink}; 
+            auto unordedHits = MuonR4::getMatchingSimHits(*seg);
+            std::vector<const xAOD::MuonSimHit*> muonSimHits{unordedHits.begin(), unordedHits.end()};           
+            ATH_MSG_VERBOSE("Segment at : "<<Amg::toString(seg->position())<<" with Sim Hits: "<<unordedHits.size());
+            muonSegmentWithSimHits.emplace_back(seg,muonSimHits);
+        }
+        const auto& particle = truthParticle->p4();
+        m_truthPt = particle.Pt();
+        m_truthP = particle.P();
+        
+        const xAOD::TruthVertex* prodVertex = truthParticle->prodVtx();
+        Amg::Vector3D prodPos = prodVertex ? Amg::Vector3D(prodVertex->x(), prodVertex->y(), prodVertex->z()) 
+                                            : Amg::Vector3D::Zero();
+        Amg::Vector3D prodDir{Amg::dirFromAngles(particle.Phi(), particle.Theta())};
+
+        //position, direction and momentum at the start of the propagation
+        Amg::Vector3D startPropPos{prodPos};
+        Amg::Vector3D startPropDir{prodDir};
+        double startPropP{particle.P()};
+        ATH_MSG_VERBOSE("Magnetic field at the production vertex: "<<Amg::toString(bField->getField(prodPos, bfieldCache).value())<<"at position "<<Amg::toString(prodPos));
+        for (double r =0; r<=2.*Gaudi::Units::m; r+=10.*Gaudi::Units::cm) {
+            Amg::Vector3D magFieldPos{startPropPos.x()+r, startPropPos.y()+r, startPropPos.z()};
+            ATH_MSG_VERBOSE("Magnetic Field in the ID is: "<<Amg::toString(bField->getField(magFieldPos, bfieldCache).value()));
+            
+        }
+        
+        
+        
+        
+        ATH_MSG_VERBOSE("Production vertex at "<<Amg::toString(prodPos)<<" with direction "<<Amg::toString(prodDir)<<" and momentum "<<startPropP);
+        
+
+        if(m_startFromFirstHit){
+            if (muonSegmentWithSimHits.empty()) {
+                continue;
+            }
+            //sort the segments by the radial distance
+            std::ranges::sort(muonSegmentWithSimHits,
+                    [](const auto& a, const auto& b) {
+                        return a.first->position().perp() < b.first->position().perp(); 
+            });
+        
+            //get the simHits from the first segment - from sorted segments
+            std::vector<const xAOD::MuonSimHit*>& muonSimHits = muonSegmentWithSimHits.front().second;
+            if (msgLvl(MSG::VERBOSE)){
+                for(const auto& simHit: muonSimHits){
+                    ATH_MSG_VERBOSE("Sim Hit of first segment at global position: "<<Amg::toString(toGlobalTrf(*gctx, simHit->identify())*xAOD::toEigen(simHit->localPosition())));
+                }
+            }
+
+            //sort the simhits to define starting propagation position
+            std::ranges::sort(muonSimHits, 
+                        [this, &gctx](const xAOD::MuonSimHit* hit1, const xAOD::MuonSimHit* hit2){
+                        const Amg::Vector3D globalPos1 = toGlobalTrf(*gctx,hit1->identify())*xAOD::toEigen(hit1->localPosition());
+                        const Amg::Vector3D globalPos2 = toGlobalTrf(*gctx,hit2->identify())*xAOD::toEigen(hit2->localPosition());
+                        return globalPos1.norm()<globalPos2.norm();
+            });
+            if (msgLvl(MSG::VERBOSE)){
+            ATH_MSG_VERBOSE("After sorting..");
+            for(const auto& simHit: muonSimHits){
+                ATH_MSG_VERBOSE("Sim Hit of first segment at position: "<<Amg::toString(toGlobalTrf(*gctx, simHit->identify())*xAOD::toEigen(simHit->localPosition())));
+
+            }
+            }
+        
+            startPropPos = toGlobalTrf(*gctx, muonSimHits.front()->identify())*xAOD::toEigen(muonSimHits.front()->localPosition());
+            startPropDir = toGlobalTrf(*gctx, muonSimHits.front()->identify()).linear()*xAOD::toEigen(muonSimHits.front()->localDirection());
+            startPropP = muonSimHits.front()->kineticEnergy();
+            ATH_MSG_VERBOSE("Kinetic Energy from the simHit: "<<muonSimHits.front()->kineticEnergy() / Gaudi::Units::GeV<<" and mass: "<<muonSimHits.front()->mass()<<" and energy deposit: "<<muonSimHits.front()->energyDeposit() / Gaudi::Units::eV);
+        }
+
+        ATH_MSG_VERBOSE("Starting propagation from"<<Amg::toString(startPropPos)<<" with direction"
+                        <<Amg::toString(startPropDir)<<" and momentum "<<startPropP);   	
+
+
+        Acts::CurvilinearTrackParameters start(
+            Acts::VectorHelpers::makeVector4(startPropPos, 0.), startPropDir,
+            truthParticle->charge() / startPropP,
+            std::nullopt,
+            particleHypothesis);
+
+        
+        Trk::CurvilinearParameters atlasStart(startPropPos, startPropP*startPropDir, truthParticle->charge());
+
+        ATH_MSG_DEBUG("start propagating here");
+        auto result = propagator.propagate(start, options);
+        const Acts::detail::SteppingLogger::result_type state = result.value().get<Acts::detail::SteppingLogger::result_type>();
+        const Acts::MaterialInteractor::result_type material = result.value().get<Acts::MaterialInteractor::result_type>();
+        ATH_MSG_DEBUG("Material interactions: " << material.materialInteractions.size());
+        ATH_MSG_DEBUG("material in x0: " << material.materialInX0);
+        ATH_MSG_DEBUG("material in L0: " << material.materialInL0);
+        std::vector<Acts::MaterialInteraction> interactions = material.materialInteractions;
+        for(const Acts::MaterialInteraction& interaction : interactions){
+                ATH_MSG_DEBUG("Path Correction: " << interaction.pathCorrection);
+                ATH_MSG_DEBUG("Momentum change: " << interaction.deltaP);
+        }
+        // loop through the states drawing each surface or portal
+        if(m_drawEvent){
+            Acts::ObjVisualization3D helper{};
+            for (const auto& s : state.steps) {
+                if(s.surface) Acts::GeometryView3D::drawSurface(helper, *s.surface, geoContext);
+            }
+            helper.write(std::format("event_{:}_{:}_Hits.obj", ctx.eventID().event_number(), truthParticle->index()));
+        }
+    
+        ATH_MSG_VERBOSE("Number of propagated steps : " << state.steps.size());
+        m_propSteps = state.steps.size();
+        for(const auto& state: state.steps){
+            if(!state.surface){
+                continue;
+            }
+            const SurfaceCache* sCache = dynamic_cast<const SurfaceCache *>(state.surface->associatedDetectorElement());
+            if(!sCache){
+                ATH_MSG_VERBOSE("Surface found but it's a portal, continuing..");
+                continue;
+            }
+            const Identifier ID = sCache->identify();
+            const Amg::Transform3D toGap{toLocalTrf(*gctx, ID)};
+            ATH_MSG_VERBOSE("Identify propagated hit " << m_idHelperSvc->toString(ID) << " with hit at local position " << Amg::toString(toGap*state.position)<<" and global direction "<<Amg::toString(state.momentum.unit()));
+            ATH_MSG_VERBOSE("Magnetic field "<<Amg::toString(bField->getField(state.position, bfieldCache).value())<<"at position "<<Amg::toString(state.position));
+            PropagatorRecorder newRecord{};
+            newRecord.id = ID;
+            newRecord.actsPropPos = toGap*state.position;
+            newRecord.actsPropDir = toGap.linear()*state.momentum.unit();
+            newRecord.actsPropabsMomentum = state.momentum.norm();
+
+            //define the surface to propagate
+            const Trk::Surface& surface = detMgr->getReadoutElement(ID)->surface(ID);
+
+            Trk::ParticleHypothesis particleType = Trk::geantino;
+            if(truthParticle->isMuon()){
+                particleType = Trk::muon;   
+            }
+            
+
+            std::unique_ptr<Trk::TrackParameters> atlasPars{m_extrapolator->extrapolate(ctx, atlasStart,
+                                                            surface, Trk::alongMomentum,false, 
+                                                            particleType, Trk::MaterialUpdateMode::removeNoise)};
+
+
+            if (atlasPars) {
+                newRecord.atlasPropPos =  toGap* atlasPars->position();
+                newRecord.atlasPropDir = toGap.linear()*atlasPars->momentum().unit();
+                newRecord.atlasPropabsMomentum = atlasPars->momentum().mag();
+            }
+            propagatedHits.emplace_back(newRecord);
+        }
+
+        //fill with the truthHits- id and local position on the measurement layer's frame and look in the propagated hits
+        unsigned int nMatchedTruth = 0, nMatchedProp = 0, nTruth{0};
+        for (const auto&[segment, simHits] : muonSegmentWithSimHits) {
+            for(const xAOD::MuonSimHit* simHit : simHits){
+                const Identifier ID = simHit->identify();
+                ++nTruth;
+                //express the truth hits in the 1st measurement of readout element's local frame - same as the propagated hits
+                const Amg::Transform3D localTrf{toLocalTrf(*gctx, simHit->identify())*
+                    toGlobalTrf(*gctx,simHit->identify())};
+                const Amg::Vector3D localPos = localTrf*xAOD::toEigen(simHit->localPosition());
+                const Amg::Vector3D localDir = localTrf.linear()*xAOD::toEigen(simHit->localDirection());
+                m_detId.push_back(ID);
+                m_techIdx.push_back(m_idHelperSvc->technologyIndex(ID));
+                m_gasGapId.push_back(layerHash(ID));
+
+                m_truthLoc.push_back(localPos);
+                m_truthDir.push_back(localDir);
+                ATH_MSG_VERBOSE("Identify truth hit at local position in 1st measurement plane" << Amg::toString(localPos));
+
+                auto it = std::ranges::find_if(propagatedHits,
+                                        [this, ID, &localPos](const auto& propagatedHit) {
+                                        return  m_idHelperSvc->detElId(ID) == m_idHelperSvc->detElId(propagatedHit.id) &&
+                                                layerHash(ID) == layerHash(propagatedHit.id);
+                });
+                m_isPropagated.push_back(it != propagatedHits.end());
+                if(it != propagatedHits.end()){
+                    ATH_MSG_DEBUG("Truth hit found in propagated hits: " << m_idHelperSvc->toString(ID));
+                    m_actsPropLoc.push_back(it->actsPropPos);
+                    m_actsPropDir.push_back(it->actsPropDir);
+                    m_atlasPropLoc.push_back(it->atlasPropPos);
+                    m_atlasPropDir.push_back(it->atlasPropDir);        
+                    m_actsPropMomentum.push_back(it->actsPropabsMomentum);
+                    m_atlasPropMomentum.push_back(it->atlasPropabsMomentum);                
+                    nMatchedTruth++;
+                }else{
+                    m_actsPropLoc.push_back(dummyPos);
+                    m_actsPropDir.push_back(dummyPos);
+                    m_atlasPropLoc.push_back(dummyPos);
+                    m_atlasPropDir.push_back(dummyPos);
+                    m_actsPropMomentum.push_back(0.);
+                    m_atlasPropMomentum.push_back(0.);
+                }
+            }
+        }
+        m_matchedTruthFraction = 1.f*nMatchedTruth / nTruth;
+        m_matchedPropFraction = 1.f*nMatchedProp / propagatedHits.size();
+
+        m_tree.fill(ctx); 
+        
+    }
+
+    return StatusCode::SUCCESS;
+}
+}  // namespace ActsTrk`
+
diff --git a/MuonSpectrometer/MuonPhaseII/MuonDetDescr/ActsMuonDetectorTest/src/MuonDetectorNavTest.h b/MuonSpectrometer/MuonPhaseII/MuonDetDescr/ActsMuonDetectorTest/src/MuonDetectorNavTest.h
index 16ba94d59074c2e905d8eec6fd48b17bf32b0c28..1a7ec1e7f66193427a59fa0bce98ff795478d03f 100644
--- a/MuonSpectrometer/MuonPhaseII/MuonDetDescr/ActsMuonDetectorTest/src/MuonDetectorNavTest.h
+++ b/MuonSpectrometer/MuonPhaseII/MuonDetDescr/ActsMuonDetectorTest/src/MuonDetectorNavTest.h
@@ -17,46 +17,91 @@
 #include <StoreGate/ReadHandleKeyArray.h>
 #include <StoreGate/ReadHandleKey.h>
 
+
 #include <MuonReadoutGeometryR4/MuonDetectorManager.h>
 #include "MuonTesterTree/MuonTesterTree.h"
+#include "MuonTesterTree/ThreeVectorBranch.h"
+#include "MuonTesterTree/IdentifierBranch.h"
+
+#include "MuonReadoutGeometry/MuonDetectorManager.h"
 
 #include "Acts/MagneticField/MagneticFieldContext.hpp"
 #include "Acts/Navigation/DetectorNavigator.hpp"
+#include "TrkExInterfaces/IExtrapolator.h"
 
 namespace ActsTrk {
     class MuonDetectorNavTest: public AthHistogramAlgorithm {
         public:
-        MuonDetectorNavTest(const std::string& name, ISvcLocator* pSvcLocator);
+        using AthHistogramAlgorithm::AthHistogramAlgorithm;
         
         ~MuonDetectorNavTest() = default;
         
         StatusCode execute() override;
         StatusCode initialize() override;
-		StatusCode finalize() override;
+        StatusCode finalize() override;
 
         private:
 
         Amg::Transform3D toGlobalTrf(const ActsGeometryContext& gctx, const Identifier& hitId) const;
 
+        Amg::Transform3D toLocalTrf(const ActsGeometryContext& gctx, const Identifier& hitId) const;
+
+        IdentifierHash layerHash(const Identifier& id) const;
+
         ServiceHandle<Muon::IMuonIdHelperSvc> m_idHelperSvc{this, "IdHelperSvc", "Muon::MuonIdHelperSvc/MuonIdHelperSvc"};
 
         SG::ReadCondHandleKey<AtlasFieldCacheCondObj> m_fieldCacheCondObjInputKey {this, "AtlasFieldCacheCondObj", "fieldCondObj", "Name of the Magnetic Field conditions object key"};
 
         SG::ReadHandleKey<ActsGeometryContext> m_geoCtxKey{this, "AlignmentKey", "ActsAlignment", "cond handle key"};
 
-        SG::ReadHandleKey<xAOD::TruthParticleContainer> m_truthParticleKey{this, "TruthKey", "TruthParticles", "key"};
+        SG::ReadHandleKey<xAOD::TruthParticleContainer> m_truthParticleKey{this, "TruthKey", "MuonTruthParticles"};
+
+        SG::ReadDecorHandleKey<xAOD::TruthParticleContainer> m_truthSegLinkKey{this, "TruthKeyToSeg", m_truthParticleKey, "truthSegLinks", "TruthParticle to TruthSegment link"};
 
         const MuonGMR4::MuonDetectorManager* m_r4DetMgr{nullptr};
 
-        SG::ReadHandleKeyArray<xAOD::MuonSimHitContainer> m_inSimHitKeys {this, "SimHitKeys",{ "xMdtSimHits","xRpcSimHits","xTgcSimHits","xStgcSimHits","xMmSimHits"}, "xAOD  SimHit collections"};
+        BooleanProperty m_drawEvent{this, "DrawEvent", false};
+
+        DoubleProperty m_pathLimit{this, "PathLimit", 23.*Gaudi::Units::m};
+
+        DoubleProperty m_maxStepSize{this, "MaxStepSize", 1.*Gaudi::Units::m};
+
+        UnsignedIntegerProperty m_maxSteps{this, "MaxSteps", 100000};
+
+        DoubleProperty m_stepTolerance{this, "StepTolerance", 1e-10};
+
+        UnsignedIntegerProperty m_maxTargetSkipping{this, "MaxTargetSkipping", 10000};            
 
         ServiceHandle<ActsTrk::IDetectorVolumeSvc> m_detVolSvc{this, "DetectorVolumeSvc", "DetectorVolumeSvc"};
 
+        ToolHandle<Trk::IExtrapolator> m_extrapolator{this, "Extrapolator",
+          "Trk::Extrapolator/AtlasExtrapolator" "Tool for ATLAS Extrapolator"};  
+
+        SG::ReadCondHandleKey<MuonGM::MuonDetectorManager> m_detMgrKey{this, "MuonManagerKey", 
+          "MuonDetectorManager", "MuonManager ReadKey for IOV Range intersection"};
+    
+        Gaudi::Property<bool> m_startFromFirstHit{this, "StartFromFirstHit", false, "Start from first hit"};
+
         MuonVal::MuonTesterTree m_tree{"MuonNavigationTestR4", "MuonNavigationTestR4"};
-		MuonVal::ScalarBranch<float>& m_distanceBetweenHits{m_tree.newScalar<float>("distanceBetweenHits")};
-		MuonVal::ScalarBranch<std::string>& m_propagatedIdentifier{m_tree.newScalar<std::string>("propagatedIdentifier")};
-		MuonVal::ScalarBranch<std::string>& m_truthIdentifier{m_tree.newScalar<std::string>("truthIdentifier")};
+        MuonVal::MuonIdentifierBranch m_detId{m_tree, "detId"};
+        MuonVal::VectorBranch<unsigned short>& m_techIdx{m_tree.newVector<unsigned short>("detId_techIdx")};
+        MuonVal::VectorBranch<unsigned short>& m_gasGapId{m_tree.newVector<unsigned short>("detId_gasGap")};
+        MuonVal::VectorBranch<double>& m_actsPropMomentum{m_tree.newVector<double>("actsPropMomentum")};
+        MuonVal::VectorBranch<double>& m_atlasPropMomentum{m_tree.newVector<double>("atlasPropMomentum")};
+        MuonVal::ThreeVectorBranch m_truthLoc{m_tree, "truthHitLoc"};
+        MuonVal::ThreeVectorBranch m_truthDir{m_tree, "truthHitDir"};
+        MuonVal::ThreeVectorBranch m_actsPropLoc{m_tree, "actsPropLoc"};
+        MuonVal::ThreeVectorBranch m_atlasPropLoc{m_tree, "atlasPropLoc"};
+        MuonVal::ThreeVectorBranch m_actsPropDir{m_tree, "actsPropDir"};
+        MuonVal::ThreeVectorBranch m_atlasPropDir{m_tree, "atlasPropDir"};
+        MuonVal::VectorBranch<unsigned short>& m_isPropagated{m_tree.newVector<unsigned short>("isPropagated")};
+        MuonVal::ScalarBranch<unsigned int>& m_propSteps{m_tree.newScalar<unsigned int>("propSteps")};
+        MuonVal::ScalarBranch<float>& m_matchedTruthFraction{m_tree.newScalar<float>("matchedTruthFraction")};
+        MuonVal::ScalarBranch<float>& m_matchedPropFraction{m_tree.newScalar<float>("matchedPropFraction")};
+        MuonVal::ScalarBranch<float>& m_truthPt{m_tree.newScalar<float>("truthPt")};
+        MuonVal::ScalarBranch<float>& m_truthP{m_tree.newScalar<float>("truthP")};
+        MuonVal::ScalarBranch<unsigned int>& m_event{m_tree.newScalar<unsigned int>("event")};
 
     };
 }
-#endif
\ No newline at end of file
+#endif