From 1a1668d3efbff9abfa64a2d9f8fa6ad03339ad14 Mon Sep 17 00:00:00 2001
From: Dave Casper <dcasper@uci.edu>
Date: Tue, 9 Apr 2024 02:36:27 -0700
Subject: [PATCH] Work in Progress on MC

---
 Simulation/G4Sim/FaserMCTruth/CMakeLists.txt  |   2 +-
 .../FaserPrimaryParticleInformation.h         |   3 +-
 .../FaserMCTruth/FaserTrackBarcodeInfo.h      |  31 ++--
 .../FaserMCTruth/FaserTrackInformation.h      |  28 +--
 .../FaserMCTruth/FaserVTrackInformation.h     |  41 ++---
 .../src/FaserTrackBarcodeInfo.cxx             |  25 +--
 .../src/FaserTrackInformation.cxx             |  57 ++++---
 .../src/FaserVTrackInformation.cxx            |  31 ++--
 .../src/FaserTruthStrategyManager.cxx         |  20 ++-
 .../G4Utilities/G4UserActions/CMakeLists.txt  |   2 +-
 .../src/AthenaDebugStackingAction.cxx         |  19 +--
 .../src/AthenaStackingAction.cxx              |  19 +--
 .../src/AthenaTrackingAction.cxx              |  10 +-
 .../G4UserActions/src/LooperKiller.h          |   1 -
 .../FaserISF_Event/IFaserTruthIncident.h      |   9 +-
 .../FaserGeant4TruthIncident.h                |  46 +++--
 .../FaserISF_Geant4Event/FaserISFG4Helper.h   |   9 +-
 .../src/FaserGeant4TruthIncident.cxx          | 159 +++++++++++-------
 .../src/FaserISFG4Helper.cxx                  |   9 +-
 package_filters.txt                           |   6 +-
 20 files changed, 301 insertions(+), 226 deletions(-)

diff --git a/Simulation/G4Sim/FaserMCTruth/CMakeLists.txt b/Simulation/G4Sim/FaserMCTruth/CMakeLists.txt
index 1ef15e63..c30100a2 100644
--- a/Simulation/G4Sim/FaserMCTruth/CMakeLists.txt
+++ b/Simulation/G4Sim/FaserMCTruth/CMakeLists.txt
@@ -16,5 +16,5 @@ atlas_add_library( FaserMCTruth
                    PUBLIC_HEADERS FaserMCTruth
                    INCLUDE_DIRS ${GEANT4_INCLUDE_DIRS} ${XERCESC_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS} 
                    DEFINITIONS ${CLHEP_DEFINITIONS}
-                   LINK_LIBRARIES ${GEANT4_LIBRARIES} ${XERCESC_LIBRARIES} ${CLHEP_LIBRARIES} AtlasHepMCLib AthenaKernel GeneratorObjects
+                   LINK_LIBRARIES ${GEANT4_LIBRARIES} ${XERCESC_LIBRARIES} ${CLHEP_LIBRARIES} AtlasHepMCLib AthenaKernel GeneratorObjects TruthUtils
                    PRIVATE_LINK_LIBRARIES ISF_Event FaserISF_Event SimHelpers )
diff --git a/Simulation/G4Sim/FaserMCTruth/FaserMCTruth/FaserPrimaryParticleInformation.h b/Simulation/G4Sim/FaserMCTruth/FaserMCTruth/FaserPrimaryParticleInformation.h
index 35003933..1d63c847 100644
--- a/Simulation/G4Sim/FaserMCTruth/FaserMCTruth/FaserPrimaryParticleInformation.h
+++ b/Simulation/G4Sim/FaserMCTruth/FaserMCTruth/FaserPrimaryParticleInformation.h
@@ -20,6 +20,7 @@ public:
 	FaserPrimaryParticleInformation();
 	FaserPrimaryParticleInformation(HepMC::GenParticlePtr, ISF::FaserISFParticle* isp=0);
 	HepMC::ConstGenParticlePtr GetHepMCParticle() const;
+	HepMC::GenParticlePtr GetHepMCParticle() { return m_theParticle; }
 	int GetParticleBarcode() const;
 	int GetParticleUniqueID() const;
 	void SuggestBarcode(int bc);
@@ -33,7 +34,7 @@ public:
 	ISF::FaserISFParticle* GetISFParticle() { return m_theISFParticle; }
 
 private:
-	HepMC::ConstGenParticlePtr m_theParticle;
+	HepMC::GenParticlePtr m_theParticle;
 	ISF::FaserISFParticle* m_theISFParticle;
 
     int m_regenerationNr{0};
diff --git a/Simulation/G4Sim/FaserMCTruth/FaserMCTruth/FaserTrackBarcodeInfo.h b/Simulation/G4Sim/FaserMCTruth/FaserMCTruth/FaserTrackBarcodeInfo.h
index ba66de39..73cda2be 100644
--- a/Simulation/G4Sim/FaserMCTruth/FaserMCTruth/FaserTrackBarcodeInfo.h
+++ b/Simulation/G4Sim/FaserMCTruth/FaserMCTruth/FaserTrackBarcodeInfo.h
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
 */
 
 #ifndef FaserTrackBarcodeInfo_H
@@ -8,23 +8,30 @@
 #include "FaserVTrackInformation.h"
 
 namespace ISF {
-  class FaserISFParticle;
+  class ISFParticle;
 }
 
 class FaserTrackBarcodeInfo: public FaserVTrackInformation {
 public:
-        FaserTrackBarcodeInfo(int bc, const ISF::FaserISFParticle* baseIsp=0);
-	int GetParticleBarcode() const;
-	const ISF::FaserISFParticle *GetBaseISFParticle() const;
-	void SetBaseISFParticle(const ISF::FaserISFParticle*);
-	void SetReturnedToISF(bool returned);
-	bool GetReturnedToISF() const;
+  FaserTrackBarcodeInfo(int uid, int bc, ISF::FaserISFParticle* baseIsp=0);
+  virtual int GetParticleBarcode() const override {return m_barcode;}  // TODO Drop this once UniqueID and Status are used instead
+  virtual int GetParticleUniqueID() const override {return m_uniqueID;}
+  virtual int GetParticleStatus() const override {return m_status;}
+  virtual const ISF::FaserISFParticle *GetBaseISFParticle() const override {return m_theBaseISFParticle;}
+  virtual ISF::FaserISFParticle *GetBaseISFParticle() override {return m_theBaseISFParticle;}
+
+  virtual void SetBaseISFParticle(ISF::FaserISFParticle*) override;
+  virtual void SetReturnedToISF(bool returned) override;
+  virtual bool GetReturnedToISF() const override {return m_returnedToISF;}
 
 private:
-	const ISF::FaserISFParticle *m_theBaseISFParticle;
-	int m_barcode;
-	bool m_returnedToISF;
+  ISF::FaserISFParticle *m_theBaseISFParticle;
+  int m_barcode;  // TODO Drop this once UniqueID and Status are used instead
+  int m_uniqueID;
+  int m_status{0}; //FIXME
+  bool m_returnedToISF;
 };
 
 
-#endif // FaserTrackBarcodeInfo_H
+#endif // TrackBarcodeInfo_H
+
diff --git a/Simulation/G4Sim/FaserMCTruth/FaserMCTruth/FaserTrackInformation.h b/Simulation/G4Sim/FaserMCTruth/FaserMCTruth/FaserTrackInformation.h
index b9be4796..b6c8db0b 100644
--- a/Simulation/G4Sim/FaserMCTruth/FaserMCTruth/FaserTrackInformation.h
+++ b/Simulation/G4Sim/FaserMCTruth/FaserMCTruth/FaserTrackInformation.h
@@ -6,6 +6,8 @@
 #define FaserTrackInformation_H
 
 #include "FaserVTrackInformation.h"
+#include "TruthUtils/MagicNumbers.h"
+#include "CxxUtils/checker_macros.h"
 
 namespace ISF {
   class FaserISFParticle;
@@ -14,20 +16,26 @@ namespace ISF {
 class FaserTrackInformation: public FaserVTrackInformation {
 public:
 	FaserTrackInformation();
-	FaserTrackInformation(HepMC::ConstGenParticlePtr,const ISF::FaserISFParticle* baseIsp=0);
-	HepMC::ConstGenParticlePtr GetHepMCParticle() const;
-	const ISF::FaserISFParticle *GetBaseISFParticle() const;
-	int GetParticleBarcode() const;
-	void SetParticle(HepMC::ConstGenParticlePtr);
-	void SetBaseISFParticle(const ISF::FaserISFParticle*);
-	void SetReturnedToISF(bool returned) {m_returnedToISF=returned;};
-	bool GetReturnedToISF() const {return m_returnedToISF;};
+	FaserTrackInformation(HepMC::GenParticlePtr, ISF::FaserISFParticle* baseIsp=0);
+	virtual HepMC::ConstGenParticlePtr GetHepMCParticle() const override { return m_theParticle; };
+	virtual HepMC::GenParticlePtr GetHepMCParticle() override { return m_theParticle; };
+	virtual const ISF::FaserISFParticle *GetBaseISFParticle() const override { return m_theBaseISFParticle; };
+	virtual ISF::FaserISFParticle *GetBaseISFParticle() override { return m_theBaseISFParticle; };
+	virtual int GetParticleBarcode() const override;
+  	virtual int GetParticleUniqueID() const override;
+  	virtual int GetParticleStatus() const override;
+   	virtual void SetParticle(HepMC::GenParticlePtr) override;
+	virtual void SetBaseISFParticle(ISF::FaserISFParticle*) override;
+	virtual void SetReturnedToISF(bool returned) override {m_returnedToISF=returned;};
+	virtual bool GetReturnedToISF() const override {return m_returnedToISF;};
 	void SetRegenerationNr(int i) {m_regenerationNr=i;};
 	int GetRegenerationNr() const {return m_regenerationNr;};
 private:
 	int m_regenerationNr;
-	HepMC::ConstGenParticlePtr m_theParticle;
-	const ISF::FaserISFParticle *m_theBaseISFParticle;
+	HepMC::GenParticlePtr m_theParticle;
+    mutable int m_barcode ATLAS_THREAD_SAFE = HepMC::INVALID_PARTICLE_BARCODE; // TODO Drop this once UniqueID and Status are used instead
+    mutable int m_uniqueID ATLAS_THREAD_SAFE = HepMC::INVALID_PARTICLE_BARCODE;
+	ISF::FaserISFParticle *m_theBaseISFParticle;
 	bool m_returnedToISF;
 };
 
diff --git a/Simulation/G4Sim/FaserMCTruth/FaserMCTruth/FaserVTrackInformation.h b/Simulation/G4Sim/FaserMCTruth/FaserMCTruth/FaserVTrackInformation.h
index 62ec9b0a..be708452 100644
--- a/Simulation/G4Sim/FaserMCTruth/FaserMCTruth/FaserVTrackInformation.h
+++ b/Simulation/G4Sim/FaserMCTruth/FaserMCTruth/FaserVTrackInformation.h
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
 */
 
 #ifndef FaserVTrackInformation_H
@@ -9,9 +9,6 @@
 
 enum TrackClassification { Primary, RegeneratedPrimary, RegisteredSecondary, Secondary, BarcodeOnly } ;
 
-// namespace HepMC {
-//   class GenParticle;
-// }
 #include "AtlasHepMC/GenParticle_fwd.h"
 
 namespace ISF {
@@ -20,22 +17,28 @@ namespace ISF {
 
 class FaserVTrackInformation: public G4VUserTrackInformation {
 public:
-	FaserVTrackInformation(TrackClassification tc=Primary);
-	HepMC::ConstGenParticlePtr GetPrimaryHepMCParticle() const;
-	void  SetPrimaryHepMCParticle(HepMC::ConstGenParticlePtr);
-	virtual HepMC::ConstGenParticlePtr GetHepMCParticle() const;
-	virtual const ISF::FaserISFParticle *GetBaseISFParticle() const;
-	virtual bool GetReturnedToISF() const;
-	virtual int  GetParticleBarcode() const =0;
-	virtual void SetParticle(HepMC::ConstGenParticlePtr);
-	virtual void SetBaseISFParticle(const ISF::FaserISFParticle*);
-	virtual void SetReturnedToISF(bool) ;
-	virtual void Print() const {}
-	void SetClassification(TrackClassification tc) {m_classify=tc;}
-	TrackClassification GetClassification() {return m_classify;}
+  FaserVTrackInformation(TrackClassification tc=Primary);
+  HepMC::ConstGenParticlePtr GetPrimaryHepMCParticle() const {return m_thePrimaryParticle;}
+  HepMC::GenParticlePtr GetPrimaryHepMCParticle() {return m_thePrimaryParticle;}
+  void  SetPrimaryHepMCParticle(HepMC::GenParticlePtr);
+  virtual HepMC::ConstGenParticlePtr GetHepMCParticle() const {return nullptr;}
+  virtual HepMC::GenParticlePtr GetHepMCParticle() {return nullptr;}
+  virtual const ISF::FaserISFParticle *GetBaseISFParticle() const {return nullptr;}
+  virtual ISF::FaserISFParticle *GetBaseISFParticle() {return nullptr;}
+  virtual bool GetReturnedToISF() const;
+  virtual int  GetParticleBarcode() const =0;  // TODO Drop this once UniqueID and Status are used instead
+  virtual int GetParticleUniqueID() const =0;
+  virtual int GetParticleStatus() const = 0;
+  virtual void SetParticle(HepMC::GenParticlePtr);
+  virtual void SetBaseISFParticle(ISF::FaserISFParticle*);
+  virtual void SetReturnedToISF(bool) ;
+  virtual void Print() const {}
+  void SetClassification(TrackClassification tc) {m_classify=tc;}
+  TrackClassification GetClassification() const {return m_classify;}
 private:
-	TrackClassification m_classify;
-	HepMC::ConstGenParticlePtr m_thePrimaryParticle;
+  TrackClassification m_classify;
+  HepMC::GenParticlePtr m_thePrimaryParticle{};
 };
 
 #endif
+
diff --git a/Simulation/G4Sim/FaserMCTruth/src/FaserTrackBarcodeInfo.cxx b/Simulation/G4Sim/FaserMCTruth/src/FaserTrackBarcodeInfo.cxx
index 78d64bed..1ddf4bd9 100644
--- a/Simulation/G4Sim/FaserMCTruth/src/FaserTrackBarcodeInfo.cxx
+++ b/Simulation/G4Sim/FaserMCTruth/src/FaserTrackBarcodeInfo.cxx
@@ -1,34 +1,25 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
 */
 
 #include "FaserMCTruth/FaserTrackBarcodeInfo.h"
 
-FaserTrackBarcodeInfo::FaserTrackBarcodeInfo(int bc, const ISF::FaserISFParticle* baseIsp):FaserVTrackInformation(BarcodeOnly),m_theBaseISFParticle(baseIsp),m_barcode(bc),m_returnedToISF(false)
+FaserTrackBarcodeInfo::FaserTrackBarcodeInfo(int uid, int bc, ISF::FaserISFParticle* baseIsp)
+  : FaserVTrackInformation(BarcodeOnly)
+  , m_theBaseISFParticle(baseIsp)
+  , m_barcode(bc)
+  , m_uniqueID(uid)
+  , m_returnedToISF(false)
 {
 }
 
-int FaserTrackBarcodeInfo::GetParticleBarcode() const
-{
-  return m_barcode;
-}
-
-void FaserTrackBarcodeInfo::SetBaseISFParticle(const ISF::FaserISFParticle* isp)
+void FaserTrackBarcodeInfo::SetBaseISFParticle(ISF::FaserISFParticle* isp)
 {
   m_theBaseISFParticle=isp;
 }
 
-const ISF::FaserISFParticle* FaserTrackBarcodeInfo::GetBaseISFParticle() const
-{
-  return m_theBaseISFParticle;
-}
-
 void FaserTrackBarcodeInfo::SetReturnedToISF(bool returned)
 {
   m_returnedToISF = returned;
 }
 
-bool FaserTrackBarcodeInfo::GetReturnedToISF() const
-{
-  return m_returnedToISF;
-}
diff --git a/Simulation/G4Sim/FaserMCTruth/src/FaserTrackInformation.cxx b/Simulation/G4Sim/FaserMCTruth/src/FaserTrackInformation.cxx
index 75f258bb..3e6d78f5 100644
--- a/Simulation/G4Sim/FaserMCTruth/src/FaserTrackInformation.cxx
+++ b/Simulation/G4Sim/FaserMCTruth/src/FaserTrackInformation.cxx
@@ -1,47 +1,66 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
 */
 
 #include "FaserMCTruth/FaserTrackInformation.h"
 #include "AtlasHepMC/GenEvent.h"
+#include "AtlasHepMC/GenParticle.h"
+#include "AtlasHepMC/GenVertex.h"
 
-FaserTrackInformation::FaserTrackInformation():m_regenerationNr(0),m_theParticle(0),m_theBaseISFParticle(0),m_returnedToISF(false)
+FaserTrackInformation::FaserTrackInformation()
+  : m_regenerationNr(0)
+  , m_theParticle(nullptr)
+  , m_theBaseISFParticle(nullptr)
+  , m_returnedToISF(false)
 {
 }
 
-FaserTrackInformation::FaserTrackInformation(HepMC::ConstGenParticlePtr p, const ISF::FaserISFParticle* baseIsp):
-    m_regenerationNr(0),
-    m_theParticle(p),
-    m_theBaseISFParticle(baseIsp),
-    m_returnedToISF(false)
+FaserTrackInformation::FaserTrackInformation(HepMC::GenParticlePtr p, ISF::FaserISFParticle* baseIsp)
+  : m_regenerationNr(0)
+  , m_theParticle(p)
+  , m_theBaseISFParticle(baseIsp)
+  , m_returnedToISF(false)
 {
 }
 
-HepMC::ConstGenParticlePtr FaserTrackInformation::GetHepMCParticle() const
+int FaserTrackInformation::GetParticleBarcode() const
 {
-  return m_theParticle;
+  if (m_barcode != HepMC::INVALID_PARTICLE_BARCODE) return m_barcode;
+  if (m_theParticle) {
+    m_barcode = HepMC::barcode(m_theParticle);
+    return m_barcode;
+  }
+  return 0;
 }
 
-const ISF::FaserISFParticle* FaserTrackInformation::GetBaseISFParticle() const
+int FaserTrackInformation::GetParticleUniqueID() const
 {
-  return m_theBaseISFParticle;
+  if (m_uniqueID != HepMC::INVALID_PARTICLE_BARCODE) return m_uniqueID;
+  if (m_theParticle) {
+    HepMC::ConstGenParticlePtr particle = m_theParticle;
+    m_uniqueID = HepMC::uniqueID(particle);
+    return m_uniqueID;
+  }
+  return 0;
 }
 
-int FaserTrackInformation::GetParticleBarcode() const
+int FaserTrackInformation::GetParticleStatus() const
 {
-#ifdef HEPMC3
-  return ( m_theParticle ? m_theParticle->id() : 0 );
-#else
-  return ( m_theParticle ? m_theParticle->barcode() : 0 );
-#endif  
+  if (m_theParticle) {
+    return m_theParticle->status();
+  }
+  return 0;
 }
 
-void FaserTrackInformation::SetParticle(HepMC::ConstGenParticlePtr p)
+void FaserTrackInformation::SetParticle(HepMC::GenParticlePtr p)
 {
   m_theParticle=p;
+  m_barcode = HepMC::INVALID_PARTICLE_BARCODE;
+  m_uniqueID = HepMC::INVALID_PARTICLE_BARCODE;
 }
 
-void FaserTrackInformation::SetBaseISFParticle(const ISF::FaserISFParticle* p)
+void FaserTrackInformation::SetBaseISFParticle(ISF::FaserISFParticle* p)
 {
   m_theBaseISFParticle=p;
 }
+
diff --git a/Simulation/G4Sim/FaserMCTruth/src/FaserVTrackInformation.cxx b/Simulation/G4Sim/FaserMCTruth/src/FaserVTrackInformation.cxx
index b3ffe83e..4f6ceddc 100644
--- a/Simulation/G4Sim/FaserMCTruth/src/FaserVTrackInformation.cxx
+++ b/Simulation/G4Sim/FaserMCTruth/src/FaserVTrackInformation.cxx
@@ -2,46 +2,34 @@
   Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
 */
 
-#include "FaserMCTruth/FaserVTrackInformation.h"
+/*
+  Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
+*/
 
-FaserVTrackInformation::FaserVTrackInformation(TrackClassification tc):m_classify(tc),m_thePrimaryParticle(0)
-{
-}
+#include "FaserMCTruth/FaserVTrackInformation.h"
 
-HepMC::ConstGenParticlePtr FaserVTrackInformation::GetPrimaryHepMCParticle() const
+FaserVTrackInformation::FaserVTrackInformation(TrackClassification tc):m_classify(tc)
 {
-  return m_thePrimaryParticle;
 }
 
-void FaserVTrackInformation::SetPrimaryHepMCParticle(HepMC::ConstGenParticlePtr p)
+void FaserVTrackInformation::SetPrimaryHepMCParticle(HepMC::GenParticlePtr p)
 {
   m_thePrimaryParticle=p;
 }
 
-
-HepMC::ConstGenParticlePtr FaserVTrackInformation::GetHepMCParticle() const
-{
-  return 0;
-}
-
-const ISF::FaserISFParticle* FaserVTrackInformation::GetBaseISFParticle() const
-{
-  return 0;
-}
-
 bool FaserVTrackInformation::GetReturnedToISF() const
 {
   return false;
 }
 
-void FaserVTrackInformation::SetParticle(HepMC::ConstGenParticlePtr /*p*/)
+void FaserVTrackInformation::SetParticle(HepMC::GenParticlePtr /*p*/)
 {
   // you should not call this, perhaps throw an exception?
-  std::cerr<<"ERROR  FaserVTrackInformation::SetParticle() not supported  "<<std::endl;
+  std::cerr<<"ERROR  VTrackInformation::SetParticle() not supported  "<<std::endl;
  
 }
 
-void FaserVTrackInformation::SetBaseISFParticle(const ISF::FaserISFParticle* /*p*/)
+void FaserVTrackInformation::SetBaseISFParticle(ISF::FaserISFParticle* /*p*/)
 {
   // you should not call this, perhaps throw an exception?
   std::cerr<<"ERROR  FaserVTrackInformation::SetBaseISFParticle() not supported  "<<std::endl;
@@ -52,3 +40,4 @@ void FaserVTrackInformation::SetReturnedToISF(bool)
 {
   std::cerr<<"ERROR  FaserVTrackInformation::SetReturnedToISF() not supported  "<<std::endl;
 }
+
diff --git a/Simulation/G4Sim/FaserMCTruthBase/src/FaserTruthStrategyManager.cxx b/Simulation/G4Sim/FaserMCTruthBase/src/FaserTruthStrategyManager.cxx
index d81de897..925163d5 100644
--- a/Simulation/G4Sim/FaserMCTruthBase/src/FaserTruthStrategyManager.cxx
+++ b/Simulation/G4Sim/FaserMCTruthBase/src/FaserTruthStrategyManager.cxx
@@ -18,7 +18,7 @@
 #include "G4VSolid.hh"
 
 // Truth-related includes
-#include "FaserMCTruth/FaserEventInformation.h"
+#include "FaserMCTruth/FaserG4EventUserInfo.h"
 // #include "FaserMCTruth/FaserTrackHelper.h"
 
 // ISF includes
@@ -50,9 +50,23 @@ bool FaserTruthStrategyManager::CreateTruthIncident(const G4Step* aStep, int sub
 {
   FaserDetDescr::FaserRegion geoID = iGeant4::FaserISFG4GeoHelper::nextGeoId(aStep, subDetVolLevel);
 
-  auto* eventInfo = static_cast<FaserEventInformation*> (G4EventManager::GetEventManager()->GetConstCurrentEvent()->GetUserInformation());
+  auto* eventInfo = static_cast<FaserG4EventUserInfo*> (G4EventManager::GetEventManager()->GetConstCurrentEvent()->GetUserInformation());
 
-  iGeant4::FaserGeant4TruthIncident truth(aStep, geoID, eventInfo);
+  // This is pretty ugly and but necessary because the Geant4TruthIncident
+  // requires an ISFParticle at this point.
+  // TODO: cleanup Geant4TruthIncident to not require an ISFParticle instance any longer
+  const Amg::Vector3D myPos(0,0,0);
+  const Amg::Vector3D myMom(0,0,0);
+  double myMass = 0.0;
+  double myCharge = 0.0;
+  int    myPdgCode = 0;
+  int    mystatus = 3333;
+  double myTime =0.;
+  const ISF::FaserDetRegionSvcIDPair origin(geoID, ISF::fUndefinedSimID);
+  int myBCID = 0;
+  ISF::FaserISFParticle myISFParticle(myPos, myMom, myMass, myCharge, myPdgCode, mystatus, myTime, origin, myBCID);
+
+  iGeant4::FaserGeant4TruthIncident truth(aStep, myISFParticle, geoID, eventInfo);
 
   m_truthSvc->registerTruthIncident(truth);
   return false;
diff --git a/Simulation/G4Utilities/G4UserActions/CMakeLists.txt b/Simulation/G4Utilities/G4UserActions/CMakeLists.txt
index b9243218..c2e1dcee 100644
--- a/Simulation/G4Utilities/G4UserActions/CMakeLists.txt
+++ b/Simulation/G4Utilities/G4UserActions/CMakeLists.txt
@@ -17,7 +17,7 @@ atlas_add_component( G4UserActions
                      src/*.cxx
                      src/components/*.cxx
                      INCLUDE_DIRS ${ROOT_INCLUDE_DIRS} ${XERCESC_INCLUDE_DIRS} ${GEANT4_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS} ${TBB_INCLUDE_DIRS}
-                     LINK_LIBRARIES ${ROOT_LIBRARIES} ${XERCESC_LIBRARIES} ${GEANT4_LIBRARIES} ${CLHEP_LIBRARIES} ${TBB_LIBRARIES} AthenaBaseComps AthenaKernel StoreGateLib SGtests GaudiKernel G4AtlasInterfaces G4AtlasToolsLib EventInfo TrackerSimEvent ScintSimEvent FaserMCTruth FaserMCTruthBaseLib SimHelpers TrackWriteFastSimLib PathResolver G4DebuggingHelperLib)
+                     LINK_LIBRARIES ${ROOT_LIBRARIES} ${XERCESC_LIBRARIES} ${GEANT4_LIBRARIES} ${CLHEP_LIBRARIES} ${TBB_LIBRARIES} AthenaBaseComps AthenaKernel StoreGateLib SGtests GaudiKernel G4AtlasInterfaces G4AtlasToolsLib EventInfo TrackerSimEvent ScintSimEvent FaserMCTruth FaserMCTruthBaseLib TruthUtils SimHelpers TrackWriteFastSimLib PathResolver G4DebuggingHelperLib)
 
 
 # Install files from the package:
diff --git a/Simulation/G4Utilities/G4UserActions/src/AthenaDebugStackingAction.cxx b/Simulation/G4Utilities/G4UserActions/src/AthenaDebugStackingAction.cxx
index 237e6208..a2b6cef8 100644
--- a/Simulation/G4Utilities/G4UserActions/src/AthenaDebugStackingAction.cxx
+++ b/Simulation/G4Utilities/G4UserActions/src/AthenaDebugStackingAction.cxx
@@ -14,7 +14,7 @@
 #include "FaserMCTruth/FaserPrimaryParticleInformation.h"
 #include "FaserMCTruth/FaserTrackInformation.h"
 #include "FaserMCTruth/FaserTrackBarcodeInfo.h"
-#include "FaserMCTruth/FaserEventInformation.h"
+#include "FaserMCTruth/FaserG4EventUserInfo.h"
 
 // Geant4 includes
 #include "G4Track.hh"
@@ -49,13 +49,10 @@ namespace G4UA
       return fKill;
     }
 
-    // TODO: this terrible, evil code should REALLY be changed!!!
-    G4Track* mutableTrack = const_cast<G4Track*> (track);
-
     // TODO: Why is this here? Can I remove it?
     G4Event* ev = G4EventManager::GetEventManager()->GetNonconstCurrentEvent();
-    FaserEventInformation* eventInfo __attribute__ ((unused)) =
-      static_cast<FaserEventInformation*> (ev->GetUserInformation());
+    FaserG4EventUserInfo* eventInfo __attribute__ ((unused)) =
+      static_cast<FaserG4EventUserInfo*> (ev->GetUserInformation());
 
     // Was track subject to a RR?
     // bool rouletted = false;
@@ -111,20 +108,20 @@ namespace G4UA
       if(ppi) {
         if (!m_config.isISFJob) {
           // don't do anything
-          const HepMC::GenParticle* part = ppi->GetHepMCParticle();
+          auto part = ppi->GetHepMCParticle();
           if(part) {
             // OK, we got back to HepMC
             std::unique_ptr<FaserTrackInformation> ti = std::make_unique<FaserTrackInformation>(part);
             ti->SetRegenerationNr(0);
             ti->SetClassification(Primary);
             // regNr=0 and classify=Primary are default values anyway
-            mutableTrack->SetUserInformation(ti.release()); /// Pass ownership to mutableTrack
+            track->SetUserInformation(ti.release()); /// Pass ownership to mutableTrack
           }
           // What does this condition mean?
-          else if(ppi->GetParticleBarcode() >= 0) {
+          else if(ppi->GetParticleBarcode() >= 0 && ppi->GetParticleBarcode() >= 0) {
             // PrimaryParticleInformation should at least provide a barcode
-            std::unique_ptr<FaserTrackBarcodeInfo> bi = std::make_unique<FaserTrackBarcodeInfo>(ppi->GetParticleBarcode());
-            mutableTrack->SetUserInformation(bi.release()); /// Pass ownership to mutableTrack
+            std::unique_ptr<FaserTrackBarcodeInfo> bi = std::make_unique<FaserTrackBarcodeInfo>(ppi->GetParticleUniqueID(), ppi->GetParticleBarcode());
+            track->SetUserInformation(bi.release()); /// Pass ownership to mutableTrack
           }
         } // no ISFParticle attached
       } // has PrimaryParticleInformation
diff --git a/Simulation/G4Utilities/G4UserActions/src/AthenaStackingAction.cxx b/Simulation/G4Utilities/G4UserActions/src/AthenaStackingAction.cxx
index 92cc340d..7afa7ca3 100644
--- a/Simulation/G4Utilities/G4UserActions/src/AthenaStackingAction.cxx
+++ b/Simulation/G4Utilities/G4UserActions/src/AthenaStackingAction.cxx
@@ -14,7 +14,7 @@
 #include "FaserMCTruth/FaserPrimaryParticleInformation.h"
 #include "FaserMCTruth/FaserTrackInformation.h"
 #include "FaserMCTruth/FaserTrackBarcodeInfo.h"
-#include "FaserMCTruth/FaserEventInformation.h"
+#include "FaserMCTruth/FaserG4EventUserInfo.h"
 
 // Geant4 includes
 #include "G4Track.hh"
@@ -68,13 +68,10 @@ namespace G4UA
       return fKill;
     }
 
-    // TODO: this terrible, evil code should REALLY be changed!!!
-    G4Track* mutableTrack = const_cast<G4Track*> (track);
-
     // TODO: Why is this here? Can I remove it?
     G4Event* ev = G4EventManager::GetEventManager()->GetNonconstCurrentEvent();
-    FaserEventInformation* eventInfo __attribute__ ((unused)) =
-      static_cast<FaserEventInformation*> (ev->GetUserInformation());
+    FaserG4EventUserInfo* eventInfo __attribute__ ((unused)) =
+      static_cast<FaserG4EventUserInfo*> (ev->GetUserInformation());
 
     // Neutron Russian Roulette
     // if (m_config.applyNRR && isNeutron(track) &&
@@ -111,20 +108,20 @@ namespace G4UA
       if(ppi) {
         if (!m_config.isISFJob) {
           // don't do anything
-          const HepMC::GenParticle* part = ppi->GetHepMCParticle();
+          auto part = ppi->GetHepMCParticle();
           if(part) {
             // OK, we got back to HepMC
             std::unique_ptr<FaserTrackInformation> ti = std::make_unique<FaserTrackInformation>(part);
             ti->SetRegenerationNr(0);
             ti->SetClassification(Primary);
             // regNr=0 and classify=Primary are default values anyway
-            mutableTrack->SetUserInformation(ti.release()); /// Pass ownership to mutableTrack
+            track->SetUserInformation(ti.release()); /// Pass ownership to mutableTrack
           }
           // What does this condition mean?
-          else if(ppi->GetParticleBarcode() >= 0) {
+          else if(ppi->GetParticleBarcode() >= 0 && ppi->GetParticleBarcode() >= 0) {
             // PrimaryParticleInformation should at least provide a barcode
-            std::unique_ptr<FaserTrackBarcodeInfo> bi = std::make_unique<FaserTrackBarcodeInfo>(ppi->GetParticleBarcode());
-            mutableTrack->SetUserInformation(bi.release()); /// Pass ownership to mutableTrack
+            std::unique_ptr<FaserTrackBarcodeInfo> bi = std::make_unique<FaserTrackBarcodeInfo>(ppi->GetParticleUniqueID(), ppi->GetParticleBarcode());
+            track->SetUserInformation(bi.release()); /// Pass ownership to mutableTrack
           }
         } // no ISFParticle attached
       } // has PrimaryParticleInformation
diff --git a/Simulation/G4Utilities/G4UserActions/src/AthenaTrackingAction.cxx b/Simulation/G4Utilities/G4UserActions/src/AthenaTrackingAction.cxx
index 813d5c3d..6370f579 100644
--- a/Simulation/G4Utilities/G4UserActions/src/AthenaTrackingAction.cxx
+++ b/Simulation/G4Utilities/G4UserActions/src/AthenaTrackingAction.cxx
@@ -9,7 +9,7 @@
 #include "G4Event.hh"
 #include "G4EventManager.hh"
 
-#include "FaserMCTruth/FaserEventInformation.h"
+#include "FaserMCTruth/FaserG4EventUserInfo.h"
 #include "FaserMCTruth/FaserPrimaryParticleInformation.h"
 #include "FaserMCTruth/FaserTrackHelper.h"
 #include "FaserMCTruth/FaserTrackInformation.h"
@@ -28,7 +28,7 @@ namespace G4UA
     , m_secondarySavingLevel(secondarySavingLevel)
     , m_subDetVolLevel(subDetVolLevel)
   {
-    m_msg.get().setLevel(lvl);
+    setLevel(lvl);
   }
 
   //---------------------------------------------------------------------------
@@ -46,12 +46,10 @@ namespace G4UA
     {
       // Why a const_cast???
       // This is an ugly way to communicate the GenParticle...
-      HepMC::GenParticle* part =
-        const_cast<HepMC::GenParticle*>( trackHelper.GetTrackInformation()->
-                                         GetHepMCParticle() );
+      HepMC::GenParticlePtr part = trackHelper.GetTrackInformation()->GetHepMCParticle();
 
       // Assign the GenParticle to the EventInformation.
-      FaserEventInformation* eventInfo = static_cast<FaserEventInformation*>
+      FaserG4EventUserInfo* eventInfo = static_cast<FaserG4EventUserInfo*>
         (G4EventManager::GetEventManager()->GetConstCurrentEvent()->GetUserInformation());
       if (trackHelper.IsPrimary()) eventInfo->SetCurrentPrimary(part);
       eventInfo->SetCurrentlyTraced(part);
diff --git a/Simulation/G4Utilities/G4UserActions/src/LooperKiller.h b/Simulation/G4Utilities/G4UserActions/src/LooperKiller.h
index 6463cf8b..720c8c03 100644
--- a/Simulation/G4Utilities/G4UserActions/src/LooperKiller.h
+++ b/Simulation/G4Utilities/G4UserActions/src/LooperKiller.h
@@ -8,7 +8,6 @@
 #include "GaudiKernel/ServiceHandle.h"
 
 // Infrastructure includes
-#include "AthenaKernel/MsgStreamMember.h"
 #include "G4UserSteppingAction.hh"
 #include "AthenaBaseComps/AthMessaging.h"
 
diff --git a/Simulation/ISF/ISF_Core/FaserISF_Event/FaserISF_Event/IFaserTruthIncident.h b/Simulation/ISF/ISF_Core/FaserISF_Event/FaserISF_Event/IFaserTruthIncident.h
index af7996c2..0627b05d 100644
--- a/Simulation/ISF/ISF_Core/FaserISF_Event/FaserISF_Event/IFaserTruthIncident.h
+++ b/Simulation/ISF/ISF_Core/FaserISF_Event/FaserISF_Event/IFaserTruthIncident.h
@@ -75,9 +75,14 @@ namespace ISF {
     virtual int                       parentPdgCode() const = 0;
     /** Return the parent particle as a HepMC particle type
         (only called for particles that will enter the HepMC truth event) */
-    virtual HepMC::GenParticlePtr     parentParticle() const = 0;
+    virtual HepMC::GenParticlePtr     parentParticle() = 0;
     /** Return the barcode of the parent particle */
-    virtual Barcode::ParticleBarcode  parentBarcode() const = 0;
+    virtual Barcode::ParticleBarcode  parentBarcode() = 0;
+
+    /** Return the bunch-crossing identifier of the parent particle */
+    virtual int                       parentBCID() const = 0;
+    /** Return the status of the parent particle */
+    virtual int                       parentStatus() = 0;
     /** Return a boolean whether or not the parent particle survives the incident */
     virtual bool                      parentSurvivesIncident() const = 0;
     /** Return the parent particle after the TruthIncident vertex (and assign
diff --git a/Simulation/ISF/ISF_Geant4/FaserISF_Geant4Event/FaserISF_Geant4Event/FaserGeant4TruthIncident.h b/Simulation/ISF/ISF_Geant4/FaserISF_Geant4Event/FaserISF_Geant4Event/FaserGeant4TruthIncident.h
index 33a52779..8bbe448a 100644
--- a/Simulation/ISF/ISF_Geant4/FaserISF_Geant4Event/FaserISF_Geant4Event/FaserGeant4TruthIncident.h
+++ b/Simulation/ISF/ISF_Geant4/FaserISF_Geant4Event/FaserISF_Geant4Event/FaserGeant4TruthIncident.h
@@ -17,10 +17,17 @@
 //Geant4 includes
 #include "G4ThreeVector.hh"
 
+#include "CxxUtils/checker_macros.h"
+
 // forward declarations
 class G4Step;
 class G4Track;
-class FaserEventInformation;
+class FaserG4EventUserInfo;
+
+namespace ISF {
+  class FaserISFParticle;
+}
+
 
 namespace iGeant4 {
 
@@ -34,8 +41,9 @@ namespace iGeant4 {
   class FaserGeant4TruthIncident : public ISF::IFaserTruthIncident {
     public:
       FaserGeant4TruthIncident( const G4Step*,
+                           const ISF::FaserISFParticle& baseISP,
                            FaserDetDescr::FaserRegion geoID,
-                           FaserEventInformation* eventInfo);
+                           FaserG4EventUserInfo* eventInfo);
       virtual ~FaserGeant4TruthIncident() {};
 
       /** Return HepMC position of the truth vertex */
@@ -55,12 +63,16 @@ namespace iGeant4 {
       /** Return the PDG Code of the parent particle */
       int                       parentPdgCode() const override final;
       /** Return the barcode of the parent particle */
-      Barcode::ParticleBarcode  parentBarcode() const override final;
+      Barcode::ParticleBarcode  parentBarcode() override final;
+      /** Return the bunch-crossing identifier of the parent particle */
+      int                       parentBCID() const override final;
+      /** Return the status of the parent particle */
+      int  parentStatus() override final;
       /** Return a boolean whether or not the parent particle survives the incident */
       bool                      parentSurvivesIncident() const override final;
       /** Return the parent particle after the TruthIncident vertex (and give
           it a new barcode) */
-      HepMC::GenParticle*       parentParticleAfterIncident(Barcode::ParticleBarcode newBC) override final;
+      HepMC::GenParticlePtr       parentParticleAfterIncident(Barcode::ParticleBarcode newBC) override final;
 
       /** Return p of the i-th child particle */
       const G4ThreeVector       childP(unsigned short index) const;
@@ -72,6 +84,8 @@ namespace iGeant4 {
       double                    childEkin(unsigned short index) const override final;
       /** Return the PDG Code of the i-th child particle */
       int                       childPdgCode(unsigned short index) const override final;
+      /** Return the barcode of the i-th child particle (if defined as part of the TruthIncident) otherwise return 0 */
+      Barcode::ParticleBarcode  childBarcode(unsigned short index) const override final; // TODO Remove - only used in one place in TruthSvc
       /** Set the the barcode of all child particles to the given bc */
       void                      setAllChildrenBarcodes(Barcode::ParticleBarcode bc) override final;
 
@@ -87,36 +101,36 @@ namespace iGeant4 {
       // only called once accepted
 
       /** Return the parent particle as a HepMC particle type */
-      HepMC::GenParticle*       parentParticle() const override final;
+      HepMC::GenParticlePtr       parentParticle() override final;
       /** Return the i-th child as a HepMC particle type and assign the given
           Barcode to the simulator particle */
-      HepMC::GenParticle*       childParticle(unsigned short index,
+      HepMC::GenParticlePtr       childParticle(unsigned short index,
                                               Barcode::ParticleBarcode bc) const override final;
       /** Update the properties of a child particle from a pre-defined
           interaction based on the properties of the ith child of the
           current TruthIncident (only used in quasi-stable particle
           simulation). */
-      HepMC::GenParticle* updateChildParticle(unsigned short index,
-                                              HepMC::GenParticle *existingChild) const override final;
+      HepMC::GenParticlePtr updateChildParticle(unsigned short index,
+                                              HepMC::GenParticlePtr existingChild) const override final;
     private:
       FaserGeant4TruthIncident();
       /** prepare the child particles */
-      inline void prepareChildren() const;
+      inline void prepareChildren();
 
       /** check if the given G4Track represents a particle that is alive in ISF or ISF-G4 */
       inline bool particleAlive(const G4Track *track) const;
 
-      HepMC::GenParticle* convert(const G4Track *particle, const int barcode, const bool secondary) const; //*AS* might be put static
+      HepMC::GenParticlePtr convert(const G4Track *particle, const int barcode, const bool secondary) const; //*AS* might be put static
 
-      mutable bool                  m_positionSet;
-      mutable HepMC::FourVector     m_position;
+      bool                  m_positionSet;
+      HepMC::FourVector     m_position;
       const G4Step*                 m_step;
+      const ISF::FaserISFParticle&  m_baseISP;
 
-      FaserEventInformation*        m_eventInfo;
-      mutable bool                  m_childrenPrepared;
-      mutable std::vector<const G4Track*> m_children;
+      FaserG4EventUserInfo*         m_faserG4EvtUserInfo ATLAS_THREAD_SAFE{};
+      std::vector<const G4Track*>   m_children;
 
-      HepMC::GenParticle*           m_parentParticleAfterIncident;
+      HepMC::GenParticlePtr         m_parentParticleAfterIncident;
    };
 
 }
diff --git a/Simulation/ISF/ISF_Geant4/FaserISF_Geant4Event/FaserISF_Geant4Event/FaserISFG4Helper.h b/Simulation/ISF/ISF_Geant4/FaserISF_Geant4Event/FaserISF_Geant4Event/FaserISFG4Helper.h
index 33211d1e..23b60e90 100644
--- a/Simulation/ISF/ISF_Geant4/FaserISF_Geant4Event/FaserISF_Geant4Event/FaserISFG4Helper.h
+++ b/Simulation/ISF/ISF_Geant4/FaserISF_Geant4Event/FaserISF_Geant4Event/FaserISFG4Helper.h
@@ -15,9 +15,8 @@
 #include "FaserMCTruth/FaserVTrackInformation.h"
 
 // forward declarations
-namespace HepMC {
-  class GenParticle;
-}
+#include "AtlasHepMC/GenParticle_fwd.h"
+
 namespace ISF {
   class TruthBinding;
 }
@@ -49,9 +48,9 @@ class FaserISFG4Helper {
   /** attach a new TrackInformation object to the given new (!) G4Track
    *  (the G4Track must not have a UserInformation object attached to it) */
   static FaserTrackInformation* attachTrackInfoToNewG4Track( G4Track& aTrack,
-                                   const ISF::FaserISFParticle& baseIsp,
+                                   ISF::FaserISFParticle& baseIsp,
                                    TrackClassification classification,
-                                   HepMC::GenParticle *nonRegeneratedTruthParticle = nullptr);
+                                   HepMC::GenParticlePtr nonRegeneratedTruthParticle = nullptr);
   
   /** return pointer to current EventInformation */
   static FaserEventInformation* getEventInformation();
diff --git a/Simulation/ISF/ISF_Geant4/FaserISF_Geant4Event/src/FaserGeant4TruthIncident.cxx b/Simulation/ISF/ISF_Geant4/FaserISF_Geant4Event/src/FaserGeant4TruthIncident.cxx
index 3af3e2fa..2d584d02 100644
--- a/Simulation/ISF/ISF_Geant4/FaserISF_Geant4Event/src/FaserGeant4TruthIncident.cxx
+++ b/Simulation/ISF/ISF_Geant4/FaserISF_Geant4Event/src/FaserGeant4TruthIncident.cxx
@@ -9,7 +9,7 @@
 #include "FaserISF_Geant4Event/FaserISFG4Helper.h"
 
 // Atlas G4 Helpers
-#include "FaserMCTruth/FaserEventInformation.h"
+#include "FaserMCTruth/FaserG4EventUserInfo.h"
 #include "FaserMCTruth/FaserTrackBarcodeInfo.h"
 #include "FaserMCTruth/FaserTrackHelper.h"
 #include "FaserMCTruth/FaserTrackInformation.h"
@@ -20,6 +20,7 @@
 
 // HepMC includes
 #include "AtlasHepMC/GenParticle.h"
+#include "TruthUtils/MagicNumbers.h"
 
 // Geant4 includes
 #include "G4Step.hh"
@@ -36,6 +37,11 @@
 #include "G4EventManager.hh"
 #include "G4Event.hh"
 
+// ISF includes
+#include "FaserISF_Event/FaserISFParticle.h"
+
+
+
 /*
   Comments:
   what about parent particle surviving (e.g. bremstrahlung)
@@ -57,29 +63,29 @@
 
 
 iGeant4::FaserGeant4TruthIncident::FaserGeant4TruthIncident( const G4Step *step,
+                                               const ISF::FaserISFParticle& baseISP,
                                                FaserDetDescr::FaserRegion geoID,
-                                               FaserEventInformation *eventInfo) :
+                                               FaserG4EventUserInfo *faserG4EventUserInfo) :
   IFaserTruthIncident(geoID, step->GetSecondaryInCurrentStep()->size()), // switch to G4Step::GetNumberOfSecondariesInCurrentStep() once we're using G4 10.2 or later
   m_positionSet(false),
   m_position(),
   m_step(step),
-  m_eventInfo(eventInfo),
-  m_childrenPrepared(false),
-  m_children(),
-  m_parentParticleAfterIncident(nullptr)
+  m_baseISP(baseISP),
+  m_faserG4EvtUserInfo(faserG4EventUserInfo)
 {
+  // prepare children:
+  prepareChildren();
+
+  // calculate position:
+  const G4StepPoint *postStepPoint = m_step->GetPostStepPoint();
+  const G4ThreeVector         &pos = postStepPoint->GetPosition();
+  const G4double              time = postStepPoint->GetGlobalTime()*Gaudi::Units::c_light;
+  m_position.set( pos.x(), pos.y(), pos.z(), time );
 }
 
-const HepMC::FourVector& iGeant4::FaserGeant4TruthIncident::position() const {
-  if (!m_positionSet) {
-    // post step processes:
-    const G4StepPoint *postStepPoint = m_step->GetPostStepPoint();
-    const G4ThreeVector         &pos = postStepPoint->GetPosition();
-    const G4double              time = postStepPoint->GetGlobalTime()*Gaudi::Units::c_light;
-    m_position.set( pos.x(), pos.y(), pos.z(), time );
-    m_positionSet = true;
-  }
 
+const HepMC::FourVector& iGeant4::FaserGeant4TruthIncident::position() const 
+{
   return m_position;
 }
 
@@ -113,18 +119,27 @@ int iGeant4::FaserGeant4TruthIncident::parentPdgCode() const {
   return  m_step->GetTrack()->GetDefinition()->GetPDGEncoding();
 }
 
-Barcode::ParticleBarcode iGeant4::FaserGeant4TruthIncident::parentBarcode() const {
+Barcode::ParticleBarcode iGeant4::FaserGeant4TruthIncident::parentBarcode() {
   auto parent = parentParticle();
 
-  return (parent) ? parent->barcode() : Barcode::fUndefinedBarcode;
+  return (parent) ? HepMC::barcode(parent) : Barcode::fUndefinedBarcode;
 }
 
-HepMC::GenParticle* iGeant4::FaserGeant4TruthIncident::parentParticle() const {
-  HepMC::GenParticle* hepParticle = m_eventInfo->GetCurrentlyTraced();
+int iGeant4::FaserGeant4TruthIncident::parentStatus()  {
+ auto parent = parentParticle();
 
-  return hepParticle;
+ return (parent) ? parent->status() : 0;
+}
+
+HepMC::GenParticlePtr iGeant4::FaserGeant4TruthIncident::parentParticle() {
+  return m_faserG4EvtUserInfo->GetCurrentlyTraced();
+}
+
+int iGeant4::FaserGeant4TruthIncident::parentBCID() const { 
+  return m_baseISP.getBCID();
 }
 
+
 bool iGeant4::FaserGeant4TruthIncident::parentSurvivesIncident() const { 
   const G4Track *track = m_step->GetTrack();
 
@@ -136,7 +151,7 @@ bool iGeant4::FaserGeant4TruthIncident::parentSurvivesIncident() const {
   }
 }
 
-HepMC::GenParticle* iGeant4::FaserGeant4TruthIncident::parentParticleAfterIncident(Barcode::ParticleBarcode newBarcode) {
+HepMC::GenParticlePtr iGeant4::FaserGeant4TruthIncident::parentParticleAfterIncident(Barcode::ParticleBarcode newBarcode) {
   const G4Track *track = m_step->GetTrack();
 
   // check if particle is a alive in G4 or in ISF
@@ -151,14 +166,14 @@ HepMC::GenParticle* iGeant4::FaserGeant4TruthIncident::parentParticleAfterIncide
     // from G4DynamicParticle (which should be equivalent to postStep)
     m_parentParticleAfterIncident = convert(track, newBarcode, false);
     
-    m_eventInfo->SetCurrentlyTraced( m_parentParticleAfterIncident );
+    m_faserG4EvtUserInfo->SetCurrentlyTraced( m_parentParticleAfterIncident );
     
     // store (new) hepmc particle in track's UserInformation
     FaserTrackHelper       tHelper(track);
     FaserTrackInformation *tInfo = tHelper.GetTrackInformation();
     if (tInfo) {
-      // do NOT update the FaserTrackInformation for regenerated particles!
-      // (most recent truth info is kept in FaserEventInformation)
+      // do NOT update the TrackInformation for regenerated particles!
+      // (most recent truth info is kept in AtlasG4EventUserInfo)
       //tInfo->SetParticle( m_parentParticleAfterIncident );
       int regenerationNr = tInfo->GetRegenerationNr();
       regenerationNr++;
@@ -176,43 +191,53 @@ HepMC::GenParticle* iGeant4::FaserGeant4TruthIncident::parentParticleAfterIncide
 }
 
 double iGeant4::FaserGeant4TruthIncident::childP2(unsigned short i) const {
-  prepareChildren();
   const G4ThreeVector & mom= m_children[i]->GetMomentum();
   return mom.mag2();
 }
 
 const G4ThreeVector iGeant4::FaserGeant4TruthIncident::childP(unsigned short i) const {
-  prepareChildren();
   const G4ThreeVector & mom= m_children[i]->GetMomentum();
   return mom;
 }
 
 double iGeant4::FaserGeant4TruthIncident::childPt2(unsigned short i) const {
-  prepareChildren();
   const G4ThreeVector & mom= m_children[i]->GetMomentum();
   return mom.perp2();
 }
 
 double iGeant4::FaserGeant4TruthIncident::childEkin(unsigned short i) const {
-  prepareChildren();
   return (m_children[i]->GetKineticEnergy()/CLHEP::MeV);
 }
 
 int iGeant4::FaserGeant4TruthIncident::childPdgCode(unsigned short i) const {
-  prepareChildren();
   return m_children[i]->GetDefinition()->GetPDGEncoding();
 }
 
+Barcode::ParticleBarcode  iGeant4::FaserGeant4TruthIncident::childBarcode(unsigned short index) const {
+  // the G4Track instance for the current child particle
+  const G4Track* track = m_children[index];
+  // This should be a *secondary* track.  If it has a primary, it was a decay and
+  //  we are running with quasi-stable particle simulation.  Note that if the primary
+  //  track is passed in as a secondary that survived the interaction, then this was
+  //  *not* a decay and we should not treat it in this way
+  if (track->GetDynamicParticle() &&
+      track->GetDynamicParticle()->GetPrimaryParticle() &&
+      track->GetDynamicParticle()->GetPrimaryParticle()->GetUserInformation()){
+    // Then the new particle should use the same barcode as the old one!!
+    FaserPrimaryParticleInformation* ppi = dynamic_cast<FaserPrimaryParticleInformation*>( track->GetDynamicParticle()->GetPrimaryParticle()->GetUserInformation() );
+    return ppi->GetParticleBarcode();
+  }
+  return 0;
+}
+
 void iGeant4::FaserGeant4TruthIncident::setAllChildrenBarcodes(Barcode::ParticleBarcode) {
   G4ExceptionDescription description;
   description << G4String("setAllChildrenBarcodes: ") + "Shared child particle barcodes are not implemented in ISF_Geant4 at this point.";
-  G4Exception("iGeant4::FaserGeant4TruthIncident", "NotImplemented", FatalException, description);
+  G4Exception("iGeant4::Geant4TruthIncident", "NotImplemented", FatalException, description);
 }
 
-HepMC::GenParticle* iGeant4::FaserGeant4TruthIncident::childParticle(unsigned short i,
-                                                            Barcode::ParticleBarcode newBarcode) const {
-  prepareChildren();
-
+HepMC::GenParticlePtr iGeant4::FaserGeant4TruthIncident::childParticle(unsigned short i,
+                                                                  Barcode::ParticleBarcode newBarcode) const {
   // the G4Track instance for the current child particle
   const G4Track* thisChildTrack = m_children[i];
 
@@ -220,17 +245,16 @@ HepMC::GenParticle* iGeant4::FaserGeant4TruthIncident::childParticle(unsigned sh
   //     secondary could decay right away and create further particles which pass the
   //     truth strategies.
 
-  HepMC::GenParticle* hepParticle = convert( thisChildTrack , newBarcode , true );
-
+  HepMC::GenParticlePtr hepParticle = convert( thisChildTrack, newBarcode, true );
   FaserTrackHelper tHelper(thisChildTrack);
   FaserTrackInformation *trackInfo = tHelper.GetTrackInformation();
 
   // needed to make AtlasG4 work with ISF TruthService
-  if(trackInfo==nullptr) {
-    trackInfo = new FaserTrackInformation( hepParticle );    
-    thisChildTrack->SetUserInformation( trackInfo );    
-  } 
-    
+  if (trackInfo==nullptr) {
+    trackInfo = new FaserTrackInformation( hepParticle );
+    thisChildTrack->SetUserInformation( trackInfo );
+  }
+
   trackInfo->SetParticle(hepParticle);
   trackInfo->SetClassification(RegisteredSecondary);
   trackInfo->SetRegenerationNr(0);
@@ -239,10 +263,8 @@ HepMC::GenParticle* iGeant4::FaserGeant4TruthIncident::childParticle(unsigned sh
 }
 
 
-HepMC::GenParticle* iGeant4::FaserGeant4TruthIncident::updateChildParticle(unsigned short index,
-                                                                      HepMC::GenParticle *existingChild) const {
-  prepareChildren();
-
+HepMC::GenParticlePtr iGeant4::FaserGeant4TruthIncident::updateChildParticle(unsigned short index,
+                                                                        HepMC::GenParticlePtr existingChild) const {
   // the G4Track instance for the current child particle
   const G4Track* thisChildTrack = m_children[index];
 
@@ -259,7 +281,7 @@ HepMC::GenParticle* iGeant4::FaserGeant4TruthIncident::updateChildParticle(unsig
   if(existingChild->pdg_id()!=pdgCode) {
     G4ExceptionDescription description;
     description << G4String("updateChildParticle: ") + "Wrong PDG ID mismatch between G4Track and GenParticle";
-    G4Exception("iGeant4::FaserGeant4TruthIncident", "PDGIDMisMatch", FatalException, description);
+    G4Exception("iGeant4::Geant4TruthIncident", "PDGIDMisMatch", FatalException, description);
   }
   existingChild->set_momentum(fourMomentum);
 
@@ -299,18 +321,29 @@ bool iGeant4::FaserGeant4TruthIncident::particleAlive(const G4Track *track) cons
   return true;
 }
 
-
-HepMC::GenParticle* iGeant4::FaserGeant4TruthIncident::convert(const G4Track *track, const int barcode, const bool secondary) const {
+#ifdef HEPMC3
+HepMC::GenParticlePtr iGeant4::FaserGeant4TruthIncident::convert(const G4Track *track, const int, const bool secondary) const {
+#else
+HepMC::GenParticlePtr iGeant4::FaserGeant4TruthIncident::convert(const G4Track *track, const int barcode, const bool secondary) const {
+#endif
 
   const G4ThreeVector & mom =  track->GetMomentum();
   const double energy =  track->GetTotalEnergy();
   const int pdgCode = track->GetDefinition()->GetPDGEncoding();
   const HepMC::FourVector fourMomentum( mom.x(), mom.y(), mom.z(), energy);
 
-  const int status = 1; // stable particle not decayed by EventGenerator
-  HepMC::GenParticle* newParticle = new HepMC::GenParticle(fourMomentum, pdgCode, status);
+  const HepMC::GenParticlePtr parent = m_faserG4EvtUserInfo->GetCurrentlyTraced();
+  int status = (secondary) ? 1 + HepMC::SIM_STATUS_THRESHOLD : parent->status() + HepMC::SIM_STATUS_INCREMENT;
+  // Treat child particles of pre-defined decays differently
+  if (this->interactionClassification() == ISF::QS_PREDEF_VTX) {
+    const G4DynamicParticle* dynPart = track->GetDynamicParticle();
+    bool hasPredefinedDecay = (dynPart && (nullptr!=(dynPart->GetPreAssignedDecayProducts())));
+    status = (hasPredefinedDecay)? 2 : 1;
+  }
+  HepMC::GenParticlePtr newParticle = HepMC::newGenParticlePtr(fourMomentum, pdgCode, status);
 
-  // This should be a *secondary* track.  If it has a primary, it was a decay and 
+#ifndef HEPMC3
+  // This should be a *secondary* track.  If it has a primary, it was a decay and
   //  we are running with quasi-stable particle simulation.  Note that if the primary
   //  track is passed in as a secondary that survived the interaction, then this was
   //  *not* a decay and we should not treat it in this way
@@ -319,27 +352,24 @@ HepMC::GenParticle* iGeant4::FaserGeant4TruthIncident::convert(const G4Track *tr
       track->GetDynamicParticle()->GetPrimaryParticle() &&
       track->GetDynamicParticle()->GetPrimaryParticle()->GetUserInformation()){
     // Then the new particle should use the same barcode as the old one!!
-    FaserPrimaryParticleInformation* ppi = dynamic_cast<FaserPrimaryParticleInformation*>( track->GetDynamicParticle()->GetPrimaryParticle()->GetUserInformation() );
-    newParticle->suggest_barcode( ppi->GetParticleBarcode() );
+    PrimaryParticleInformation* ppi = dynamic_cast<PrimaryParticleInformation*>( track->GetDynamicParticle()->GetPrimaryParticle()->GetUserInformation() );
+    HepMC::suggest_barcode( newParticle, ppi->GetParticleBarcode() );
   } else {
-    newParticle->suggest_barcode( barcode );
+    HepMC::suggest_barcode( newParticle, barcode );
   }
+#endif
 
   return newParticle;
 }
 
 
-void iGeant4::FaserGeant4TruthIncident::prepareChildren() const {
+void iGeant4::FaserGeant4TruthIncident::prepareChildren() {
 
-  if (!m_childrenPrepared) {
-    unsigned short numChildren = numberOfChildren();
-    const auto &tracks = m_step->GetSecondaryInCurrentStep();
-    const int iSize=tracks->size();
-    const int iLast=iSize-numChildren-1; //NB can be -1.
-    for(int i=iSize-1;i>iLast;i--) {
-      m_children.push_back((*tracks)[i]);
-    }
-    m_childrenPrepared  = true;
+  const std::vector<const G4Track*>* tracks = m_step->GetSecondaryInCurrentStep();
+  const int iSize = tracks->size();
+  const int iLast = iSize - numberOfChildren() - 1; //NB can be -1.
+  for(int i=iSize-1;i>iLast;i--) {
+    m_children.push_back((*tracks)[i]);
   }
 }
 
@@ -372,3 +402,4 @@ ISF::InteractionClass_t iGeant4::FaserGeant4TruthIncident::interactionClassifica
   return classification;
   // end of code to determine interaction type
 }
+
diff --git a/Simulation/ISF/ISF_Geant4/FaserISF_Geant4Event/src/FaserISFG4Helper.cxx b/Simulation/ISF/ISF_Geant4/FaserISF_Geant4Event/src/FaserISFG4Helper.cxx
index 10698d4b..67170505 100644
--- a/Simulation/ISF/ISF_Geant4/FaserISF_Geant4Event/src/FaserISFG4Helper.cxx
+++ b/Simulation/ISF/ISF_Geant4/FaserISF_Geant4Event/src/FaserISFG4Helper.cxx
@@ -41,14 +41,15 @@ iGeant4::FaserISFG4Helper::convertG4TrackToISFParticle(const G4Track& aTrack,
   double charge  = particleDefinition.GetPDGCharge();
   int    pdgID   = particleDefinition.GetPDGEncoding();
 
-  auto* genParticle = (truth) ? truth->getTruthParticle(): nullptr;
-  Barcode::ParticleBarcode barcode = (genParticle) ? genParticle->barcode() : Barcode::fUndefinedBarcode;
+  Barcode::ParticleBarcode barcode = (truth && truth->getTruthParticle() ) ?  HepMC::barcode(truth->getTruthParticle()) : Barcode::fUndefinedBarcode;
+
 
   ISF::FaserISFParticle *isp = new ISF::FaserISFParticle( position,
                                                 momentum,
                                                 mass,
                                                 charge,
                                                 pdgID,
+                                                1,
                                                 gTime,
                                                 parent,
                                                 barcode,
@@ -71,9 +72,9 @@ iGeant4::FaserISFG4Helper::getISFTrackInfo(const G4Track& aTrack)
 /** link the given G4Track to the given ISFParticle */
 FaserTrackInformation*
 iGeant4::FaserISFG4Helper::attachTrackInfoToNewG4Track( G4Track& aTrack,
-                                                        const ISF::FaserISFParticle& baseIsp,
+                                                        ISF::FaserISFParticle& baseIsp,
                                                         TrackClassification classification,
-                                                        HepMC::GenParticle *nonRegeneratedTruthParticle)
+                                                        HepMC::GenParticlePtr nonRegeneratedTruthParticle)
 {
   if ( aTrack.GetUserInformation() ) {
     G4ExceptionDescription description;
diff --git a/package_filters.txt b/package_filters.txt
index 02b44072..a3d9a255 100644
--- a/package_filters.txt
+++ b/package_filters.txt
@@ -77,15 +77,17 @@
 #+Scintillator/ScintEventCnv/ScintSimEventTPCnv
 #+Scintillator/ScintSimEvent
 +Scintillator/.*
-##+Simulation/G4Extensions/Pythia8Decayer
++Simulation/G4Extensions/Pythia8Decayer
 ##+Simulation/G4Faser/G4FaserAlg
 +Simulation/G4Sim/FaserMCTruth
++Simulation/G4Sim/FaserMCTruthBase
 +Simulation/G4Utilities/Geo2G4
 +Simulation/G4Utilities/GeoMaterial2G4
-##+Simulation/G4Utilities/G4UserActions
++Simulation/G4Utilities/G4UserActions
 +Simulation/ISF/ISF_Core/FaserISF_Event
 +Simulation/ISF/ISF_Core/FaserISF_Interfaces
 +Simulation/ISF/ISF_Core/FaserISF_Services
++Simulation/ISF/ISF_Geant4/FaserISF_Geant4Event
 +Simulation/ISF/ISF_HepMC/FaserISF_HepMC_Interfaces
 +Simulation/ISF/ISF_HepMC/FaserISF_HepMC_Tools
 -Simulation/.*
-- 
GitLab