diff --git a/MuonSpectrometer/MuonPhaseII/MuonPatternRecognition/MuonTruthAlgsR4/CMakeLists.txt b/MuonSpectrometer/MuonPhaseII/MuonPatternRecognition/MuonTruthAlgsR4/CMakeLists.txt
index a87b3218f1cedcd87234258536d4d143a876020b..e87f9bcb710adbb2a9475ebc4c6d30f76f6189b9 100644
--- a/MuonSpectrometer/MuonPhaseII/MuonPatternRecognition/MuonTruthAlgsR4/CMakeLists.txt
+++ b/MuonSpectrometer/MuonPhaseII/MuonPatternRecognition/MuonTruthAlgsR4/CMakeLists.txt
@@ -10,7 +10,7 @@ atlas_add_component( MuonTruthAlgsR4
                      src/components/*.cxx src/*.cxx
                      LINK_LIBRARIES  xAODMuonSimHit AthenaBaseComps GaudiKernel xAODMuon MuonIdHelpersLib
                                      MuonReadoutGeometryR4 xAODMuonPrepData MuonPatternEvent xAODMuonViews
-                                     TrkTruthData MuonTruthHelpers)
+                                     TrkTruthData MuonTruthHelpers MuonRecHelperToolsLib)
 
 # Install files from the package:
 atlas_install_python_modules( python/*.py POST_BUILD_CMD ${ATLAS_FLAKE8} )
diff --git a/MuonSpectrometer/MuonPhaseII/MuonPatternRecognition/MuonTruthAlgsR4/python/MuonTruthAlgsConfig.py b/MuonSpectrometer/MuonPhaseII/MuonPatternRecognition/MuonTruthAlgsR4/python/MuonTruthAlgsConfig.py
index 11a816b444d4ea6069e1e4de84624d559a16530b..18a24c954c74dc48353bf04b07d756fb8142bda3 100644
--- a/MuonSpectrometer/MuonPhaseII/MuonPatternRecognition/MuonTruthAlgsR4/python/MuonTruthAlgsConfig.py
+++ b/MuonSpectrometer/MuonPhaseII/MuonPatternRecognition/MuonTruthAlgsR4/python/MuonTruthAlgsConfig.py
@@ -87,24 +87,33 @@ def PrdMultiTruthMakerCfg(flags):
         result.addEventAlgo(the_alg) 
     return result
 
-def TruthSegmentToTruthPartCfg(flags, name="MuonTruthSegmentToTruthAssocAlg", **kwargs):
+def TruthSegmentToTruthPartAssocCfg(flags, name="MuonTruthSegmentToTruthAssocAlg", **kwargs):
     result = ComponentAccumulator()
     hitDecors = []
-    if flags.Detector.GeometryMDT:
-        hitDecors+=["truthMdtHits"]
-    if flags.Detector.GeometryRPC:
-        hitDecors+=["truthRpcHits"]
-    if flags.Detector.GeometryTGC:
-        hitDecors+=["truthTgcHits"]
-    if flags.Detector.GeometryMM:
-        hitDecors+=["truthMMHits"]
-    if flags.Detector.GeometrysTGC:
-        hitDecors+=["truthStgcHits"]
+    if flags.Detector.GeometryMDT: hitDecors+=["truthMdtHits"]
+    if flags.Detector.GeometryRPC: hitDecors+=["truthRpcHits"]
+    if flags.Detector.GeometryTGC: hitDecors+=["truthTgcHits"]
+    if flags.Detector.GeometryMM: hitDecors+=["truthMMHits"]
+    if flags.Detector.GeometrysTGC: hitDecors+=["truthStgcHits"]
     kwargs.setdefault("SimHitIds", hitDecors)
     the_alg = CompFactory.MuonR4.TruthSegToTruthPartAssocAlg(name, **kwargs)
     result.addEventAlgo(the_alg, primary = True)
     return result
 
+def TrackToTruthPartAssocCfg(flags, **kwargs):
+    result = ComponentAccumulator()
+    hitDecors = []
+    if flags.Detector.GeometryMDT: hitDecors+=["truthMdtHits"]
+    if flags.Detector.GeometryRPC: hitDecors+=["truthRpcHits"]
+    if flags.Detector.GeometryTGC: hitDecors+=["truthTgcHits"]
+    if flags.Detector.GeometryMM: hitDecors+=["truthMMHits"]
+    if flags.Detector.GeometrysTGC: hitDecors+=["truthStgcHits"]
+    kwargs.setdefault("SimHitIds", hitDecors)
+    the_alg = CompFactory.MuonR4.TrackToTruthPartAssocAlg(**kwargs)
+    result.addEventAlgo(the_alg, primary = True)
+    return result
+
+
 @AccumulatorCache
 def MuonTruthAlgsCfg(flags):
     result = ComponentAccumulator()
@@ -123,5 +132,5 @@ def MuonTruthAlgsCfg(flags):
     #### Disable for the moment because tracking geometry explodes for R4
     ### from MuonConfig.MuonTruthAlgsConfig import MuonTruthAddTrackRecordsAlgCfg
     ### result.merge(MuonTruthAddTrackRecordsAlgCfg(flags))
-    result.merge(TruthSegmentToTruthPartCfg(flags))
+    result.merge(TruthSegmentToTruthPartAssocCfg(flags))
     return result
diff --git a/MuonSpectrometer/MuonPhaseII/MuonPatternRecognition/MuonTruthAlgsR4/src/TrackToTruthPartAssocAlg.cxx b/MuonSpectrometer/MuonPhaseII/MuonPatternRecognition/MuonTruthAlgsR4/src/TrackToTruthPartAssocAlg.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..25fb7a4b048d33d1323b4d1afaa3e1e110768e5c
--- /dev/null
+++ b/MuonSpectrometer/MuonPhaseII/MuonPatternRecognition/MuonTruthAlgsR4/src/TrackToTruthPartAssocAlg.cxx
@@ -0,0 +1,121 @@
+/*
+  Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "TrackToTruthPartAssocAlg.h"
+
+#include "StoreGate/ReadDecorHandleKeyArray.h"
+#include "StoreGate/WriteDecorHandle.h"
+#include "xAODTruth/xAODTruthHelpers.h"
+
+#include <unordered_set>
+namespace {
+    using IdSet_t = std::unordered_set<Identifier>;
+    using TruthLink_t = ElementLink<xAOD::TruthParticleContainer>;
+    using TruthPartWithIds_t = std::tuple<const xAOD::TruthParticle*, IdSet_t>;
+    using IdDecorHandle_t = SG::ReadDecorHandle<xAOD::TruthParticleContainer, std::vector<unsigned long long>>;
+}
+
+namespace MuonR4{
+    StatusCode TrackToTruthPartAssocAlg::initialize() {
+        
+        
+        ATH_CHECK(m_trkKey.initialize());
+        ATH_CHECK(m_originWriteKey.initialize());
+        ATH_CHECK(m_typeWriteKey.initialize());
+        ATH_CHECK(m_linkWriteKey.initialize());
+        ATH_CHECK(m_truthMuonKey.initialize());
+
+        ATH_CHECK(m_idHelperSvc.retrieve());
+        ATH_CHECK(m_edmHelperSvc.retrieve());
+
+        for (const std::string& hitIds  : m_simHitIds) {
+            m_simHitKeys.emplace_back(m_truthMuonKey, hitIds);
+        }
+        ATH_CHECK(m_simHitKeys.initialize());
+        ATH_CHECK(m_truMuOriginKey.initialize());
+        ATH_CHECK(m_truMuTypeKey.initialize());
+        return StatusCode::SUCCESS;
+    }
+    StatusCode TrackToTruthPartAssocAlg::execute(const EventContext& ctx) const {
+        SG::ReadHandle tracks{m_trkKey, ctx};
+        ATH_CHECK(tracks.isPresent());
+
+
+        SG::WriteDecorHandle<xAOD::TrackParticleContainer, int> acc_truthOrigin{m_originWriteKey, ctx};
+        SG::WriteDecorHandle<xAOD::TrackParticleContainer, int> acc_truthType{m_typeWriteKey, ctx};
+        SG::WriteDecorHandle<xAOD::TrackParticleContainer, TruthLink_t> acc_truthLink{m_linkWriteKey, ctx};
+        ///
+        /// Initialize the Identifier decorators
+        std::vector<IdDecorHandle_t> idDecorHandles{};
+        for (const SG::ReadDecorHandleKey<xAOD::TruthParticleContainer>& hitKey : m_simHitKeys) {
+            idDecorHandles.emplace_back(hitKey, ctx);
+        }
+        
+        std::vector<TruthPartWithIds_t> truthWithIds{};
+        ///
+        SG::ReadHandle truthMuonCont{m_truthMuonKey, ctx};
+        ATH_CHECK(truthMuonCont.isPresent());
+        for (const xAOD::TruthParticle* truthMuon : *truthMuonCont) {
+            IdSet_t assocIds{};
+            ATH_MSG_DEBUG("Truth muon: pT:"<<truthMuon->pt()<<" [GeV], eta: "<<truthMuon->eta()<<", phi: "
+                        <<truthMuon->phi()<<", q: "<<truthMuon->charge()<<", truthType: "<<xAOD::TruthHelpers::getParticleTruthType(*truthMuon)
+                        <<", origin: "<<xAOD::TruthHelpers::getParticleTruthOrigin(*truthMuon));
+            for (const IdDecorHandle_t& hitDecor : idDecorHandles) {
+                std::ranges::transform(hitDecor(*truthMuon), std::inserter(assocIds, assocIds.begin()),
+                                [this](unsigned long long rawId) {
+                                    const Identifier id{rawId};
+                                    ATH_MSG_VERBOSE(" --- associated hit id: "<<m_idHelperSvc->toString(id));
+                                    return id; 
+                                });
+            }
+            truthWithIds.emplace_back(std::make_tuple(truthMuon, std::move(assocIds)));
+        }
+
+        for (const xAOD::TrackParticle* trackPart : *tracks){
+            const Trk::Track* track = trackPart->track();
+            if (!track) {
+                ATH_MSG_ERROR("Associated reconstructed track is not available for "<<m_trkKey);
+                return StatusCode::FAILURE;
+            }
+            /// Assemble the track identifiers
+            IdSet_t trackIds{};
+            for (const Trk::TrackStateOnSurface* tsos : *track->trackStateOnSurfaces()) {
+                const Trk::MeasurementBase* meas = tsos->measurementOnTrack();
+                /// Probably scatterer
+                if (!meas) {
+                    continue;
+                }
+                const Identifier measId = m_edmHelperSvc->getIdentifier(*meas);
+                if (!measId.is_valid() || !m_idHelperSvc->isMuon(measId)){
+                    ATH_MSG_VERBOSE("Measurement is not a muon one");
+                    continue;
+                }
+                trackIds.insert(measId);
+            }
+            /// Start matching by finding the particle with the largest fraction
+            int bestMatchFrac{-1};
+            const xAOD::TruthParticle* bestMatch{nullptr};
+            for (const auto& [truthPart, truthIds]: truthWithIds) {
+                const int matchedReco = std::ranges::count_if(trackIds,[&truthIds](const Identifier& recoId){
+                                                                return truthIds.count(recoId);
+                                                            });
+                ///  If the particle has no matched hits or it's worse than the best matched
+                if (!matchedReco || matchedReco < bestMatchFrac){
+                    continue;
+                }
+                bestMatchFrac = matchedReco;
+                bestMatch = truthPart;
+            }
+            /// Track could not be matched
+            if (!bestMatch) {
+                continue;
+            }
+            acc_truthOrigin(*trackPart) = xAOD::TruthHelpers::getParticleTruthOrigin(*bestMatch);
+            acc_truthType(*trackPart) = xAOD::TruthHelpers::getParticleTruthType(*bestMatch);
+            const auto bestMatchCont = static_cast<const xAOD::TruthParticleContainer*>(bestMatch->container());
+            acc_truthLink(*trackPart) = TruthLink_t{bestMatchCont, bestMatch->index()};
+        }
+        return StatusCode::SUCCESS;
+    }
+}
\ No newline at end of file
diff --git a/MuonSpectrometer/MuonPhaseII/MuonPatternRecognition/MuonTruthAlgsR4/src/TrackToTruthPartAssocAlg.h b/MuonSpectrometer/MuonPhaseII/MuonPatternRecognition/MuonTruthAlgsR4/src/TrackToTruthPartAssocAlg.h
new file mode 100644
index 0000000000000000000000000000000000000000..c48865f15a178741c0ee4cd4d2d007ac1f2abe6a
--- /dev/null
+++ b/MuonSpectrometer/MuonPhaseII/MuonPatternRecognition/MuonTruthAlgsR4/src/TrackToTruthPartAssocAlg.h
@@ -0,0 +1,64 @@
+/*
+  Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
+*/
+#ifndef MUONTRUTHSEGMENTMAKER_TrackToTruthPartAssocAlg_H
+#define MUONTRUTHSEGMENTMAKER_TrackToTruthPartAssocAlg_H
+
+#include <AthenaBaseComps/AthReentrantAlgorithm.h>
+
+#include <xAODTruth/TruthParticleContainer.h>
+#include <xAODTracking/TrackParticleContainer.h>
+
+#include <StoreGate/ReadHandleKey.h>
+#include <StoreGate/ReadDecorHandleKeyArray.h>
+#include <StoreGate/WriteDecorHandleKey.h>
+
+#include <MuonIdHelpers/IMuonIdHelperSvc.h>
+#include <MuonRecHelperTools/IMuonEDMHelperSvc.h>
+
+namespace MuonR4{
+    /** @brief The TrackToTruthPartAssocAlg matches the reconstructed tracks to truth muons.
+     *         As baseline, the 
+     */
+    class TrackToTruthPartAssocAlg : public AthReentrantAlgorithm {
+        public:
+            using AthReentrantAlgorithm::AthReentrantAlgorithm;
+
+            StatusCode initialize() override final;
+            StatusCode execute(const EventContext& ctx) const override final;
+        private:
+            
+        
+            /** @brief IdHelperSvc to decode the Identifiers */
+            ServiceHandle<Muon::IMuonIdHelperSvc> m_idHelperSvc{this, "IdHelperSvc",  "Muon::MuonIdHelperSvc/MuonIdHelperSvc"};
+            /** @brief Helper service to handle the Identifiers of measurements */
+            ServiceHandle<Muon::IMuonEDMHelperSvc> m_edmHelperSvc{this, "EdmHelperSvc", "Muon::MuonEDMHelperSvc/MuonEDMHelperSvc"};
+        
+
+            using TrkReadKey_t = SG::ReadHandleKey<xAOD::TrackParticleContainer>;
+            using TrkWriteDecorKey_t = SG::WriteDecorHandleKey<xAOD::TrackParticleContainer>;
+
+            TrkReadKey_t m_trkKey{this, "TrackCollection", "MSTrks"};
+            /** @brief Decorations to be written to the TrackParticle truthOrigin/truthType/truthParticleLink */
+            TrkWriteDecorKey_t m_originWriteKey{this, "TruthOriginWriteKey", m_trkKey, "truthOrigin"};
+            TrkWriteDecorKey_t m_typeWriteKey{this, "TruthTypeWriteKey", m_trkKey, "truthType"};
+            TrkWriteDecorKey_t m_linkWriteKey{this, "TruthLinkWriteKey", m_trkKey, "truthParticleLink"};
+            /** @brief Input truth particle keys */
+            using TruthReadKey_t = SG::ReadHandleKey<xAOD::TruthParticleContainer>;
+            using TruthDecor_t = SG::ReadDecorHandleKey<xAOD::TruthParticleContainer>;
+            using TruthDecorArr_t =  SG::ReadDecorHandleKeyArray<xAOD::TruthParticleContainer>;
+
+            TruthReadKey_t m_truthMuonKey{this, "TruthMuonKey", "MuonTruthParticles"};
+
+            /** @brief List of simHit id decorations to read from the truth particle */
+            Gaudi::Property<std::vector<std::string>> m_simHitIds{this, "SimHitIds", {}};
+            /** @brief Declaration of the dependency on the simHit decorations */
+            TruthDecorArr_t m_simHitKeys{this, "TruthSimHitIdKeys", {}};
+
+            TruthDecor_t m_truMuOriginKey{this, "TruthMuonOriginKey", m_truthMuonKey, "truthOrigin"};
+            TruthDecor_t m_truMuTypeKey{this, "TruthMuonTypeKey", m_truthMuonKey, "truthType"};
+
+    };
+}
+
+#endif
\ No newline at end of file
diff --git a/MuonSpectrometer/MuonPhaseII/MuonPatternRecognition/MuonTruthAlgsR4/src/components/MuonTruthAlgsR4_entries.cxx b/MuonSpectrometer/MuonPhaseII/MuonPatternRecognition/MuonTruthAlgsR4/src/components/MuonTruthAlgsR4_entries.cxx
index 885077f6681a11e41c1cfa2a9f8e2695b2b6e08e..f2c29c1b03c6cc2da1d3b051d9b91606df8e4ee3 100644
--- a/MuonSpectrometer/MuonPhaseII/MuonPatternRecognition/MuonTruthAlgsR4/src/components/MuonTruthAlgsR4_entries.cxx
+++ b/MuonSpectrometer/MuonPhaseII/MuonPatternRecognition/MuonTruthAlgsR4/src/components/MuonTruthAlgsR4_entries.cxx
@@ -7,7 +7,9 @@
 #include "../PrepDataToSimHitAssocAlg.h"
 #include "../PrdMultiTruthMaker.h"
 #include "../TruthSegToTruthPartAssocAlg.h"
+#include "../TrackToTruthPartAssocAlg.h"
 DECLARE_COMPONENT(MuonR4::TruthSegmentMaker)
 DECLARE_COMPONENT(MuonR4::PrepDataToSimHitAssocAlg)
 DECLARE_COMPONENT(MuonR4::PrdMultiTruthMaker)
-DECLARE_COMPONENT(MuonR4::TruthSegToTruthPartAssocAlg)
\ No newline at end of file
+DECLARE_COMPONENT(MuonR4::TruthSegToTruthPartAssocAlg)
+DECLARE_COMPONENT(MuonR4::TrackToTruthPartAssocAlg)
\ No newline at end of file
diff --git a/MuonSpectrometer/MuonPhaseII/MuonValidation/MuonPatternRecognitionTest/python/PatternTestConfig.py b/MuonSpectrometer/MuonPhaseII/MuonValidation/MuonPatternRecognitionTest/python/PatternTestConfig.py
index 6a7f04aac97643ce42141e517c4365b0df6281df..5b4ef7765ff868e63c70f54b35419e509e1a81fe 100644
--- a/MuonSpectrometer/MuonPhaseII/MuonValidation/MuonPatternRecognitionTest/python/PatternTestConfig.py
+++ b/MuonSpectrometer/MuonPhaseII/MuonValidation/MuonPatternRecognitionTest/python/PatternTestConfig.py
@@ -161,22 +161,11 @@ def TrackTruthMatchCfg(flags):
     result = ComponentAccumulator()
     if not flags.Input.isMC:
         return result
-    from MuonConfig.MuonTruthAlgsConfig import MuonDetailedTrackTruthMakerCfg
+    from MuonTruthAlgsR4.MuonTruthAlgsConfig import TrackToTruthPartAssocCfg
     
-    track_cols = ["MuonTracksR4", "MuonTracksFromHoughR4", "MuonSpectrometerTracks"]
     track_colstp = ["MuonSpectrometerTrackParticlesR4", "MuonSpectrometerTrackParticlesFromHoughR4", "MuonSpectrometerTrackParticles"]
 
-    for trk in track_cols:
-        result.merge(MuonDetailedTrackTruthMakerCfg(flags, name=f"MuonDetailedTruthTrkMaker{trk}",
-                                                        TrackCollectionNames=[trk]))
+    for trk in track_colstp:
+        result.merge(TrackToTruthPartAssocCfg(flags, name=f"TrackToTruth{trk}",  TrackCollection=trk))
 
-        from MuonConfig.MuonTruthAlgsConfig import MuonTruthAssociationAlgCfg
-        result.merge(MuonTruthAssociationAlgCfg(flags, TrackContainers=[]))
-        for i in range(len(track_cols)):
-            from TrkConfig.TrkTruthAlgsConfig import TrackTruthSelectorCfg, TrackParticleTruthAlgCfg
-            result.merge(TrackTruthSelectorCfg(flags, tracks=track_cols[i]))
-
-            result.merge(TrackParticleTruthAlgCfg(flags, tracks=track_cols[i],
-                                                  TrackParticleName=track_colstp[i]))
     return result
-