diff --git a/InnerDetector/InDetEventCnv/InDetSimEventAthenaPool/src/SiHitCollectionCnv.cxx b/InnerDetector/InDetEventCnv/InDetSimEventAthenaPool/src/SiHitCollectionCnv.cxx
index df859cb03742249af2f6c4985a74b06d04eed654..2f1f4113c26166bfddd1d26a9158e904b0364ca5 100644
--- a/InnerDetector/InDetEventCnv/InDetSimEventAthenaPool/src/SiHitCollectionCnv.cxx
+++ b/InnerDetector/InDetEventCnv/InDetSimEventAthenaPool/src/SiHitCollectionCnv.cxx
@@ -1,10 +1,11 @@
 /*
-  Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
 */
 
 #include "InDetSimEventTPCnv/InDetHits/SiHitCollectionCnv_p1.h"
 #include "InDetSimEventTPCnv/InDetHits/SiHitCollectionCnv_p2.h"
 #include "InDetSimEventTPCnv/InDetHits/SiHitCollectionCnv_p3.h"
+#include "InDetSimEventTPCnv/InDetHits/SiHitCollectionCnv_p4.h"
 #include "InDetSimEventTPCnv/InDetHits/SiHit_p1.h"
 #include "InDetSimEventTPCnv/InDetHits/SiHit_p2.h"
 #include "SiHitCollectionCnv.h"
@@ -23,10 +24,12 @@ SiHitCollection* SiHitCollectionCnv::createTransient() {
     SiHitCollectionCnv_p1   converter_p1;
     SiHitCollectionCnv_p2   converter_p2;
     SiHitCollectionCnv_p3   converter_p3;
+    SiHitCollectionCnv_p4   converter_p4;
 
     static const pool::Guid   p1_guid("36D1FF8E-5734-4A93-A133-F286CF47DB72");
     static const pool::Guid   p2_guid("BD1469C5-C904-40B8-82B9-43D25888D884");
     static const pool::Guid   p3_guid("59E13FDA-2799-4362-8423-44D57F08734D");
+    static const pool::Guid   p4_guid("018E1E2B-6C61-752E-b26D-6ABB05FBD4D9");
     static const pool::Guid   old_guid("1EC39DA3-14F9-4901-88C7-F6909B064574");
 
     SiHitCollection       *trans_cont(nullptr);
@@ -42,6 +45,10 @@ SiHitCollection* SiHitCollectionCnv::createTransient() {
       std::unique_ptr< SiHitCollection_p2 >   col_vect( this->poolReadObject< SiHitCollection_p2 >() );
       trans_cont = converter_p2.createTransient( col_vect.get(), mlog );
     }
+    else if( this->compareClassGuid(p4_guid)) { // version p4
+      std::unique_ptr< SiHitCollection_p4 >   col_vect( this->poolReadObject< SiHitCollection_p4 >() );
+      trans_cont = converter_p4.createTransient( col_vect.get(), mlog );
+    }
     else if( this->compareClassGuid(old_guid)) {
       // old version from before TP separation, just return it
       AthenaHitsVector<SiHit>* oldColl = this->poolReadObject< AthenaHitsVector<SiHit> >();
diff --git a/InnerDetector/InDetEventCnv/InDetSimEventAthenaPool/src/SiHitCollectionCnv.h b/InnerDetector/InDetEventCnv/InDetSimEventAthenaPool/src/SiHitCollectionCnv.h
index 77cfdc51b24bbd43edbf4d319c9966f6b083668f..1550e058d13f6815bec398236cb38de41ff96162 100644
--- a/InnerDetector/InDetEventCnv/InDetSimEventAthenaPool/src/SiHitCollectionCnv.h
+++ b/InnerDetector/InDetEventCnv/InDetSimEventAthenaPool/src/SiHitCollectionCnv.h
@@ -1,9 +1,9 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
 */
 
-#ifndef SIHITCOLLECTIONCNV
-#define SIHITCOLLECTIONCNV
+#ifndef INDETSIMEVENTATHENAPOOL_SIHITCOLLECTIONCNV_H
+#define INDETSIMEVENTATHENAPOOL_SIHITCOLLECTIONCNV_H
 
 #include "InDetSimEvent/SiHitCollection.h"
 #include "InDetSimEventTPCnv/InDetHits/SiHitCollection_p1.h"
@@ -12,6 +12,8 @@
 #include "InDetSimEventTPCnv/InDetHits/SiHitCollectionCnv_p2.h"
 #include "InDetSimEventTPCnv/InDetHits/SiHitCollection_p3.h"
 #include "InDetSimEventTPCnv/InDetHits/SiHitCollectionCnv_p3.h"
+#include "InDetSimEventTPCnv/InDetHits/SiHitCollection_p4.h"
+#include "InDetSimEventTPCnv/InDetHits/SiHitCollectionCnv_p4.h"
 #include "AthenaPoolCnvSvc/T_AthenaPoolCustomCnv.h"
 // Gaudi
 #include "GaudiKernel/MsgStream.h"
@@ -30,4 +32,4 @@ protected:
 };
 
 
-#endif
+#endif // INDETSIMEVENTATHENAPOOL_SIHITCOLLECTIONCNV_H
diff --git a/InnerDetector/InDetEventCnv/InDetSimEventAthenaPool/src/TRTUncompressedHitCollectionCnv.cxx b/InnerDetector/InDetEventCnv/InDetSimEventAthenaPool/src/TRTUncompressedHitCollectionCnv.cxx
index ce47987b342f817193a29ac112daa0e28990513b..52fb406f6dd20a79aa16cbce4ea5416a789d4f27 100755
--- a/InnerDetector/InDetEventCnv/InDetSimEventAthenaPool/src/TRTUncompressedHitCollectionCnv.cxx
+++ b/InnerDetector/InDetEventCnv/InDetSimEventAthenaPool/src/TRTUncompressedHitCollectionCnv.cxx
@@ -1,11 +1,12 @@
 /*
-  Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
 */
 
 #include "InDetSimEventTPCnv/InDetHits/TRT_HitCollectionCnv_p1.h"
 #include "InDetSimEventTPCnv/InDetHits/TRT_HitCollectionCnv_p2.h"
 #include "InDetSimEventTPCnv/InDetHits/TRT_HitCollectionCnv_p3.h"
 #include "InDetSimEventTPCnv/InDetHits/TRT_HitCollectionCnv_p4.h"
+#include "InDetSimEventTPCnv/InDetHits/TRT_HitCollectionCnv_p5.h"
 #include "TRTUncompressedHitCollectionCnv.h"
 #include "InDetSimEventTPCnv/InDetHits/TRT_Hit_p1.h"
 #include "InDetSimEventTPCnv/InDetHits/TRT_Hit_p2.h"
@@ -25,10 +26,12 @@ TRTUncompressedHitCollection* TRTUncompressedHitCollectionCnv::createTransient()
     TRT_HitCollectionCnv_p2   converter_p2;
     TRT_HitCollectionCnv_p3   converter_p3;
     TRT_HitCollectionCnv_p4   converter_p4;
+    TRT_HitCollectionCnv_p5  converter_p5;
     static const pool::Guid   p1_guid("6688E934-157E-421A-B6D1-A35FC8BD651C");
     static const pool::Guid   p2_guid("473FF621-3466-4D87-9469-4780A6A77023");
     static const pool::Guid   p3_guid("FB5F5BFC-43E5-44E1-B79C-C330C1480E2E");
     static const pool::Guid   p4_guid("73BECF03-4C45-491E-A973-A1C4402AD018");
+    static const pool::Guid   p5_guid("018E1E3D-8B69-7BDF-B1E9-D5D09F3CF750");
     static const pool::Guid   old_guid("35722E01-C4E3-420E-8A7E-E375C5E7989D");
 
 
@@ -49,6 +52,10 @@ TRTUncompressedHitCollection* TRTUncompressedHitCollectionCnv::createTransient()
         std::unique_ptr< TRT_HitCollection_p3 >   col_vect( this->poolReadObject< TRT_HitCollection_p3 >() );
         trans_cont = converter_p3.createTransient( col_vect.get(), mlog );
     }
+    else if( this->compareClassGuid(p5_guid)) {
+        std::unique_ptr< TRT_HitCollection_p5 >   col_vect( this->poolReadObject< TRT_HitCollection_p5 >() );
+        trans_cont = converter_p5.createTransient( col_vect.get(), mlog );
+    }
     else if( this->compareClassGuid(old_guid)) {
       // old version from before TP separation - convert to new transient format
       AthenaHitsVector<TRTUncompressedHit>* oldColl = this->poolReadObject< AthenaHitsVector<TRTUncompressedHit> >();
diff --git a/InnerDetector/InDetEventCnv/InDetSimEventAthenaPool/src/TRTUncompressedHitCollectionCnv.h b/InnerDetector/InDetEventCnv/InDetSimEventAthenaPool/src/TRTUncompressedHitCollectionCnv.h
index 47405d750d6e9572adcacbbd22b10b1437c7ac58..2808a45664a478eaa65319ba335a27d15b5d4637 100755
--- a/InnerDetector/InDetEventCnv/InDetSimEventAthenaPool/src/TRTUncompressedHitCollectionCnv.h
+++ b/InnerDetector/InDetEventCnv/InDetSimEventAthenaPool/src/TRTUncompressedHitCollectionCnv.h
@@ -1,9 +1,9 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
 */
 
-#ifndef TRT_HITCOLLECTIONCNV
-#define TRT_HITCOLLECTIONCNV
+#ifndef INDETSIMEVENTATHENAPOOL_TRT_HITCOLLECTIONCNV_H
+#define INDETSIMEVENTATHENAPOOL_TRT_HITCOLLECTIONCNV_H
 
 #include "InDetSimEvent/TRTUncompressedHitCollection.h"
 #include "InDetSimEventTPCnv/InDetHits/TRT_HitCollection_p1.h"
@@ -14,6 +14,8 @@
 #include "InDetSimEventTPCnv/InDetHits/TRT_HitCollectionCnv_p3.h"
 #include "InDetSimEventTPCnv/InDetHits/TRT_HitCollection_p4.h"
 #include "InDetSimEventTPCnv/InDetHits/TRT_HitCollectionCnv_p4.h"
+#include "InDetSimEventTPCnv/InDetHits/TRT_HitCollection_p5.h"
+#include "InDetSimEventTPCnv/InDetHits/TRT_HitCollectionCnv_p5.h"
 #include "AthenaPoolCnvSvc/T_AthenaPoolCustomCnv.h"
 // Gaudi
 #include "GaudiKernel/MsgStream.h"
@@ -27,6 +29,8 @@
 //typedef TRT_HitCollectionCnv_p3  TRT_HitCollectionCnv_PERS;
 typedef TRT_HitCollection_p4     TRT_HitCollection_PERS;
 typedef TRT_HitCollectionCnv_p4  TRT_HitCollectionCnv_PERS;
+//typedef TRT_HitCollection_p5     TRT_HitCollection_PERS;
+//typedef TRT_HitCollectionCnv_p5  TRT_HitCollectionCnv_PERS;
 
 class TRTUncompressedHitCollectionCnv  : public T_AthenaPoolCustomCnv<TRTUncompressedHitCollection, TRT_HitCollection_PERS > {
   friend class CnvFactory<TRTUncompressedHitCollectionCnv>;
@@ -38,4 +42,4 @@ protected:
   TRTUncompressedHitCollection*       createTransient ();
 };
 
-#endif
+#endif // INDETSIMEVENTATHENAPOOL_TRT_HITCOLLECTIONCNV_H
diff --git a/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/CMakeLists.txt b/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/CMakeLists.txt
index 8c1b4032d3ccf7f58e17092b3081d0564227a512..78cc23de482682c1d0a5c2d54d78ceeaa7b33919 100644
--- a/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/CMakeLists.txt
+++ b/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+# Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
 
 # Declare the package name:
 atlas_subdir( InDetSimEventTPCnv )
@@ -24,34 +24,44 @@ atlas_add_dictionary( InDetSimEventTPCnvDict
 atlas_add_test( SiHitCnv_p1_test
                 SOURCES
                 test/SiHitCnv_p1_test.cxx
-                LINK_LIBRARIES AtlasHepMCLib GeneratorObjectsTPCnv InDetSimEventTPCnv TestTools )
+                LINK_LIBRARIES AtlasHepMCLib GeneratorObjectsTPCnv InDetSimEventTPCnv TestTools TruthUtils )
 
 atlas_add_test( SiHitCollectionCnv_p2_test
                 SOURCES
                 test/SiHitCollectionCnv_p2_test.cxx
-                LINK_LIBRARIES AtlasHepMCLib GeneratorObjectsTPCnv InDetSimEventTPCnv TestTools )
+                LINK_LIBRARIES AtlasHepMCLib GeneratorObjectsTPCnv InDetSimEventTPCnv TestTools TruthUtils )
 
 atlas_add_test( SiHitCollectionCnv_p3_test
                 SOURCES
                 test/SiHitCollectionCnv_p3_test.cxx
-                LINK_LIBRARIES AtlasHepMCLib GeneratorObjectsTPCnv InDetSimEventTPCnv TestTools )
+                LINK_LIBRARIES AtlasHepMCLib GeneratorObjectsTPCnv InDetSimEventTPCnv TestTools TruthUtils )
+
+atlas_add_test( SiHitCollectionCnv_p4_test
+                SOURCES
+                test/SiHitCollectionCnv_p4_test.cxx
+                LINK_LIBRARIES AtlasHepMCLib GeneratorObjectsTPCnv InDetSimEventTPCnv TestTools TruthUtils )
 
 atlas_add_test( TRT_HitCnv_p1_test
                 SOURCES
                 test/TRT_HitCnv_p1_test.cxx
-                LINK_LIBRARIES AtlasHepMCLib GeneratorObjectsTPCnv InDetSimEventTPCnv TestTools )
+                LINK_LIBRARIES AtlasHepMCLib GeneratorObjectsTPCnv InDetSimEventTPCnv TestTools TruthUtils )
 
 atlas_add_test( TRT_HitCollectionCnv_p2_test
                 SOURCES
                 test/TRT_HitCollectionCnv_p2_test.cxx
-                LINK_LIBRARIES AtlasHepMCLib GeneratorObjectsTPCnv InDetSimEventTPCnv TestTools )
+                LINK_LIBRARIES AtlasHepMCLib GeneratorObjectsTPCnv InDetSimEventTPCnv TestTools TruthUtils )
 
 atlas_add_test( TRT_HitCollectionCnv_p3_test
                 SOURCES
                 test/TRT_HitCollectionCnv_p3_test.cxx
-                LINK_LIBRARIES AtlasHepMCLib GeneratorObjectsTPCnv InDetSimEventTPCnv TestTools )
+                LINK_LIBRARIES AtlasHepMCLib GeneratorObjectsTPCnv InDetSimEventTPCnv TestTools TruthUtils )
 
 atlas_add_test( TRT_HitCollectionCnv_p4_test
                 SOURCES
                 test/TRT_HitCollectionCnv_p4_test.cxx
-                LINK_LIBRARIES AtlasHepMCLib GeneratorObjectsTPCnv InDetSimEventTPCnv TestTools )
+                LINK_LIBRARIES AtlasHepMCLib GeneratorObjectsTPCnv InDetSimEventTPCnv TestTools TruthUtils )
+
+atlas_add_test( TRT_HitCollectionCnv_p5_test
+                SOURCES
+                test/TRT_HitCollectionCnv_p5_test.cxx
+                LINK_LIBRARIES AtlasHepMCLib GeneratorObjectsTPCnv InDetSimEventTPCnv TestTools TruthUtils )
diff --git a/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/InDetSimEventTPCnv/InDetHits/SiHitCollectionCnv_p4.h b/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/InDetSimEventTPCnv/InDetHits/SiHitCollectionCnv_p4.h
new file mode 100755
index 0000000000000000000000000000000000000000..5530106c483bed2896c0cfdc4f34ac6af5f4946f
--- /dev/null
+++ b/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/InDetSimEventTPCnv/InDetHits/SiHitCollectionCnv_p4.h
@@ -0,0 +1,37 @@
+/*
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef INDETSIMEVENTTPCNV_SIHITCOLLECTIONCNV_P4_H
+#define INDETSIMEVENTTPCNV_SIHITCOLLECTIONCNV_P4_H
+
+#include "AthenaPoolCnvSvc/T_AthenaPoolTPConverter.h"
+#include "InDetSimEvent/SiHitCollection.h"
+#include "SiHitCollection_p4.h"
+
+
+class SiHitCollectionCnv_p4 : public T_AthenaPoolTPCnvBase<SiHitCollection, SiHitCollection_p4>
+{
+ public:
+
+  SiHitCollectionCnv_p4()  {};
+
+  virtual SiHitCollection* createTransient(const SiHitCollection_p4* persObj, MsgStream &log);
+
+  virtual void persToTrans(const SiHitCollection_p4* persCont,
+                           SiHitCollection* transCont,
+                           MsgStream &log) ;
+  virtual void transToPers(const SiHitCollection* transCont,
+                           SiHitCollection_p4* persCont,
+                           MsgStream &log) ;
+
+ private:
+
+  static const double m_persEneUnit;
+  static const double m_persLenUnit;
+  static const double m_persAngUnit;
+  static const double m_2bHalfMaximum;
+  static const int m_2bMaximum;
+};
+
+#endif // INDETSIMEVENTTPCNV_SIHITCOLLECTIONCNV_P4_H
diff --git a/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/InDetSimEventTPCnv/InDetHits/SiHitCollection_p4.h b/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/InDetSimEventTPCnv/InDetHits/SiHitCollection_p4.h
new file mode 100755
index 0000000000000000000000000000000000000000..a65d215f88a7772834fb1cf64444320d63154b71
--- /dev/null
+++ b/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/InDetSimEventTPCnv/InDetHits/SiHitCollection_p4.h
@@ -0,0 +1,50 @@
+/*
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef INDETSIMEVENTTPCNV_SIHITCOLLECTION_P4_H
+#define INDETSIMEVENTTPCNV_SIHITCOLLECTION_P4_H
+
+#include <vector>
+#include <string>
+
+class SiHitCollection_p4
+{
+ public:
+/// Default constructor
+  SiHitCollection_p4 ();
+  //private:
+
+  std::vector<float>          m_hit1_meanTime;   //  1 element per string
+  std::vector<float>          m_hit1_x0;         //
+  std::vector<float>          m_hit1_y0;         //
+  std::vector<float>          m_hit1_z0;         //
+  std::vector<float>          m_hit1_theta;      //
+  std::vector<float>          m_hit1_phi;        //
+  std::vector<unsigned short> m_nHits;           //
+
+  std::vector<unsigned short> m_hitEne_2b;       //  1 element per hit
+  std::vector<unsigned short> m_hitLength_2b;    //
+
+  std::vector<unsigned short> m_dTheta;          //  1 element per hit except for first hit in string
+  std::vector<unsigned short> m_dPhi;            //
+
+  std::vector<float>          m_hitEne_4b;       //  1 element per hit with  m_hitEne_2b[i] == 2**16
+
+  std::vector<float>          m_hitLength_4b;    //  1 element per hit with  m_hitLength_2b[i] == 2**16
+
+  std::vector<unsigned long>  m_truthID;
+  std::vector<unsigned short> m_mcEvtIndex;
+  std::vector<unsigned short> m_nTruthID;
+
+  std::vector<unsigned long>  m_id;
+  std::vector<unsigned short> m_nId;
+};
+
+
+// inlines
+
+inline
+SiHitCollection_p4::SiHitCollection_p4 () {}
+
+#endif // INDETSIMEVENTTPCNV_SIHITCOLLECTION_P4_H
diff --git a/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/InDetSimEventTPCnv/InDetHits/TRT_HitCollectionCnv_p5.h b/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/InDetSimEventTPCnv/InDetHits/TRT_HitCollectionCnv_p5.h
new file mode 100644
index 0000000000000000000000000000000000000000..4bc40a687e2113aed51325e6915d7ecb99a31445
--- /dev/null
+++ b/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/InDetSimEventTPCnv/InDetHits/TRT_HitCollectionCnv_p5.h
@@ -0,0 +1,29 @@
+/*
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef INDETSIMEVENTTPCNV_TRTHITCOLLECTIONCNV_P5_H
+#define INDETSIMEVENTTPCNV_TRTHITCOLLECTIONCNV_P5_H
+
+#include "InDetSimEvent/TRTUncompressedHitCollection.h"
+#include "AthenaPoolCnvSvc/T_AthenaPoolTPConverter.h"
+#include "TRT_HitCollection_p5.h"
+
+
+class TRT_HitCollectionCnv_p5 : public T_AthenaPoolTPCnvBase<TRTUncompressedHitCollection, TRT_HitCollection_p5>
+{
+ public:
+
+  TRT_HitCollectionCnv_p5() {};
+
+  virtual TRTUncompressedHitCollection* createTransient(const TRT_HitCollection_p5* persObj, MsgStream &log);
+
+  virtual void persToTrans(const TRT_HitCollection_p5* persCont,
+                           TRTUncompressedHitCollection* transCont,
+                           MsgStream &log) ;
+  virtual void transToPers(const TRTUncompressedHitCollection* transCont,
+                           TRT_HitCollection_p5* persCont,
+                           MsgStream &log) ;
+};
+
+#endif // INDETSIMEVENTTPCNV_TRTHITCOLLECTIONCNV_P5_H
diff --git a/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/InDetSimEventTPCnv/InDetHits/TRT_HitCollection_p5.h b/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/InDetSimEventTPCnv/InDetHits/TRT_HitCollection_p5.h
new file mode 100644
index 0000000000000000000000000000000000000000..c5ebb2409c03475d957f05a17425539cd6a624f2
--- /dev/null
+++ b/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/InDetSimEventTPCnv/InDetHits/TRT_HitCollection_p5.h
@@ -0,0 +1,67 @@
+/*
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef INDETSIMEVENTTPCNV_TRTHITCOLLECTION_P5_H
+#define INDETSIMEVENTTPCNV_TRTHITCOLLECTION_P5_H
+
+/*
+   Author: Rob Duxfield <r.duxfield@sheffield.ac.uk> Spring 2008
+   _p3 Integer compression: <Andrew.Beddall@cern.ch> Spring 2009
+   _p4 HepMcParticleLink_p2 <Olivier.Arnaez@cern.ch> Fall 2015
+   _p5 HepMcParticleLink_p3
+   See http://cern.ch/beddall/TRThitCompression/
+*/
+
+#include <vector>
+#include <string>
+
+class TRT_HitCollection_p5
+{
+ public:
+  /// Default constructor
+  TRT_HitCollection_p5 ();
+
+  //private:
+
+  //
+  //  1 element per string (a string resides in one straw; there may be more than one string in a straw)
+  //
+
+  std::vector<unsigned short> m_nHits;       // number of hits in the string (0,1,2 ... ,hundreds).
+  std::vector<unsigned short> m_strawId2b;   // straw id | 24-bit
+  std::vector<unsigned char>  m_strawId1b;   // straw id | integer.
+  std::vector<unsigned char>  m_startR;      // hit start radius (0, 2 mm) [not always stored].
+  std::vector<unsigned char>  m_startPhi;    // hit start phi (-pi, pi).
+  std::vector<unsigned char>  m_startZ;      // hit start z (-365, +365 mm), and 1-bit startRflag.
+
+  //
+  //  1 element per hit, there are typically 1 or 2 hits per string, but can be hundreds!
+  //
+
+  std::vector<unsigned short> m_kinEne;      // short float, kinematic energy of the particle causing the hit.
+  std::vector<unsigned short> m_steplength;  // short float, g4 step length; endZ is derived from this.
+  std::vector<unsigned char>  m_endR;        // hit end radius (0, 2 mm) [Not always stored].
+  std::vector<unsigned char>  m_endPhi;      // hit end phi (-pi, pi).
+  std::vector<unsigned short> m_meanTime;    // time to center of the hit, and 1-bit idZsign and 1-bit endRflag.
+  std::vector<float>          m_meanTimeof;  // t >= 75 ns overflow to a float.
+
+  //
+  // much less frequent
+  //
+
+  std::vector<float>          m_hitEne; // energy deposited; *only stored for photons* (m_id=22)
+  std::vector<unsigned short> m_nId;
+  std::vector<unsigned int>   m_truthID;
+  std::vector<unsigned short> m_mcEvtIndex;
+  std::vector<unsigned short> m_nTruthID;
+  std::vector<int>            m_id;     // particle code.
+
+};
+
+// inlines
+
+inline
+TRT_HitCollection_p5::TRT_HitCollection_p5 () {}
+
+#endif // INDETSIMEVENTTPCNV_TRTHITCOLLECTION_P5_H
diff --git a/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/InDetSimEventTPCnv/InDetSimEventTPCnvDict.h b/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/InDetSimEventTPCnv/InDetSimEventTPCnvDict.h
index 45559130382c83f60f0c7b5403a6785c77aeb40c..275645dacfb01f11f05f124b11d34c995dedca6f 100644
--- a/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/InDetSimEventTPCnv/InDetSimEventTPCnvDict.h
+++ b/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/InDetSimEventTPCnv/InDetSimEventTPCnvDict.h
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
 */
 
 #ifndef INDETEVENTTPCNV_INDETSIMEVENTTPCNVDICT_H
@@ -20,6 +20,7 @@
 #include "InDetSimEventTPCnv/InDetHits/SiHitCollection_p1.h"
 #include "InDetSimEventTPCnv/InDetHits/SiHitCollection_p2.h"
 #include "InDetSimEventTPCnv/InDetHits/SiHitCollection_p3.h"
+#include "InDetSimEventTPCnv/InDetHits/SiHitCollection_p4.h"
 #include "InDetSimEventTPCnv/InDetHits/SiHit_p1.h"
 #include "InDetSimEventTPCnv/InDetHits/SiHit_p2.h"
 #include "InDetSimEventTPCnv/InDetHits/TRT_HitCnv_p1.h"
@@ -32,6 +33,7 @@
 #include "InDetSimEventTPCnv/InDetHits/TRT_HitCollection_p2.h"
 #include "InDetSimEventTPCnv/InDetHits/TRT_HitCollection_p3.h"
 #include "InDetSimEventTPCnv/InDetHits/TRT_HitCollection_p4.h"
+#include "InDetSimEventTPCnv/InDetHits/TRT_HitCollection_p5.h"
 #include "InDetSimEventTPCnv/InDetHits/TRT_Hit_p1.h"
 #include "InDetSimEventTPCnv/InDetHits/TRT_Hit_p2.h"
 
diff --git a/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/InDetSimEventTPCnv/selection.xml b/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/InDetSimEventTPCnv/selection.xml
index 9fd46e4c08ce389ad1a833faa3a5cdfe6e456574..e2c1f390911b15a1ff52eda17f6543df3e43529e 100755
--- a/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/InDetSimEventTPCnv/selection.xml
+++ b/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/InDetSimEventTPCnv/selection.xml
@@ -8,6 +8,7 @@
     <class name="SiHitCollection_p1" id="36D1FF8E-5734-4A93-A133-F286CF47DB72" />
     <class name="SiHitCollection_p2" id="BD1469C5-C904-40B8-82B9-43D25888D884" />
     <class name="SiHitCollection_p3" id="59E13FDA-2799-4362-8423-44D57F08734D" />
+    <class name="SiHitCollection_p4" id="018E1E2B-6C61-752E-b26D-6ABB05FBD4D9" />
     <class name="TRT_Hit_p1" />
     <class name="std::vector<TRT_Hit_p1>" />
     <class name="TRT_Hit_p2" />
@@ -16,5 +17,6 @@
     <class name="TRT_HitCollection_p2" id="473FF621-3466-4D87-9469-4780A6A77023" />
     <class name="TRT_HitCollection_p3" id="FB5F5BFC-43E5-44E1-B79C-C330C1480E2E" />
     <class name="TRT_HitCollection_p4" id="73BECF03-4C45-491E-A973-A1C4402AD018" />
-     
+    <class name="TRT_HitCollection_p5" id="018E1E3D-8B69-7BDF-B1E9-D5D09F3CF750" />
+
 </lcgdict>
diff --git a/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/share/SiHitCollectionCnv_p4_test.ref b/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/share/SiHitCollectionCnv_p4_test.ref
new file mode 100644
index 0000000000000000000000000000000000000000..ee9824a396e67d03d1e160e1c58bafc36c733971
--- /dev/null
+++ b/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/share/SiHitCollectionCnv_p4_test.ref
@@ -0,0 +1,8 @@
+ApplicationMgr       INFO Application Manager Configured successfully
+EventLoopMgr      WARNING Unable to locate service "EventSelector"
+EventLoopMgr      WARNING No events will be processed from external input.
+HistogramPersis...WARNING Histograms saving not required.
+ApplicationMgr       INFO Application Manager Initialized successfully
+ApplicationMgr Ready
+test1
+HepMcParticleLink    INFO find_proxy: Using TruthEvent as McEventCollection key for this job
diff --git a/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/share/TRT_HitCollectionCnv_p5_test.ref b/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/share/TRT_HitCollectionCnv_p5_test.ref
new file mode 100644
index 0000000000000000000000000000000000000000..4a7c11977bb121447c32603da54a83a704e8898b
--- /dev/null
+++ b/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/share/TRT_HitCollectionCnv_p5_test.ref
@@ -0,0 +1,8 @@
+ApplicationMgr       INFO Application Manager Configured successfully
+EventLoopMgr      WARNING Unable to locate service "EventSelector" 
+EventLoopMgr      WARNING No events will be processed from external input.
+HistogramPersis...WARNING Histograms saving not required.
+ApplicationMgr       INFO Application Manager Initialized successfully
+ApplicationMgr Ready
+test1
+HepMcParticleLink    INFO find_proxy: Using TruthEvent as McEventCollection key for this job 
diff --git a/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/src/InDetHits/SiHitCollectionCnv_p4.cxx b/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/src/InDetHits/SiHitCollectionCnv_p4.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..84451240e235d4a4b908ed7db25cebcc3fe948d6
--- /dev/null
+++ b/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/src/InDetHits/SiHitCollectionCnv_p4.cxx
@@ -0,0 +1,364 @@
+/*
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "InDetSimEvent/SiHit.h"
+#include "InDetSimEvent/SiHitCollection.h"
+#include "InDetSimEventTPCnv/InDetHits/SiHitCollection_p4.h"
+#include "InDetSimEventTPCnv/InDetHits/SiHitCollectionCnv_p4.h"
+#include "GeneratorObjects/HepMcParticleLink.h"
+
+#include <cmath>
+
+//CLHEP
+#include "CLHEP/Geometry/Point3D.h"
+// Gaudi
+#include "GaudiKernel/MsgStream.h"
+#include "GaudiKernel/ThreadLocalContext.h"
+
+// Athena
+#include "AthenaKernel/ExtendedEventContext.h"
+#include "StoreGate/StoreGateSvc.h"
+
+//  * * *  stolen from eflowRec  * * *  //
+inline double phicorr(double a)
+{
+  if (a <= -M_PI)
+    {
+      return a+(2*M_PI*floor(-(a-M_PI)/(2*M_PI)));
+    }
+  else if (a > M_PI)
+    {
+      return a-(2*M_PI*floor((a+M_PI)/(2*M_PI)));
+    }
+  else
+    {
+      return a;
+    }
+}
+
+//  * * *  stolen from eflowRec  * * *  //
+inline double cycle(double a, double b)
+{
+  double del = b-a;
+  if (del > M_PI)
+    {
+      return a+2.0*M_PI;
+    }
+  else if (del < -M_PI)
+    {
+      return a-2.0*M_PI;
+    }
+  else
+    {
+      return a;
+    }
+}
+
+
+const double SiHitCollectionCnv_p4::m_persEneUnit = 1.0e-5;
+const double SiHitCollectionCnv_p4::m_persLenUnit = 1.0e-5;
+const double SiHitCollectionCnv_p4::m_persAngUnit = 1.0e-5;
+const double SiHitCollectionCnv_p4::m_2bHalfMaximum = pow(2.0, 15.0);
+const int SiHitCollectionCnv_p4::m_2bMaximum = (unsigned short)(-1);
+
+
+void SiHitCollectionCnv_p4::transToPers(const SiHitCollection* transCont, SiHitCollection_p4* persCont, MsgStream &log)
+{
+  // Finds hits belonging to a "string" (in which the end point of one hit is the same as the start point of the next) and
+  // persistifies the end point of each hit plus the start point of the first hit in each string.
+  //
+  // Further compression is achieved by optimising the storage of the position vectors:- start (x,y,z) and (theta,phi) of
+  // first hit are stored as floats, (delta_theta,delta_phi) relative to the fisrst hit are stored as 2 byte numbers and
+  // used to specify the hit direction. All hit lengths are stored as 2 byte numbers.
+  //
+  // Additional savings are achieved by storing the energy loss for each hit as a 2 byte number and only storing the mean
+  // time of the first hit per string.
+  //
+  // See http://indico.cern.ch/getFile.py/access?contribId=11&resId=2&materialId=slides&confId=30893 for more info.
+
+  static const double dRcut = 1.0e-7;
+  static const double dTcut = 1.0;
+
+  const EventContext& ctx = Gaudi::Hive::currentContext();
+  const IProxyDict* proxy = Atlas::getExtendedEventContext(ctx).proxy();
+  const HepMcParticleLink * lastLink=nullptr;
+  int lastId = -1;
+  double stringFirstTheta = 0.0;
+  double stringFirstPhi = 0.0;
+  double lastT = 0.0;
+  double persSumE = 0.0;
+  double transSumE = 0.0;
+  unsigned int idx = 0;
+  unsigned int endTruthID = 0;
+  unsigned int endId = 0;
+  unsigned int endHit = 0;
+  HepGeom::Point3D<double> lastTransEnd(0.0, 0.0, 0.0);
+  HepGeom::Point3D<double> lastPersEnd(0.0, 0.0, 0.0);
+
+  for (SiHitCollection::const_iterator it = transCont->begin(); it != transCont->end(); ++it) {
+
+    SiHitCollection::const_iterator siHit = it;
+
+
+    if ( !lastLink || (siHit->particleLink() != *lastLink) || (idx-endTruthID)==USHRT_MAX ) {
+
+      // store barcode, eventIndex and McEventCollection once for set of consecutive hits with same barcode
+
+      lastLink = &(siHit->particleLink());
+      persCont->m_truthID.push_back(lastLink->id());
+      unsigned short index{0};
+      const HepMcParticleLink::index_type position =
+        HepMcParticleLink::getEventPositionInCollection(lastLink->eventIndex(),
+                                                        proxy).at(0);
+      if (position!=0) {
+        index = lastLink->eventIndex();
+        if(lastLink->eventIndex()!=static_cast<HepMcParticleLink::index_type>(index)) {
+          log << MSG::WARNING << "Attempting to persistify an eventIndex larger than max unsigned short!" << endmsg;
+        }
+      }
+      persCont->m_mcEvtIndex.push_back(index);
+
+      if (idx > 0) {
+        persCont->m_nTruthID.push_back(idx - endTruthID);
+        endTruthID = idx;
+      }
+    }
+
+    if ( ( (int)siHit->identify() != lastId ) || (idx-endId)==USHRT_MAX) {
+
+      // store id once for set of consecutive hits with same barcode
+
+      lastId = siHit->identify();
+      persCont->m_id.push_back(lastId);
+
+      if (idx > 0) {
+        persCont->m_nId.push_back(idx - endId);
+        endId = idx;
+      }
+    }
+
+    HepGeom::Point3D<double> st = siHit->localStartPosition();
+    HepGeom::Point3D<double> en = siHit->localEndPosition();
+
+    const double dx = st.x() - lastTransEnd.x();
+    const double dy = st.y() - lastTransEnd.y();
+    const double dz = st.z() - lastTransEnd.z();
+    const double t = siHit->meanTime();
+
+    const double dRLast = sqrt(dx * dx + dy * dy + dz * dz);  // dR between end of previous hit and start of current one
+    const double dTLast = fabs(t - lastT);
+
+    CLHEP::Hep3Vector direction(0.0, 0.0, 0.0);
+    double theta = 0.0;
+    double phi = 0.0;
+    bool startNewString = (dRLast >= dRcut || dTLast >= dTcut || (idx - endHit) == USHRT_MAX);
+
+    if (!startNewString) {
+
+      // hit is part of existing string
+
+      direction = CLHEP::Hep3Vector( en.x() - lastPersEnd.x(), en.y() - lastPersEnd.y(), en.z() - lastPersEnd.z() );
+
+      theta = direction.theta();
+      phi = phicorr( direction.phi() );
+
+      const int dTheta_2b = (int)( (theta - stringFirstTheta) / m_persAngUnit + m_2bHalfMaximum + 0.5 );
+      const int dPhi_2b = (int)( (cycle(phi, stringFirstPhi) - stringFirstPhi) / m_persAngUnit + m_2bHalfMaximum + 0.5 );
+
+      if ( dTheta_2b < m_2bMaximum && dTheta_2b >= 0 && dPhi_2b < m_2bMaximum && dPhi_2b >= 0) {
+        persCont->m_dTheta.push_back(dTheta_2b);
+        persCont->m_dPhi.push_back(dPhi_2b);
+        theta = stringFirstTheta + ( (double)dTheta_2b - m_2bHalfMaximum ) * m_persAngUnit;
+        phi = stringFirstPhi + ( (double)dPhi_2b - m_2bHalfMaximum ) * m_persAngUnit;
+        phi = phicorr(phi);
+      }
+      else {
+        startNewString = true;
+      }
+    }
+
+    if (startNewString) {
+
+      // begin new hit string
+
+      direction = CLHEP::Hep3Vector( en.x() - st.x(), en.y() - st.y(), en.z() - st.z() );
+
+      theta = direction.theta();
+      phi = phicorr( direction.phi() );
+
+      persCont->m_hit1_meanTime.push_back(t);
+      persCont->m_hit1_x0.push_back(st.x());
+      persCont->m_hit1_y0.push_back(st.y());
+      persCont->m_hit1_z0.push_back(st.z());
+      persCont->m_hit1_theta.push_back(theta);
+      persCont->m_hit1_phi.push_back(phi);
+
+      lastPersEnd = HepGeom::Point3D<double>(st.x(), st.y(), st.z());
+
+      stringFirstTheta = theta;
+      stringFirstPhi = phi;
+
+      if (idx > 0) {
+        persCont->m_nHits.push_back(idx - endHit);
+        endHit = idx;
+      }
+    }
+
+    lastTransEnd = HepGeom::Point3D<double>(en.x(), en.y(), en.z());
+    transSumE += siHit->energyLoss();
+
+    const int eneLoss_2b = (int)((transSumE - persSumE) / m_persEneUnit + 0.5);  // calculated to allow recovery sum over
+                                                                                 // whole hit string to chosen precision
+
+    const int hitLength_2b = (int)(direction.mag() / m_persLenUnit + 0.5);  // calculated to give the correct position to
+                                                                            // the chosen precision, NOT the length of the
+                                                                            // hit (small difference in practice).
+    double eneLoss = 0.0;
+
+    if (eneLoss_2b >= m_2bMaximum) {
+      eneLoss = siHit->energyLoss();
+      persCont->m_hitEne_2b.push_back(m_2bMaximum);
+      persCont->m_hitEne_4b.push_back(eneLoss);
+    }
+    else {
+      eneLoss = eneLoss_2b * m_persEneUnit;
+      persCont->m_hitEne_2b.push_back(eneLoss_2b);
+    }
+
+    double length = 0.0;
+
+    if (hitLength_2b >= m_2bMaximum) {
+      length = direction.mag();
+      persCont->m_hitLength_2b.push_back(m_2bMaximum);
+      persCont->m_hitLength_4b.push_back(direction.mag());
+    }
+    else {
+      length = hitLength_2b * m_persLenUnit;
+      persCont->m_hitLength_2b.push_back(hitLength_2b);
+    }
+
+    CLHEP::Hep3Vector persDir(length, 0.0, 0.0);
+    persDir.setTheta(theta);
+    persDir.setPhi(phi);
+
+    lastPersEnd = (CLHEP::Hep3Vector)lastPersEnd + persDir;
+    persSumE += eneLoss;
+    lastT = t;
+
+    ++idx;
+  }
+
+  persCont->m_nTruthID.push_back(idx - endTruthID);
+  persCont->m_nId.push_back(idx - endId);
+  persCont->m_nHits.push_back(idx - endHit);
+#ifdef ENABLE_SANITY_CHECKS
+  // Sanity check
+  const unsigned int init(0);
+  const unsigned int transContSize = transCont->size();
+  if (std::accumulate(persCont->m_nTruthID.begin(), persCont->m_nTruthID.end(), init)!=transContSize) {
+    log << MSG::ERROR << "transToPers: sum of entries of persCont->m_nTruthID (" << std::accumulate(persCont->m_nTruthID.begin(), persCont->m_nTruthID.end(), init) << ") does not match transient container size = " << transContSize << endmsg;
+  }
+  if (std::accumulate(persCont->m_nId.begin(), persCont->m_nId.end(), init)!=transContSize) {
+    log << MSG::ERROR << "transToPers: sum of entries of persCont->m_nId (" << std::accumulate(persCont->m_nId.begin(), persCont->m_nId.end(), init) << ") does not match transient container size = " << transContSize << endmsg;
+  }
+  if (std::accumulate(persCont->m_nHits.begin(), persCont->m_nHits.end(), init)!=transContSize) {
+    log << MSG::ERROR << "transToPers: sum of entries of persCont->m_nHits (" << std::accumulate(persCont->m_nHits.begin(), persCont->m_nHits.end(), init) << ") does not match transient container size = " << transContSize << endmsg;
+  }
+#endif
+}
+
+
+SiHitCollection* SiHitCollectionCnv_p4::createTransient(const SiHitCollection_p4* persObj, MsgStream &log) {
+  std::unique_ptr<SiHitCollection> trans(std::make_unique<SiHitCollection>("DefaultCollectionName",persObj->m_nHits.size()));
+  persToTrans(persObj, trans.get(), log);
+  return(trans.release());
+}
+
+
+#ifdef ENABLE_SANITY_CHECKS
+void SiHitCollectionCnv_p4::persToTrans(const SiHitCollection_p4* persCont, SiHitCollection* transCont, MsgStream &log)
+#else
+void SiHitCollectionCnv_p4::persToTrans(const SiHitCollection_p4* persCont, SiHitCollection* transCont, MsgStream &/*log*/)
+#endif
+{
+  const EventContext& ctx = Gaudi::Hive::currentContext();
+#ifdef ENABLE_SANITY_CHECKS
+  // Sanity check
+  const unsigned int transContSize = persCont->m_hitEne_2b.size(); // this vector has one entry per transient SiHit, so its size can be used as a proxy for the transient Container size
+  const unsigned int init(0);
+  if (std::accumulate(persCont->m_nTruthID.begin(), persCont->m_nTruthID.end(), init)!=transContSize) {
+    log << MSG::ERROR << "persToTrans: sum of entries of persCont->m_nTruthID (" << std::accumulate(persCont->m_nTruthID.begin(), persCont->m_nTruthID.end(), init) << ") does not match transient container size = " << transContSize << endmsg;
+  }
+  if (std::accumulate(persCont->m_nId.begin(), persCont->m_nId.end(), init)!=transContSize) {
+    log << MSG::ERROR << "persToTrans: sum of entries of persCont->m_nId (" << std::accumulate(persCont->m_nId.begin(), persCont->m_nId.end(), init) << ") does not match transient container size = " << transContSize << endmsg;
+  }
+  if (std::accumulate(persCont->m_nHits.begin(), persCont->m_nHits.end(), init)!=transContSize) {
+    log << MSG::ERROR << "persToTrans: sum of entries of persCont->m_nHits (" << std::accumulate(persCont->m_nHits.begin(), persCont->m_nHits.end(), init) << ") does not match transient container size = " << transContSize << endmsg;
+  }
+#endif
+
+  unsigned int hitCount = 0;
+  unsigned int angleCount = 0;
+  unsigned int idxTruthID = 0;
+  unsigned int idxId = 0;
+  unsigned int idxEne4b = 0;
+  unsigned int idxLen4b = 0;
+  unsigned int endHit = 0;
+  unsigned int endTruthID = 0;
+  unsigned int endId = 0;
+
+  for (unsigned int i = 0; i < persCont->m_nHits.size(); i++) {
+
+    if (persCont->m_nHits[i]) {
+
+      const unsigned int start = endHit;
+      endHit += persCont->m_nHits[i];
+
+      const double t0 = persCont->m_hit1_meanTime[i];
+      const double theta0 = persCont->m_hit1_theta[i];
+      const double phi0 = persCont->m_hit1_phi[i];
+      HepGeom::Point3D<double> endLast(persCont->m_hit1_x0[i], persCont->m_hit1_y0[i], persCont->m_hit1_z0[i]);
+
+      for (unsigned int j = start; j < endHit; j++) {
+
+        if (j >= endTruthID + persCont->m_nTruthID[idxTruthID])
+          endTruthID += persCont->m_nTruthID[idxTruthID++];
+
+        if (j >= endId + persCont->m_nId[idxId])
+          endId += persCont->m_nId[idxId++];
+
+        const double eneLoss_2b = persCont->m_hitEne_2b[hitCount];
+        const double hitLength_2b = persCont->m_hitLength_2b[hitCount];
+
+        const double eneLoss = (eneLoss_2b < m_2bMaximum) ? eneLoss_2b * m_persEneUnit : persCont->m_hitEne_4b[idxEne4b++];
+        const double length = (hitLength_2b < m_2bMaximum) ? hitLength_2b * m_persLenUnit : persCont->m_hitLength_4b[idxLen4b++];
+
+        const double dTheta = (j > start) ? ((double)persCont->m_dTheta[angleCount] - m_2bHalfMaximum) * m_persAngUnit : 0.0;
+        const double dPhi = (j > start) ? ((double)persCont->m_dPhi[angleCount] - m_2bHalfMaximum) * m_persAngUnit : 0.0;
+
+        const double meanTime = t0;
+        const double theta = theta0 + dTheta;
+        const double phi = phicorr(phi0 + dPhi);
+
+        CLHEP::Hep3Vector r(length, 0.0, 0.0);
+        r.setTheta(theta);
+        r.setPhi(phi);
+
+        HepGeom::Point3D<double> endThis( endLast + r );
+
+        HepMcParticleLink::PositionFlag flag = HepMcParticleLink::IS_EVENTNUM;
+        if (persCont->m_mcEvtIndex[idxTruthID] == 0) {
+          flag = HepMcParticleLink::IS_POSITION;
+        }
+        HepMcParticleLink partLink( persCont->m_truthID[idxTruthID], persCont->m_mcEvtIndex[idxTruthID], flag, HepMcParticleLink::IS_ID, ctx  );
+        transCont->Emplace( endLast, endThis, eneLoss, meanTime, partLink, persCont->m_id[idxId] );
+
+        endLast = endThis;
+
+        ++hitCount;
+        if (j > start) ++angleCount;
+      }
+    }
+  }
+}
diff --git a/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/src/InDetHits/TRT_HitCollectionCnv_p5.cxx b/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/src/InDetHits/TRT_HitCollectionCnv_p5.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..afc7fb0db4d9c523cd11e9fa7789c3b6597c63ad
--- /dev/null
+++ b/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/src/InDetHits/TRT_HitCollectionCnv_p5.cxx
@@ -0,0 +1,516 @@
+/*
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "InDetSimEvent/TRTUncompressedHit.h"
+#include "InDetSimEvent/TRTUncompressedHitCollection.h"
+#include "InDetSimEventTPCnv/InDetHits/TRT_HitCollection_p5.h"
+#include "InDetSimEventTPCnv/InDetHits/TRT_HitCollectionCnv_p5.h"
+
+#include <cmath>
+
+// CLHEP
+#include "CLHEP/Geometry/Point3D.h"
+#include "CLHEP/Units/SystemOfUnits.h"
+
+// Gaudi
+#include "GaudiKernel/MsgStream.h"
+#include "GaudiKernel/ThreadLocalContext.h"
+
+// Athena
+#include "AthenaKernel/ExtendedEventContext.h"
+#include "StoreGate/StoreGateSvc.h"
+
+// Transient(Geant) to Persistent(Disk)
+void TRT_HitCollectionCnv_p5::transToPers(const TRTUncompressedHitCollection* transCont, TRT_HitCollection_p5* persCont, MsgStream &log)
+{
+
+  /*
+    Spring 2009
+    Andrew Beddall - lossy TRT G4hit compression [p3]
+
+    In p1, p2 versions, GEANT hits are persistified on disk as floats.
+    In the p3 version, floats are compressed to "integers"/"short-floats" before persistifying.
+    In the p5 version, HepMcParticleLink_p2 can identify the event index and collection.
+    The saving is about 75%; see http://cern.ch/beddall/TRThitCompression/
+
+    Spring 2008
+    Rob Duxfield - lossless TRT G4hit compression [p2]
+
+    Finds hits belonging to a "string" (in which the end point of one hit is
+    the same as the start point of the next) and persistifies the end point
+    of each hit plus the start point of the first hit in each string.
+  */
+
+  //  The original units from the hit simulation are indicated in comments;
+  //  they are all in CLHEP units except for hitEne which is in keV.
+  //  I sometimes make use of CLHEP scales *CLHEP::mm and *CLHEP::ns (both=1) for clarity (I hope!).
+  //  See also https://twiki.cern.ch/twiki/bin/view/Atlas/TrtSoftware#Production_of_Hits
+
+  static const double dRcut = 1.0e-7*CLHEP::mm;
+  static const double dTcut = 1.0*CLHEP::ns; // redundant?
+
+  //    if (log.level() <= MSG::DEBUG) log << MSG::DEBUG << "In TRT_HitCollectionCnv_p5::transToPers()" << endmsg;
+
+  const EventContext& ctx = Gaudi::Hive::currentContext();
+  const IProxyDict* proxy = Atlas::getExtendedEventContext(ctx).proxy();
+  const HepMcParticleLink * lastLink=nullptr;
+  int lastId = -1;
+  double lastT = 0.0*CLHEP::ns;
+  unsigned int idx = 0;
+  unsigned int endTruthID = 0;
+  unsigned int endId = 0;
+  unsigned int endHit = 0;
+  HepGeom::Point3D<double> lastEnd(0.0, 0.0, 0.0); // mm
+
+  for (TRTUncompressedHitCollection::const_iterator it = transCont->begin(); it != transCont->end(); ++it) {
+
+    TRTUncompressedHitCollection::const_iterator trtHit = it;
+
+    if ( !lastLink || (trtHit->particleLink() != *lastLink)  ||  (idx - endTruthID > 65500)) {   // max unsigned short =  65535;
+      // store truth id once for set of consecutive hits with same truth id
+      lastLink = &(trtHit->particleLink());
+      persCont->m_truthID.push_back(lastLink->id());
+      unsigned short index{0};
+      const HepMcParticleLink::index_type position =
+        HepMcParticleLink::getEventPositionInCollection(lastLink->eventIndex(),
+                                                        proxy).at(0);
+      if (position!=0) {
+        index = lastLink->eventIndex();
+        if(lastLink->eventIndex()!=static_cast<HepMcParticleLink::index_type>(index)) {
+          log << MSG::WARNING << "Attempting to persistify an eventIndex larger than max unsigned short!" << endmsg;
+        }
+      }
+      persCont->m_mcEvtIndex.push_back(index);
+
+      if ( idx > 0 ) {
+        persCont->m_nTruthID.push_back(idx - endTruthID);
+        endTruthID = idx;
+      }
+    }
+
+    if ( (int)trtHit->GetParticleEncoding() != lastId || idx - endId >  65500) { // max unsigned short =  65535;
+      // store id once for set of consecutive hits with same id
+      lastId = trtHit->GetParticleEncoding();
+      persCont->m_id.push_back(lastId);
+      if ( idx > 0 ) {
+        persCont->m_nId.push_back(idx - endId);
+        endId = idx;
+      }
+    }
+
+    const HepGeom::Point3D<double> hitStart(trtHit->GetPreStepX(), trtHit->GetPreStepY(), trtHit->GetPreStepZ()); // mm
+
+    const double meanTime = trtHit->GetGlobalTime(); // ns  // Time of flight from the I.P. to the center of the hit.
+    const double dTLast = std::abs(meanTime - lastT);      // |d(meantime)| between the previous hit and the current one.
+    const double dRLast = lastEnd.distance(hitStart);  // Distance between end of previous hit and start of current one;
+    // this is zero if the hit is a continuation of the same particle in the same straw.
+
+    // Begin a new string if the current and previous hits are disconnected;
+    // it looks like dTcut is redundant (but not sure about this).
+    if ( dRLast >= dRcut || dTLast >= dTcut ) {
+
+      // if ( dRLast < dRcut) std::cout << "AJBdTLastTriggeredNewString " << dRLast << " " << dTLast << std::endl;
+
+      ////////////////////
+      // new hit string //
+      ////////////////////
+
+      //
+      // Persistify string *strawId* using 24 bits.
+      // Assumes 0 <= strawId <= 16,777,215 (strawId appears to be < 4,000,000)
+      //
+      const unsigned int strawId = trtHit->GetHitID();
+      persCont->m_strawId1b.push_back(  (unsigned char)(strawId % 256) ); //  8 bits
+      persCont->m_strawId2b.push_back( (unsigned short)(strawId / 256) ); // 16 bits
+      if ( strawId>16777215 )
+        log << MSG::WARNING << "TRT_HitCollectionCnv: strawId > 2^24-1 cannot be persistified correctly! " << endmsg;
+
+      //
+      // Persistify string start radius using 1 bit (istartRflag) or 8 bits (startR)
+      // Note that the smallest value of R is the wire radius (0.0155 mm)
+      //
+      // R will be flagged as 2 mm if it is within 0.1 um of the straw wall => max error = 0.1 um,
+      // otherwise compress with 8 bits => max error = 3.9 um (0.078 ns), RMS error = 1.1 um (0.022 ns)
+      //
+      const double startR = sqrt( hitStart.x()*hitStart.x() + hitStart.y()*hitStart.y() ); // mm
+      unsigned short istartRflag;
+      if ( startR > 1.9999*CLHEP::mm ) {
+        istartRflag=1; // persistify as a 1-bit flag
+      }
+      else {
+        istartRflag=0; // compress to 8 bits with a span of 2 mm
+        persCont->m_startR.push_back( (unsigned char)(startR/(2.0*CLHEP::mm)*256.0) );
+      }
+
+      //
+      // Persistify string *startPhi* using 8 bits (min=-pi, max=+pi)
+      // Max. error = 12 mrad (< 24 um, 0.48 ns); RMS error = 7 mrad (< 14 um, 0.28 ns)
+      //
+      const double startPhi = atan2( hitStart.y(), hitStart.x() ); // returns range -pi to +pi rad
+      persCont->m_startPhi.push_back( (unsigned char)( (startPhi+M_PI)/(2.0*M_PI)*256.0 ) );
+
+      //
+      // Persistify *startZ* using a 4 bits (min = -365 mm, max= +365 mm)
+      // Max. error = 25 mm (25e-3/(0.75c) = 0.111 ns * 2 reflect = 0.222 ns)
+      // RMS  error = 14 mm (14e-3/(0.75c) = 0.062 ns * 2 reflect = 0.124 ns)
+      // Also the 1-bit *istartRflag* is packed into this variable.
+      //
+      // Note:
+      // In the digi code we need to allow for something like 22.5 mm outside straw.
+      // Also because we have short straws,
+      // short straws are about < +-180 mm, long straws are about < +-350 mm
+      // The following compressions can give a large "out of straw" value;
+      // *don't* use these: (2.0), 32.0, 128.0, 256.0.
+
+      unsigned char istartZ = (unsigned char)( (hitStart.z()+365.0*CLHEP::mm)/(730.0*CLHEP::mm)*16.0 );
+      istartZ = (istartZ << 1) | istartRflag;
+      persCont->m_startZ.push_back( istartZ );
+
+      if ( idx > 0 ) {
+        persCont->m_nHits.push_back( idx - endHit );
+        endHit = idx;
+      }
+      /*
+      // Validation output
+      std::cout.precision(15);
+      std::cout << "AJBTtoPstrawId "    << strawId      << std::endl;
+      std::cout << "AJBTtoPstartR "     << startR       << std::endl;
+      std::cout << "AJBTtoPstartPhi "   << startPhi     << std::endl;
+      std::cout << "AJBTtoPstartX "     << hitStart.x() << std::endl;
+      std::cout << "AJBTtoPstartY "     << hitStart.y() << std::endl;
+      std::cout << "AJBTtoPstartZ "     << hitStart.z() << std::endl;
+      */
+    } // end of "begin new hit string"
+
+    //////////////////////////
+    // Now for the end hits //
+    //////////////////////////
+
+    const HepGeom::Point3D<double> hitEnd(trtHit->GetPostStepX(), trtHit->GetPostStepY(), trtHit->GetPostStepZ()); // mm
+    const HepGeom::Point3D<double> hitLength = (hitEnd - hitStart);
+
+    //
+    // Here both *kinEne* (kinetic energy of the particle causing the hit) and
+    // *steplength* (g4hit length) are persistified using a 15-bit "short float"
+    // (9 bit unsigned mantissa, 6 bit unsigned exponent).
+    // This stores values in the range 0.51*2^0 = 0.51 to 1.00*2^63 = 9.2e18.
+    // I enforce the limits 1.0 and 9.0e18; see below.
+    // Max relative error = 0.0010, RMS = 0.0004
+    //
+    // Notes:
+    //
+    //  - G4 gives kinEne in MeV; I sometimes see values ~ 1e-7 MeV (100 meV) [float round-off?]
+    //    So I multiply by 1e9 and store in units of meV => range 1.0 meV to 9.0e18 meV (9000 TeV!)
+    //  - About 1 in 10000 hits have steplength ~ 1e-7 mm [float round-off?]
+    //    so again I multiply by 1e9 and store in units of pm => range 1.0 pm to 9.0e18 pm (9000 km)
+    //  - The mantissa has maximum 9 bits, the exponent has maximum 6 bits,
+    //    Note: a rare condition causes an 10-bit mantissa (mantissa=512).
+    //
+    double kinEne = trtHit->GetKineticEnergy()    * 1.0e9;  // nano Mev = meV.
+    double steplength = hitLength.distance() * 1.0e9;  // nano mm  = pm.
+    if ( kinEne     < 1.0 )        kinEne=1.0;         // Keep  the value
+    if ( steplength < 1.0 )    steplength=1.0;         // well within the
+    if ( kinEne     > 9.0e18 )     kinEne=9.0e18;      // range  of   the
+    if ( steplength > 9.0e18 ) steplength=9.0e18;      // short    float.
+    const unsigned int kexponent = (unsigned int)ceil(log10(kinEne)/0.30102999566398);
+    const unsigned int sexponent = (unsigned int)ceil(log10(steplength)/0.30102999566398);
+    const unsigned int kmantissa = (unsigned int)(kinEne/pow(2.0,kexponent)*1024) - 512;
+    const unsigned int smantissa = (unsigned int)(steplength/pow(2.0,sexponent)*1024) - 512;
+    persCont->m_kinEne.push_back(     (kmantissa << 6) | kexponent );
+    persCont->m_steplength.push_back( (smantissa << 6) | sexponent );
+
+    //
+    // Persistify hit end radius using 1 bit (iendRflag) or 8 bits (endR).
+    // Note that the smallest value of R is the wire radius (0.0155 mm)
+    //
+    // R will be flagged as 2 mm if it is within 0.1 um of the straw wall => max error = 0.1 um,
+    // otherwise compress with 8 bits. The errors are as for startR, but can increased greatly
+    // after steplength preservation in PtoT.
+    //
+    const double endR = sqrt( hitEnd.x()*hitEnd.x() + hitEnd.y()*hitEnd.y() ); // mm
+    unsigned short iendRflag;
+    if ( endR > 1.9999*CLHEP::mm ) {
+      iendRflag=1; // persistify as a 1-bit flag
+    }
+    else {
+      iendRflag=0; // compress to 8 bits with a span of 2 mm
+      persCont->m_endR.push_back( (unsigned char)(endR/(2.0*CLHEP::mm)*256.0) );
+    }
+
+    //
+    // Persistify string *endPhi* using 8 bits (min=-pi, max=+pi)
+    // The errors are as for startPhi, but are very different after steplength
+    // preservation in PtoT.
+    //
+    const double endPhi = atan2( hitEnd.y(), hitEnd.x() ); // returns range -pi to +pi rad
+    persCont->m_endPhi.push_back( (unsigned char)( (endPhi+M_PI)/(2.0*M_PI)*256.0 ) );
+
+    //
+    // Persistify hit *meanTime* using 10 bits (min=0.,span=75 ns)
+    // with float overflow for meanTime >= 75ns (the tail of the distribution).
+    // Max. error = 0.037 ns; RMS error = 0.021 ns.
+    // Also the 1-bit *iendRflag* and 1-bit *idZsign* are packed into this variable.
+    //
+    unsigned short idZsign = (hitLength.z()>0.0) ? 1 : 0; // flag the sign of dZ
+    unsigned short imeanTime = ( meanTime < 75.0*CLHEP::ns ) ? (unsigned short)(meanTime/(75.0*CLHEP::ns)*1024.0) : 1023;
+    if ( imeanTime == 1023 ) persCont->m_meanTimeof.push_back( (float)meanTime ); // "overflow flag"
+    imeanTime = (imeanTime << 2) | (idZsign << 1) | iendRflag;
+    persCont->m_meanTime.push_back( imeanTime );
+
+    //
+    // Persistify hit *hitEne* (the energy deposited by the hit in keV) using a float but only for photons
+    // (relatively very few of these). Digitisation does not use hitEne for charged particles.
+    //
+    if ( lastId == 22 ||
+         (int)(abs(lastId)/100000) == 41 ||
+         (int)(abs(lastId)/10000000) == 1
+         ) persCont->m_hitEne.push_back( (float)(trtHit->GetEnergyDeposit()) );  // keV
+
+    lastEnd = hitEnd;
+    lastT = meanTime;
+    ++idx;
+    /*
+    // Validation output
+    std::cout.precision(15);
+    std::cout << "AJBTtoPendR "     << endR                  << std::endl;
+    std::cout << "AJBTtoPendPhi "   << endPhi                << std::endl;
+    std::cout << "AJBTtoPendX "     << hitEnd.x()            << std::endl;
+    std::cout << "AJBTtoPendY "     << hitEnd.y()            << std::endl;
+    std::cout << "AJBTtoPendZ "     << hitEnd.z()            << std::endl;
+    std::cout << "AJBTtoPmeanTime " << meanTime              << std::endl;
+    std::cout << "AJBTtoPkinEne "   << trtHit->GetKineticEnergy() << std::endl;
+    std::cout << "AJBTtoPhitEne "   << trtHit->GetEnergyDeposit() << std::endl;
+    std::cout << "AJBTtoPsteplength " << hitLength.distance() << std::endl;
+    */
+  }
+
+  persCont->m_nTruthID.push_back(idx - endTruthID);
+  persCont->m_nId.push_back(idx - endId);
+  persCont->m_nHits.push_back( idx - endHit );
+
+} // transToPers
+
+
+// Create Transient
+TRTUncompressedHitCollection* TRT_HitCollectionCnv_p5::createTransient(const TRT_HitCollection_p5* persObj, MsgStream &log) {
+  std::unique_ptr<TRTUncompressedHitCollection> trans(std::make_unique<TRTUncompressedHitCollection>("DefaultCollectionName",persObj->m_nHits.size()));
+  persToTrans(persObj, trans.get(), log);
+  return(trans.release());
+} //createTransient
+
+
+// Persistent(Disk) to Transient
+void TRT_HitCollectionCnv_p5::persToTrans(const TRT_HitCollection_p5* persCont, TRTUncompressedHitCollection* transCont, MsgStream& /*log*/)
+{
+  const EventContext& ctx = Gaudi::Hive::currentContext();
+
+  //    if (log.level() <= MSG::DEBUG) log << MSG::DEBUG << "In TRT_HitCollectionCnv_p5::persToTrans()" << endmsg;
+
+  // some values are read less than once per hit, these need counters.
+  unsigned int meanTimeofCount=0, startRCount=0, endRCount=0, hitEneCount=0;
+  unsigned int idxTruthID=0, idxId=0, endHit=0, endTruthID=0, endId=0;
+
+  //
+  // loop over strings - index [i]
+  //
+
+  for ( unsigned int i = 0; i < persCont->m_nHits.size(); i++ ) {
+
+    if ( persCont->m_nHits[i] ) { // at least one hit in the string
+
+      const unsigned int startHit = endHit;
+      endHit += persCont->m_nHits[i];
+
+      //
+      // string strawId
+      //
+      const unsigned int i1 = persCont->m_strawId1b[i]; //  8 bits
+      const unsigned int i2 = persCont->m_strawId2b[i]; // 16 bits
+      const unsigned int strawId = i2*256+i1;           // => 24 bits (0 to 16,777,215)
+
+      //
+      // string startPhi
+      //
+      const unsigned int istartPhi = persCont->m_startPhi[i];         // 8 bits
+      const double startPhi = -M_PI + (istartPhi+0.5)*2.0*M_PI/256.0; // rad (min = -pi, max = +pi)
+
+      //
+      // string startZ
+      //
+      const unsigned int istartZ = persCont->m_startZ[i] >> 1; // 4 bits
+      double startZ = -365.0*CLHEP::mm + (istartZ+0.5)*730.0*CLHEP::mm/16.0; // (min = -365 mm, max = +365 mm)
+
+      //
+      // start Rflag
+      //
+      const unsigned int istartRflag = persCont->m_startZ[i] & 1; // 1 bit
+
+      //
+      // string startR
+      //
+      double startR;
+      if ( istartRflag == 1 ) {
+        startR = 2.0*CLHEP::mm; // 1 bit
+      }
+      else {
+        const unsigned int istartR = persCont->m_startR[startRCount++]; // 8 bits
+        startR = (istartR+0.5)*2.0*CLHEP::mm/256.0;                            // (range 0 - 2 mm)
+        if ( startR < 0.0155*CLHEP::mm ) startR = 0.0155*CLHEP::mm;                   // The wire radius
+      }
+
+      //
+      // string startX, startY (derived from R,Phi)
+      //
+      double startX = startR*cos(startPhi);
+      double startY = startR*sin(startPhi);
+      /*
+      // Validation output
+      std::cout.precision(15);
+      std::cout << "AJBPtoTstrawId "    << strawId              << std::endl;
+      std::cout << "AJBPtoTstartR "     << startR               << std::endl;
+      std::cout << "AJBPtoTstartPhi "   << startPhi             << std::endl;
+      std::cout << "AJBPtoTstartX "     << startX               << std::endl;
+      std::cout << "AJBPtoTstartY "     << startY               << std::endl;
+      std::cout << "AJBPtoTstartZ "     << startZ               << std::endl;
+      std::cout << "AJBPtoTnHits "      << persCont->m_nHits[i] << std::endl;
+      */
+      //
+      // loop over end hits in the string - index [j]
+      //
+
+      for ( unsigned int j = startHit; j < endHit; j++ ) {
+
+        if ( j >= endTruthID + persCont->m_nTruthID[idxTruthID] ) endTruthID += persCont->m_nTruthID[idxTruthID++];
+        if ( j >= endId + persCont->m_nId[idxId] ) endId += persCont->m_nId[idxId++];
+
+        //
+        // hit meanTime
+        //
+        const unsigned int imeanTime = persCont->m_meanTime[j] >> 2; // 10 bits
+        double meanTime = (imeanTime+0.5)*75.0*CLHEP::ns/1024.0;            // (min = 0.0 ns, max = 75.0 ns)
+        if ( imeanTime == 1023 ) meanTime = (double)persCont->m_meanTimeof[meanTimeofCount++]; // ns, 32-bit float overflow
+
+        //
+        // dZ sign
+        //
+        const unsigned int idZsign = (persCont->m_meanTime[j] >> 1 ) & 1; // 1 bit
+
+        //
+        // endR flag
+        //
+        const unsigned int iendRflag =  persCont->m_meanTime[j] & 1;         // 1 bit
+
+        //
+        // hit energy deposited in keV (only relevant for photons) 32-bit float
+        //
+        const double hitEne = ( persCont->m_id[idxId] == 22 ||
+                                (int)(abs(persCont->m_id[idxId])/100000) == 41 ||
+                                (int)(abs(persCont->m_id[idxId])/10000000) == 1
+                                ) ? (double)persCont->m_hitEne[hitEneCount++] : 0.0;
+
+        //
+        // hit endPhi (can be modified later during "steplength preservation")
+        //
+        const unsigned int iendPhi =  persCont->m_endPhi[j];  // 8 bits
+        double endPhi = -M_PI + (iendPhi+0.5)*2.0*M_PI/256.0; // rad (min = -pi, max = +pi)
+
+        //
+        // string endR (can be modified later during "steplength preservation")
+        //
+        double endR;
+        if ( iendRflag==1 ) {
+          endR = 2.0*CLHEP::mm;  // 1 bit
+        }
+        else {
+          const unsigned int iendR = persCont->m_endR[endRCount++];
+          endR = (iendR+0.5)*2.0*CLHEP::mm/256.0;          // 8 bits
+          if ( endR < 0.0155*CLHEP::mm ) endR = 0.0155*CLHEP::mm; // the wire radius
+        }
+
+        //
+        // hit endX, endY (derived from R,Phi)
+        //
+        double endX = endR*cos(endPhi); // can be modified later during "steplength preservation"
+        double endY = endR*sin(endPhi); // can be modified later during "steplength preservation"
+
+        // Save the (o)riginal endX, endY values for the next hit start because
+        // they might get shrunk to fit the g4 steplength of the current hit.
+        double endXo = endX;
+        double endYo = endY;
+
+        //
+        // g4 step length of the hit, m_steplength, and
+        // kinetic energy of the hit, m_kinEne, are both 15-bit short floats.
+        // Note: a rare condition causes a 16-bit short float (mantissa=512).
+        //
+        const int kmantissa = persCont->m_kinEne[j]     >> 6;   // 9 bits (expected)
+        const int smantissa = persCont->m_steplength[j] >> 6;
+        const int kexponent = persCont->m_kinEne[j]     & 0x3F; // 6 bits
+        const int sexponent = persCont->m_steplength[j] & 0x3F;
+        const double kinEne = (kmantissa+512.5)/1024 * pow(2.0,kexponent) / 1.0e9; // MeV
+        double g4steplength = (smantissa+512.5)/1024 * pow(2.0,sexponent) / 1.0e9; // mm
+        if ( idZsign==0 ) g4steplength = -g4steplength;
+
+        //
+        // Preserving the steplength of the hit by setting endZ or shrinking dX,dY.
+        //
+        double dX = endX-startX;
+        double dY = endY-startY;
+        double dZ;
+        double dXY2 = dX*dX+dY*dY;
+        double dL2 = g4steplength*g4steplength;
+        if ( dL2 > dXY2 ) {         // define dZ such that steplength = g4steplength
+          dZ = sqrt(dL2-dXY2);
+          if (g4steplength<0.0) dZ=-dZ;
+        }
+        else {    // dL2 < dXY2   // shrink dX,dY such that dXY = g4steplength
+          dX = dX * sqrt(dL2/dXY2); // this includes the cases where dL2=0!
+          dY = dY * sqrt(dL2/dXY2);
+          dZ = 0.0*CLHEP::mm;
+          endX = startX + dX;
+          endY = startY + dY;
+          //endR = sqrt( endX*endX + endY*endY ); // for validation information
+          //endPhi = atan2(endY,endX);            // for validation information
+        }
+        double endZ = startZ + dZ;
+        //dX = endX-startX; // for validation information
+        //dY = endY-startY; // for validation information
+        /*
+        // Validation output
+        std::cout.precision(15);
+        std::cout << "AJBPtoTendR "     << endR     << std::endl;
+        std::cout << "AJBPtoTendPhi "   << endPhi   << std::endl;
+        std::cout << "AJBPtoTendX "     << endX     << std::endl;
+        std::cout << "AJBPtoTendY "     << endY     << std::endl;
+        std::cout << "AJBPtoTendZ "     << endZ     << std::endl;
+        std::cout << "AJBPtoTmeanTime " << meanTime << std::endl;
+        std::cout << "AJBPtoTkinEne "   << kinEne   << std::endl;
+        std::cout << "AJBPtoThitEne "   << hitEne   << std::endl;
+        std::cout << "AJBPtoTsteplength " << sqrt(dX*dX+dY*dY+dZ*dZ) << std::endl;
+        */
+        //
+        // Notes:
+        // - All units are CLHEP, except hitEne which is in keV.
+        // - For charged particles kinEne is *zero*!
+        //
+
+        HepMcParticleLink::PositionFlag flag = HepMcParticleLink::IS_EVENTNUM;
+        if (persCont->m_mcEvtIndex[idxTruthID] == 0) {
+          flag = HepMcParticleLink::IS_POSITION;
+        }
+        HepMcParticleLink partLink( persCont->m_truthID[idxTruthID], persCont->m_mcEvtIndex[idxTruthID], flag, HepMcParticleLink::IS_ID, ctx );
+        transCont->Emplace( strawId, partLink, persCont->m_id[idxId],
+                            kinEne, hitEne, startX, startY, startZ,
+                            endX, endY, endZ, meanTime );
+        //
+        // End of this hit becomes the start of the next;
+        // use the original (uncorrected) values for X,Y
+        // but the derived value for Z.
+        //
+        startX = endXo; startY = endYo; startZ = endZ;
+
+      }
+    } // nhits>0
+  } // straw loop
+} // persToTrans
diff --git a/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/test/SiHitCnv_p1_test.cxx b/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/test/SiHitCnv_p1_test.cxx
index 447149aa3dc90e0fd140547aae96dd22245cbef5..1e9386a6cf5bee9bbdf8a0f8bc5735b6bf8f8b67 100644
--- a/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/test/SiHitCnv_p1_test.cxx
+++ b/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/test/SiHitCnv_p1_test.cxx
@@ -16,6 +16,7 @@
 #include <cassert>
 #include <iostream>
 
+#include "TruthUtils/MagicNumbers.h"
 #include "GeneratorObjectsTPCnv/initMcEventCollection.h"
 #include "AtlasHepMC/GenParticle.h"
 #include "AtlasHepMC/GenEvent.h"
@@ -27,6 +28,7 @@ void compare (const HepMcParticleLink& p1,
 {
   assert ( p1.isValid() == p2.isValid() );
   assert ( HepMC::barcode(p1) == HepMC::barcode(p2) );
+  assert ( p1.id() == p2.id() );
   assert ( p1.eventIndex() == p2.eventIndex() );
   assert ( p1.cptr() == p2.cptr() );
   assert ( p1 == p2 );
@@ -63,12 +65,12 @@ void test1 ATLAS_NOT_THREAD_SAFE (std::vector<HepMC::GenParticlePtr>& genPartVec
   std::cout << "test1\n";
   auto particle = genPartVector.at(0);
   // Create HepMcParticleLink outside of leak check.
-  HepMcParticleLink dummyHMPL(HepMC::barcode(particle),particle->parent_event()->event_number(), HepMcParticleLink::IS_EVENTNUM, HepMcParticleLink::IS_BARCODE); // FIXME barcode-based
+  HepMcParticleLink dummyHMPL(HepMC::uniqueID(particle),particle->parent_event()->event_number(), HepMcParticleLink::IS_EVENTNUM, HepMcParticleLink::IS_ID);
   assert(dummyHMPL.cptr()==particle);
   Athena_test::Leakcheck check;
 
   auto pGenParticle = genPartVector.at(0);
-  HepMcParticleLink trkLink(HepMC::barcode(pGenParticle),pGenParticle->parent_event()->event_number(), HepMcParticleLink::IS_EVENTNUM, HepMcParticleLink::IS_BARCODE); // FIXME barcode-based
+  HepMcParticleLink trkLink(HepMC::uniqueID(pGenParticle),pGenParticle->parent_event()->event_number(), HepMcParticleLink::IS_EVENTNUM, HepMcParticleLink::IS_ID);
   SiHit trans1 (HepGeom::Point3D<double> (10.5, 11.5, 12.5),
                 HepGeom::Point3D<double> (13.5, 14.5, 15.5),
                 16.5,
diff --git a/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/test/SiHitCollectionCnv_p2_test.cxx b/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/test/SiHitCollectionCnv_p2_test.cxx
index a6396cf26bb0a9f1b507f175f23a6f0dabb12684..7b4158eabb3ff764a07e8420c3d713312844d47a 100644
--- a/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/test/SiHitCollectionCnv_p2_test.cxx
+++ b/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/test/SiHitCollectionCnv_p2_test.cxx
@@ -16,6 +16,7 @@
 #include <cassert>
 #include <iostream>
 
+#include "TruthUtils/MagicNumbers.h"
 #include "GeneratorObjectsTPCnv/initMcEventCollection.h"
 #include "AtlasHepMC/GenParticle.h"
 #include "AtlasHepMC/GenEvent.h"
@@ -27,6 +28,7 @@ void compare (const HepMcParticleLink& p1,
 {
   assert ( p1.isValid() == p2.isValid() );
   assert ( HepMC::barcode(p1) == HepMC::barcode(p2) );
+  assert ( p1.id() == p2.id() );
   assert ( p1.eventIndex() == p2.eventIndex() );
   assert ( p1.cptr() == p2.cptr() );
   assert ( p1 == p2 );
@@ -73,7 +75,7 @@ void test1 ATLAS_NOT_THREAD_SAFE (std::vector<HepMC::GenParticlePtr>& genPartVec
   std::cout << "test1\n";
   auto particle = genPartVector.at(0);
   // Create HepMcParticleLink outside of leak check.
-  HepMcParticleLink dummyHMPL(HepMC::barcode(particle),particle->parent_event()->event_number(), HepMcParticleLink::IS_EVENTNUM, HepMcParticleLink::IS_BARCODE); // FIXME barcode-based
+  HepMcParticleLink dummyHMPL(HepMC::uniqueID(particle),particle->parent_event()->event_number(), HepMcParticleLink::IS_EVENTNUM, HepMcParticleLink::IS_ID);
   assert(dummyHMPL.cptr()==particle);
   // Create DVL info outside of leak check.
   SiHitCollection dum ("coll");
@@ -82,7 +84,7 @@ void test1 ATLAS_NOT_THREAD_SAFE (std::vector<HepMC::GenParticlePtr>& genPartVec
   SiHitCollection trans1 ("coll");
   for (int i=0; i < 10; i++) {
     auto pGenParticle = genPartVector.at(i);
-    HepMcParticleLink trkLink(HepMC::barcode(pGenParticle),pGenParticle->parent_event()->event_number(), HepMcParticleLink::IS_EVENTNUM, HepMcParticleLink::IS_BARCODE); // FIXME barcode-based
+    HepMcParticleLink trkLink(HepMC::uniqueID(pGenParticle),pGenParticle->parent_event()->event_number(), HepMcParticleLink::IS_EVENTNUM, HepMcParticleLink::IS_ID);
     const double angle = i*0.2*M_PI;
     std::vector< HepGeom::Point3D<double> > stepPoints(11);
     for (int j=0; j<11; ++j) {
diff --git a/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/test/SiHitCollectionCnv_p3_test.cxx b/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/test/SiHitCollectionCnv_p3_test.cxx
index b32fb10dad29dca18358814407eede6113e10d33..7fdaa2aab12ef75e0f9c5275fb8541393c25ff44 100644
--- a/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/test/SiHitCollectionCnv_p3_test.cxx
+++ b/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/test/SiHitCollectionCnv_p3_test.cxx
@@ -15,6 +15,7 @@
 #include <cassert>
 #include <iostream>
 
+#include "TruthUtils/MagicNumbers.h"
 #include "GeneratorObjectsTPCnv/initMcEventCollection.h"
 #include "AtlasHepMC/GenParticle.h"
 #include "AtlasHepMC/GenEvent.h"
@@ -26,6 +27,7 @@ void compare (const HepMcParticleLink& p1,
 {
   assert ( p1.isValid() == p2.isValid() );
   assert ( HepMC::barcode(p1) == HepMC::barcode(p2) );
+  assert ( p1.id() == p2.id() );
   assert ( p1.eventIndex() == p2.eventIndex() );
   assert ( p1.cptr() == p2.cptr() );
   assert ( p1 == p2 );
@@ -72,7 +74,7 @@ void test1 ATLAS_NOT_THREAD_SAFE (std::vector<HepMC::GenParticlePtr>& genPartVec
   std::cout << "test1\n";
   auto particle = genPartVector.at(0);
   // Create HepMcParticleLink outside of leak check.
-  HepMcParticleLink dummyHMPL(HepMC::barcode(particle),particle->parent_event()->event_number(), HepMcParticleLink::IS_EVENTNUM, HepMcParticleLink::IS_BARCODE); // FIXME barcode-based
+  HepMcParticleLink dummyHMPL(HepMC::uniqueID(particle),particle->parent_event()->event_number(), HepMcParticleLink::IS_EVENTNUM, HepMcParticleLink::IS_ID);
   assert(dummyHMPL.cptr()==particle);
   // Create DVL info outside of leak check.
   SiHitCollection dum ("coll");
@@ -81,7 +83,7 @@ void test1 ATLAS_NOT_THREAD_SAFE (std::vector<HepMC::GenParticlePtr>& genPartVec
   SiHitCollection trans1 ("coll");
   for (int i=0; i < 10; i++) {
     auto pGenParticle = genPartVector.at(i);
-    HepMcParticleLink trkLink(HepMC::barcode(pGenParticle),pGenParticle->parent_event()->event_number(), HepMcParticleLink::IS_EVENTNUM, HepMcParticleLink::IS_BARCODE); // FIXME barcode-based
+    HepMcParticleLink trkLink(HepMC::uniqueID(pGenParticle),pGenParticle->parent_event()->event_number(), HepMcParticleLink::IS_EVENTNUM, HepMcParticleLink::IS_ID);
     const double angle = i*0.2*M_PI;
     std::vector< HepGeom::Point3D<double> > stepPoints(11);
     for (int j=0; j<11; ++j) {
diff --git a/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/test/SiHitCollectionCnv_p4_test.cxx b/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/test/SiHitCollectionCnv_p4_test.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..6106029d6e9d22273460dd75f5d652e4683a17d0
--- /dev/null
+++ b/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/test/SiHitCollectionCnv_p4_test.cxx
@@ -0,0 +1,119 @@
+/*
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
+*/
+/**
+ * @file InDetSimEventTPCnv/test/SiHitCollectionCnv_p4_test.cxx
+ * @brief Tests for SiHitCollectionCnv_p4.
+ */
+
+
+#undef NDEBUG
+#include "InDetSimEventTPCnv/InDetHits/SiHitCollectionCnv_p4.h"
+#include "CxxUtils/checker_macros.h"
+#include "TestTools/leakcheck.h"
+#include <cassert>
+#include <iostream>
+
+#include "TruthUtils/MagicNumbers.h"
+#include "GeneratorObjectsTPCnv/initMcEventCollection.h"
+#include "AtlasHepMC/GenParticle.h"
+#include "AtlasHepMC/GenEvent.h"
+#include "AtlasHepMC/Operators.h"
+
+
+void compare (const HepMcParticleLink& p1,
+              const HepMcParticleLink& p2)
+{
+  assert ( p1.isValid() == p2.isValid() );
+  assert ( HepMC::barcode(p1) == HepMC::barcode(p2) );
+  assert ( p1.id() == p2.id() );
+  assert ( p1.eventIndex() == p2.eventIndex() );
+  assert ( p1.cptr() == p2.cptr() );
+  assert ( p1 == p2 );
+}
+
+void compare (const SiHit& p1,
+              const SiHit& p2)
+{
+  assert (p1.localStartPosition() == p2.localStartPosition());
+  assert (p1.localEndPosition() == p2.localEndPosition());
+  assert (p1.energyLoss() == p2.energyLoss());
+  assert (p1.meanTime() == p2.meanTime());
+  compare(p1.particleLink(), p2.particleLink());
+  assert (p1.particleLink() == p2.particleLink());
+  assert (p1.identify() == p2.identify());
+}
+
+
+void compare (const SiHitCollection& p1,
+              const SiHitCollection& p2)
+{
+  //assert (p1.Name() == p2.Name());
+  assert (p1.size() == p2.size());
+  for (size_t i = 0; i < p1.size(); i++)
+    compare (p1[i], p2[i]);
+}
+
+
+void testit (const SiHitCollection& trans1)
+{
+  MsgStream log (nullptr, "test");
+  SiHitCollectionCnv_p4 cnv;
+  SiHitCollection_p4 pers;
+  cnv.transToPers (&trans1, &pers, log);
+  SiHitCollection trans2;
+  cnv.persToTrans (&pers, &trans2, log);
+
+  compare (trans1, trans2);
+}
+
+
+void test1 ATLAS_NOT_THREAD_SAFE (std::vector<HepMC::GenParticlePtr>& genPartVector)
+{
+  std::cout << "test1\n";
+  auto particle = genPartVector.at(0);
+  // Create HepMcParticleLink outside of leak check.
+  HepMcParticleLink dummyHMPL(HepMC::uniqueID(particle),particle->parent_event()->event_number(), HepMcParticleLink::IS_EVENTNUM, HepMcParticleLink::IS_ID);
+  assert(dummyHMPL.cptr()==particle);
+  // Create DVL info outside of leak check.
+  SiHitCollection dum ("coll");
+  Athena_test::Leakcheck check;
+
+  SiHitCollection trans1 ("coll");
+  for (int i=0; i < 10; i++) {
+    auto pGenParticle = genPartVector.at(i);
+    HepMcParticleLink trkLink(HepMC::uniqueID(pGenParticle),pGenParticle->parent_event()->event_number(), HepMcParticleLink::IS_EVENTNUM, HepMcParticleLink::IS_ID);
+    const double angle = i*0.2*M_PI;
+    std::vector< HepGeom::Point3D<double> > stepPoints(11);
+    for (int j=0; j<11; ++j) {
+      const double jd(j);
+      const double r(30.+110.*jd);
+      stepPoints.emplace_back(r*std::cos(angle),
+                              r*std::sin(angle),
+                              350.*jd);
+    }
+    const int o = i*100;
+    trans1.Emplace (stepPoints.at(i), stepPoints.at(i+1),
+                    16.5+o,
+                    17.5+o,
+                    trkLink,
+                    19+o);
+
+  }
+
+  testit (trans1);
+}
+
+
+int main ATLAS_NOT_THREAD_SAFE ()
+{
+  ISvcLocator* pSvcLoc = nullptr;
+  std::vector<HepMC::GenParticlePtr> genPartVector;
+  if (!Athena_test::initMcEventCollection(pSvcLoc, genPartVector)) {
+    std::cerr << "This test can not be run" << std::endl;
+    return 0;
+  }
+
+  test1(genPartVector);
+  return 0;
+}
diff --git a/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/test/TRT_HitCnv_p1_test.cxx b/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/test/TRT_HitCnv_p1_test.cxx
index 74cbddf8e878878b549776dca87629d5ec112800..e302623e0fc1c2e2d2883360b3f21b6ec7a824f3 100644
--- a/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/test/TRT_HitCnv_p1_test.cxx
+++ b/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/test/TRT_HitCnv_p1_test.cxx
@@ -16,6 +16,7 @@
 #include <cassert>
 #include <iostream>
 
+#include "TruthUtils/MagicNumbers.h"
 #include "GeneratorObjectsTPCnv/initMcEventCollection.h"
 #include "AtlasHepMC/GenParticle.h"
 #include "AtlasHepMC/GenEvent.h"
@@ -26,6 +27,7 @@ void compare (const HepMcParticleLink& p1,
 {
   assert ( p1.isValid() == p2.isValid() );
   assert ( HepMC::barcode(p1) == HepMC::barcode(p2) );
+  assert ( p1.id() == p2.id() );
   assert ( p1.eventIndex() == p2.eventIndex() );
   assert ( p1.cptr() == p2.cptr() );
   assert ( p1 == p2 );
@@ -68,12 +70,12 @@ void test1 ATLAS_NOT_THREAD_SAFE (std::vector<HepMC::GenParticlePtr>& genPartVec
   std::cout << "test1\n";
   auto particle = genPartVector.at(0);
   // Create HepMcParticleLink outside of leak check.
-  HepMcParticleLink dummyHMPL(HepMC::barcode(particle),particle->parent_event()->event_number(), HepMcParticleLink::IS_EVENTNUM, HepMcParticleLink::IS_BARCODE); // FIXME barcode-based
+  HepMcParticleLink dummyHMPL(HepMC::uniqueID(particle),particle->parent_event()->event_number(), HepMcParticleLink::IS_EVENTNUM, HepMcParticleLink::IS_ID);
   assert(dummyHMPL.cptr()==particle);
   Athena_test::Leakcheck check;
 
   auto pGenParticle = genPartVector.at(0);
-  HepMcParticleLink trkLink(HepMC::barcode(pGenParticle),pGenParticle->parent_event()->event_number(), HepMcParticleLink::IS_EVENTNUM, HepMcParticleLink::IS_BARCODE); // FIXME barcode-based
+  HepMcParticleLink trkLink(HepMC::uniqueID(pGenParticle),pGenParticle->parent_event()->event_number(), HepMcParticleLink::IS_EVENTNUM, HepMcParticleLink::IS_ID);
   TRTUncompressedHit trans1 (101, trkLink, pGenParticle->pdg_id(),
                              104.5, 105.5,
                              106.5, 107.5, 108.5,
diff --git a/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/test/TRT_HitCollectionCnv_p2_test.cxx b/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/test/TRT_HitCollectionCnv_p2_test.cxx
index 08f618edb0a78a93704c14a279fc6aa116f76613..166ae10fc4427ddd852d3ed68f60eaa0af8d4e1d 100644
--- a/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/test/TRT_HitCollectionCnv_p2_test.cxx
+++ b/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/test/TRT_HitCollectionCnv_p2_test.cxx
@@ -16,6 +16,7 @@
 #include <cassert>
 #include <iostream>
 
+#include "TruthUtils/MagicNumbers.h"
 #include "GeneratorObjectsTPCnv/initMcEventCollection.h"
 #include "AtlasHepMC/GenParticle.h"
 #include "AtlasHepMC/GenEvent.h"
@@ -26,6 +27,7 @@ void compare (const HepMcParticleLink& p1,
 {
   assert ( p1.isValid() == p2.isValid() );
   assert ( HepMC::barcode(p1) == HepMC::barcode(p2) );
+  assert ( p1.id() == p2.id() );
   assert ( p1.eventIndex() == p2.eventIndex() );
   assert ( p1.cptr() == p2.cptr() );
   assert ( p1 == p2 );
@@ -78,7 +80,7 @@ void test1 ATLAS_NOT_THREAD_SAFE (std::vector<HepMC::GenParticlePtr>& genPartVec
   std::cout << "test1\n";
   auto particle = genPartVector.at(0);
   // Create HepMcParticleLink outside of leak check.
-  HepMcParticleLink dummyHMPL(HepMC::barcode(particle),particle->parent_event()->event_number(), HepMcParticleLink::IS_EVENTNUM, HepMcParticleLink::IS_BARCODE); // FIXME barcode-based
+  HepMcParticleLink dummyHMPL(HepMC::uniqueID(particle),particle->parent_event()->event_number(), HepMcParticleLink::IS_EVENTNUM, HepMcParticleLink::IS_ID);
   assert(dummyHMPL.cptr()==particle);
   // Create DVL info outside of leak check.
   TRTUncompressedHitCollection dum ("coll");
@@ -88,7 +90,7 @@ void test1 ATLAS_NOT_THREAD_SAFE (std::vector<HepMC::GenParticlePtr>& genPartVec
   for (int i=0; i < 10; i++) {
     int o = i*100;
     auto pGenParticle = genPartVector.at(0);
-    HepMcParticleLink trkLink(HepMC::barcode(pGenParticle),pGenParticle->parent_event()->event_number(), HepMcParticleLink::IS_EVENTNUM, HepMcParticleLink::IS_BARCODE); // FIXME barcode-based
+    HepMcParticleLink trkLink(HepMC::uniqueID(pGenParticle),pGenParticle->parent_event()->event_number(), HepMcParticleLink::IS_EVENTNUM, HepMcParticleLink::IS_ID);
     trans1.Emplace (101+o, trkLink, pGenParticle->pdg_id(),
                     104.5+o, 105.5+o,
                     (106.5+o)/1000, (107.5+o)/1000, 108.5+o,
@@ -97,7 +99,7 @@ void test1 ATLAS_NOT_THREAD_SAFE (std::vector<HepMC::GenParticlePtr>& genPartVec
   }
   // Special case for photons
   auto pGenParticle = genPartVector.at(10);
-  HepMcParticleLink trkLink(HepMC::barcode(pGenParticle),pGenParticle->parent_event()->event_number(), HepMcParticleLink::IS_EVENTNUM, HepMcParticleLink::IS_BARCODE); // FIXME barcode-based
+  HepMcParticleLink trkLink(HepMC::uniqueID(pGenParticle),pGenParticle->parent_event()->event_number(), HepMcParticleLink::IS_EVENTNUM, HepMcParticleLink::IS_ID);
   trans1.Emplace (131, trkLink, 22,
                   134.5, 135.5,
                   10, 3, 138.5,
diff --git a/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/test/TRT_HitCollectionCnv_p3_test.cxx b/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/test/TRT_HitCollectionCnv_p3_test.cxx
index 92bc9586bb055538a43675e04d7e45e3015de766..bb6ade35a7ce398e7ff031b31bf3bf2c351e9f40 100644
--- a/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/test/TRT_HitCollectionCnv_p3_test.cxx
+++ b/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/test/TRT_HitCollectionCnv_p3_test.cxx
@@ -18,6 +18,7 @@
 #include <iostream>
 #include <cmath>
 
+#include "TruthUtils/MagicNumbers.h"
 #include "GeneratorObjectsTPCnv/initMcEventCollection.h"
 #include "AtlasHepMC/GenParticle.h"
 #include "AtlasHepMC/GenEvent.h"
@@ -32,6 +33,7 @@ void compare (const HepMcParticleLink& p1,
 {
   assert ( p1.isValid() == p2.isValid() );
   assert ( HepMC::barcode(p1) == HepMC::barcode(p2) );
+  assert ( p1.id() == p2.id() );
   assert ( p1.eventIndex() == p2.eventIndex() );
   assert ( p1.cptr() == p2.cptr() );
   assert ( p1 == p2 );
@@ -98,7 +100,7 @@ void test1 ATLAS_NOT_THREAD_SAFE (std::vector<HepMC::GenParticlePtr>& genPartVec
   std::cout << "test1\n";
   auto particle = genPartVector.at(0);
   // Create HepMcParticleLink outside of leak check.
-  HepMcParticleLink dummyHMPL(HepMC::barcode(particle),particle->parent_event()->event_number(), HepMcParticleLink::IS_EVENTNUM, HepMcParticleLink::IS_BARCODE); // FIXME barcode-based
+  HepMcParticleLink dummyHMPL(HepMC::uniqueID(particle),particle->parent_event()->event_number(), HepMcParticleLink::IS_EVENTNUM, HepMcParticleLink::IS_ID);
   assert(dummyHMPL.cptr()==particle);
   // Create DVL info outside of leak check.
   TRTUncompressedHitCollection dum ("coll");
@@ -108,7 +110,7 @@ void test1 ATLAS_NOT_THREAD_SAFE (std::vector<HepMC::GenParticlePtr>& genPartVec
   for (int i=0; i < 10; i++) {
     int o = i*100;
     auto pGenParticle = genPartVector.at(0);
-    HepMcParticleLink trkLink(HepMC::barcode(pGenParticle),pGenParticle->parent_event()->event_number(), HepMcParticleLink::IS_EVENTNUM, HepMcParticleLink::IS_BARCODE); // FIXME barcode-based
+    HepMcParticleLink trkLink(HepMC::uniqueID(pGenParticle),pGenParticle->parent_event()->event_number(), HepMcParticleLink::IS_EVENTNUM, HepMcParticleLink::IS_ID);
     trans1.Emplace (101+o, trkLink, 20+o,
                     104.5+o, 105.5+o,
                     (106.5+o)/1000, (107.5+o)/1000, 108.5+o,
@@ -117,7 +119,7 @@ void test1 ATLAS_NOT_THREAD_SAFE (std::vector<HepMC::GenParticlePtr>& genPartVec
   }
   // Special case for photons
   auto pGenParticle = genPartVector.at(10);
-  HepMcParticleLink trkLink(HepMC::barcode(pGenParticle),pGenParticle->parent_event()->event_number(), HepMcParticleLink::IS_EVENTNUM, HepMcParticleLink::IS_BARCODE); // FIXME barcode-based
+  HepMcParticleLink trkLink(HepMC::uniqueID(pGenParticle),pGenParticle->parent_event()->event_number(), HepMcParticleLink::IS_EVENTNUM, HepMcParticleLink::IS_ID);
   trans1.Emplace (131, trkLink, 22,
                   134.5, 135.5,
                   10, 3, 138.5,
diff --git a/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/test/TRT_HitCollectionCnv_p4_test.cxx b/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/test/TRT_HitCollectionCnv_p4_test.cxx
index 288c094f0a3f21076aca8cb9849d4ac665cec2c3..7d466c816cd132edecbbc725d7706fe33e543664 100644
--- a/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/test/TRT_HitCollectionCnv_p4_test.cxx
+++ b/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/test/TRT_HitCollectionCnv_p4_test.cxx
@@ -18,6 +18,7 @@
 #include <iostream>
 #include <cmath>
 
+#include "TruthUtils/MagicNumbers.h"
 #include "GeneratorObjectsTPCnv/initMcEventCollection.h"
 #include "AtlasHepMC/GenParticle.h"
 #include "AtlasHepMC/GenEvent.h"
@@ -32,6 +33,7 @@ void compare (const HepMcParticleLink& p1,
 {
   assert ( p1.isValid() == p2.isValid() );
   assert ( HepMC::barcode(p1) == HepMC::barcode(p2) );
+  assert ( p1.id() == p2.id() );
   assert ( p1.eventIndex() == p2.eventIndex() );
   assert ( p1.cptr() == p2.cptr() );
   assert ( p1 == p2 );
@@ -98,7 +100,7 @@ void test1 ATLAS_NOT_THREAD_SAFE (std::vector<HepMC::GenParticlePtr>& genPartVec
   std::cout << "test1\n";
   auto particle = genPartVector.at(0);
   // Create HepMcParticleLink outside of leak check.
-  HepMcParticleLink dummyHMPL(HepMC::barcode(particle),particle->parent_event()->event_number(), HepMcParticleLink::IS_EVENTNUM, HepMcParticleLink::IS_BARCODE); // FIXME barcode-based
+  HepMcParticleLink dummyHMPL(HepMC::uniqueID(particle),particle->parent_event()->event_number(), HepMcParticleLink::IS_EVENTNUM, HepMcParticleLink::IS_ID);
   assert(dummyHMPL.cptr()==particle);
   // Create DVL info outside of leak check.
   TRTUncompressedHitCollection dum ("coll");
@@ -108,7 +110,7 @@ void test1 ATLAS_NOT_THREAD_SAFE (std::vector<HepMC::GenParticlePtr>& genPartVec
   for (int i=0; i < 10; i++) {
     int o = i*100;
     auto pGenParticle = genPartVector.at(0);
-    HepMcParticleLink trkLink(HepMC::barcode(pGenParticle),pGenParticle->parent_event()->event_number(), HepMcParticleLink::IS_EVENTNUM, HepMcParticleLink::IS_BARCODE); // FIXME barcode-based
+    HepMcParticleLink trkLink(HepMC::uniqueID(pGenParticle),pGenParticle->parent_event()->event_number(), HepMcParticleLink::IS_EVENTNUM, HepMcParticleLink::IS_ID);
     trans1.Emplace (101+o, trkLink, 20+o,
                     104.5+o, 105.5+o,
                     (106.5+o)/1000, (107.5+o)/1000, 108.5+o,
@@ -117,7 +119,7 @@ void test1 ATLAS_NOT_THREAD_SAFE (std::vector<HepMC::GenParticlePtr>& genPartVec
   }
   // Special case for photons
   auto pGenParticle = genPartVector.at(10);
-  HepMcParticleLink trkLink(HepMC::barcode(pGenParticle),pGenParticle->parent_event()->event_number(), HepMcParticleLink::IS_EVENTNUM, HepMcParticleLink::IS_BARCODE); // FIXME barcode-based
+  HepMcParticleLink trkLink(HepMC::uniqueID(pGenParticle),pGenParticle->parent_event()->event_number(), HepMcParticleLink::IS_EVENTNUM, HepMcParticleLink::IS_ID);
   trans1.Emplace (131, trkLink, 22,
                   134.5, 135.5,
                   10, 3, 138.5,
diff --git a/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/test/TRT_HitCollectionCnv_p5_test.cxx b/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/test/TRT_HitCollectionCnv_p5_test.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..5413fd7730cab26f7c3e59d7671c9c3f39c594a4
--- /dev/null
+++ b/InnerDetector/InDetEventCnv/InDetSimEventTPCnv/test/TRT_HitCollectionCnv_p5_test.cxx
@@ -0,0 +1,144 @@
+/*
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
+*/
+/**
+ * @file InDetSimEventTPCnv/test/TRT_HitCollectionCnv_p5_test.cxx
+ * @author scott snyder <snyder@bnl.gov>
+ * @date Feb, 2016
+ * @brief Tests for TRT_HitCollectionCnv_p5.
+ */
+
+
+#undef NDEBUG
+#include "InDetSimEventTPCnv/InDetHits/TRT_HitCollectionCnv_p5.h"
+#include "CxxUtils/checker_macros.h"
+#include "TestTools/FLOATassert.h"
+#include "TestTools/leakcheck.h"
+#include <cassert>
+#include <iostream>
+#include <cmath>
+
+#include "TruthUtils/MagicNumbers.h"
+#include "GeneratorObjectsTPCnv/initMcEventCollection.h"
+#include "AtlasHepMC/GenParticle.h"
+#include "AtlasHepMC/GenEvent.h"
+#include "AtlasHepMC/Operators.h"
+
+using Athena_test::isEqual;
+using std::atan2;
+
+
+void compare (const HepMcParticleLink& p1,
+              const HepMcParticleLink& p2)
+{
+  assert ( p1.isValid() == p2.isValid() );
+  assert ( HepMC::barcode(p1) == HepMC::barcode(p2) );
+  assert ( p1.id() == p2.id() );
+  assert ( p1.eventIndex() == p2.eventIndex() );
+  assert ( p1.cptr() == p2.cptr() );
+  assert ( p1 == p2 );
+}
+
+void compare (const TRTUncompressedHit& p1,
+              const TRTUncompressedHit& p2)
+{
+  assert (p1.GetHitID() == p2.GetHitID());
+  compare(p1.particleLink(), p2.particleLink());
+  assert (p1.particleLink() == p2.particleLink());
+  assert (p1.GetParticleEncoding() == p2.GetParticleEncoding());
+  assert (isEqual (p1.GetKineticEnergy(), p2.GetKineticEnergy(), 5e-4));
+  if (p1.GetParticleEncoding() == 22)
+    assert (p1.GetEnergyDeposit() == p2.GetEnergyDeposit());
+  else
+    assert (0 == p2.GetEnergyDeposit());
+  if (p1.GetPreStepX() > 2) {
+    const double phi1 = atan2 (p1.GetPreStepY(), p1.GetPreStepX());
+    assert (isEqual (2*cos(phi1), p2.GetPreStepX(), 1e-2));
+    assert (isEqual (2*sin(phi1), p2.GetPreStepY(), 2e-2));
+
+    const double phi2 = atan2 (p1.GetPostStepY(), p1.GetPostStepX());
+    assert (isEqual (2*cos(phi2), p2.GetPostStepX(), 2e-2));
+    assert (isEqual (2*sin(phi2), p2.GetPostStepY(), 1e-2));
+  }
+  else {
+    assert (isEqual (p1.GetPreStepX(), p2.GetPreStepX(), 1e-2));
+    assert (isEqual (p1.GetPreStepY(), p2.GetPreStepY(), 1e-2));
+    assert (isEqual (p1.GetPostStepX(), p2.GetPostStepX(), 2e-2));
+    assert (isEqual (p1.GetPostStepY(), p2.GetPostStepY(), 2e-2));
+  }
+  assert (isEqual (p1.GetPreStepZ(), p2.GetPreStepZ(), 0.1));
+  assert (isEqual (p1.GetPostStepZ(), p2.GetPostStepZ(), 0.1));
+  assert (p1.GetGlobalTime() == p2.GetGlobalTime());
+}
+
+
+void compare (const TRTUncompressedHitCollection& p1,
+              const TRTUncompressedHitCollection& p2)
+{
+  //assert (p1.Name() == p2.Name());
+  assert (p1.size() == p2.size());
+  for (size_t i = 0; i < p1.size(); i++)
+    compare (p1[i], p2[i]);
+}
+
+
+void testit (const TRTUncompressedHitCollection& trans1)
+{
+  MsgStream log (nullptr, "test");
+  TRT_HitCollectionCnv_p5 cnv;
+  TRT_HitCollection_p5 pers;
+  cnv.transToPers (&trans1, &pers, log);
+  TRTUncompressedHitCollection trans2;
+  cnv.persToTrans (&pers, &trans2, log);
+
+  compare (trans1, trans2);
+}
+
+
+void test1 ATLAS_NOT_THREAD_SAFE (std::vector<HepMC::GenParticlePtr>& genPartVector)
+{
+  std::cout << "test1\n";
+  auto particle = genPartVector.at(0);
+  // Create HepMcParticleLink outside of leak check.
+  HepMcParticleLink dummyHMPL(HepMC::uniqueID(particle),particle->parent_event()->event_number(), HepMcParticleLink::IS_EVENTNUM, HepMcParticleLink::IS_ID);
+  assert(dummyHMPL.cptr()==particle);
+  // Create DVL info outside of leak check.
+  TRTUncompressedHitCollection dum ("coll");
+  Athena_test::Leakcheck check;
+
+  TRTUncompressedHitCollection trans1 ("coll");
+  for (int i=0; i < 10; i++) {
+    int o = i*100;
+    auto pGenParticle = genPartVector.at(0);
+    HepMcParticleLink trkLink(HepMC::uniqueID(pGenParticle),pGenParticle->parent_event()->event_number(), HepMcParticleLink::IS_EVENTNUM, HepMcParticleLink::IS_ID);
+    trans1.Emplace (101+o, trkLink, 20+o,
+                    104.5+o, 105.5+o,
+                    (106.5+o)/1000, (107.5+o)/1000, 108.5+o,
+                    (109.5+o)/1000, (110.5+o)/1000, 111.5+o,
+                    112.5+o);
+  }
+  // Special case for photons
+  auto pGenParticle = genPartVector.at(10);
+  HepMcParticleLink trkLink(HepMC::uniqueID(pGenParticle),pGenParticle->parent_event()->event_number(), HepMcParticleLink::IS_EVENTNUM, HepMcParticleLink::IS_ID);
+  trans1.Emplace (131, trkLink, 22,
+                  134.5, 135.5,
+                  10, 3, 138.5,
+                  3, 10, 148.5,
+                  142.5);
+
+  testit (trans1);
+}
+
+
+int main ATLAS_NOT_THREAD_SAFE ()
+{
+  ISvcLocator* pSvcLoc = nullptr;
+  std::vector<HepMC::GenParticlePtr> genPartVector;
+  if (!Athena_test::initMcEventCollection(pSvcLoc, genPartVector)) {
+    std::cerr << "This test can not be run" << std::endl;
+    return 0;
+  }
+
+  test1(genPartVector);
+  return 0;
+}