From dc440d64b58e0439738a8fe518f914e428c0bba4 Mon Sep 17 00:00:00 2001
From: Dave Casper <dcasper@uci.edu>
Date: Mon, 23 Mar 2020 13:58:07 +0000
Subject: [PATCH] Fix issues with truth information and reorganize some channel
 IDs

---
 CMakeLists.txt                                |  11 +-
 .../GeoModelTest/src/GeoModelTestAlg.cxx      |  21 +-
 .../GeoModelTest/src/GeoModelTestAlg.h        |   4 +-
 .../DetDescrCnvSvc/DetDescrCnvSvc.h           |   1 +
 .../DetDescrCnvSvc/src/DetDescrCnvSvc.cxx     |   1 +
 .../FaserDetDescr/FaserDetTechnology.h        |  28 +-
 .../FaserDetDescr/FaserDetDescr/FaserRegion.h |  12 +-
 .../FaserDetDescr/src/FaserRegionHelper.cxx   |  12 +-
 .../GeoModel/FaserGeoModel/data/FASER_IDS.xml |   2 +
 .../FaserGeoModel/data/IdDictFASER.xml        |   6 +
 .../GeoModel/FaserGeoModel/data/geomDB.sql    | 396 +++++++----
 .../src/DecodeFaserVersionKey.cxx             |  19 +
 .../GeoModelInterfaces/IGeoDbTagSvc.h         |   4 +
 .../GeoModelInterfaces/IGeoModelSvc.h         |   4 +
 .../GeoModel/GeoModelSvc/src/GeoDbTagSvc.cxx  |   9 +
 .../GeoModel/GeoModelSvc/src/GeoDbTagSvc.h    |  10 +
 .../GeoModel/GeoModelSvc/src/GeoModelSvc.cxx  |  46 +-
 .../GeoModel/GeoModelSvc/src/GeoModelSvc.h    |   6 +
 .../GeoModelSvc/src/RDBMaterialManager.cxx    |  29 +
 .../GeoModelSvc/src/RDBMaterialManager.h      |   2 +
 .../src/IdDictDetDescrCnv.cxx                 | 113 +++-
 .../IdDictDetDescrCnv/src/IdDictDetDescrCnv.h |   8 +-
 .../NeutrinoIdDictFiles/CMakeLists.txt        |  10 +
 .../data/IdDictNeutrino.xml                   |  18 +
 .../src/PreshowerDetectorFactory.cxx          |   1 -
 .../ScintG4/PreshowerG4_SD/CMakeLists.txt     |   4 +-
 .../PreshowerG4_SD/src/PreshowerSensorSD.cxx  |   4 +-
 .../ScintG4/TriggerG4_SD/CMakeLists.txt       |   4 +-
 .../TriggerG4_SD/src/TriggerSensorSD.cxx      |  10 +-
 Scintillator/ScintG4/VetoG4_SD/CMakeLists.txt |   4 +-
 .../ScintG4/VetoG4_SD/src/VetoSensorSD.cxx    |   4 +-
 Simulation/G4Faser/G4FaserAlg/CMakeLists.txt  |  37 +-
 .../G4FaserAlg/python/G4FaserAlgConfigNew.py  | 115 +---
 .../G4Faser/G4FaserAlg/src/G4FaserAlg.cxx     | 433 ++++++++++++
 .../G4Faser/G4FaserAlg/src/G4FaserAlg.h       | 140 ++++
 .../G4FaserAlg/src/G4FaserFluxRecorder.cxx    | 121 ++++
 .../G4FaserAlg/src/G4FaserFluxRecorder.h      |  25 +
 .../src/components/G4FaserAlg_entries.cxx     |   3 +
 .../{G4FaserApp => G4FaserAlg}/test/runG4.py  |  21 +-
 Simulation/G4Faser/G4FaserApp/CMakeLists.txt  |  55 --
 .../G4Faser/G4FaserServices/CMakeLists.txt    |  18 +-
 .../python/G4FaserServicesConfigNew.py        |  14 +-
 .../python/G4FaserUserActionConfigNew.py      |  80 +++
 .../G4FaserServices/src/FaserGeoIDSvc.cxx     |  71 --
 .../components/G4FaserServices_entries.cxx    |   3 -
 .../python/G4FaserToolsConfigNew.py           |  82 +++
 .../G4FaserTools/python/G4FieldConfigNew.py   |  15 +-
 Simulation/G4Sim/FaserMCTruth/CMakeLists.txt  |  30 +
 .../FaserMCTruth/FaserEventInformation.h      |  61 ++
 .../FaserPrimaryParticleInformation.h         |  38 ++
 .../FaserMCTruth/FaserTrackBarcodeInfo.h      |  30 +
 .../FaserMCTruth/FaserTrackHelper.h           |  26 +
 .../FaserMCTruth/FaserTrackInformation.h      |  34 +
 .../FaserMCTruth/FaserTruthController.h       |  28 +
 .../FaserMCTruth/FaserVTrackInformation.h     |  40 ++
 .../FaserMCTruth/FaserMCTruth/TruthEvent.h    |  17 +
 .../src/FaserEventInformation.cxx             |  38 ++
 .../src/FaserPrimaryParticleInformation.cxx   |  48 ++
 .../src/FaserTrackBarcodeInfo.cxx             |  34 +
 .../FaserMCTruth/src/FaserTrackHelper.cxx     |  48 ++
 .../src/FaserTrackInformation.cxx             |  43 ++
 .../FaserMCTruth/src/FaserTruthController.cxx |  30 +
 .../src/FaserVTrackInformation.cxx            |  54 ++
 .../G4Sim/FaserMCTruthBase/CMakeLists.txt     |  56 ++
 .../FaserMCTruthBase/FaserTrajectory.h        |  40 ++
 .../FaserTruthStrategyManager.h               |  41 ++
 .../FaserMCTruthBase/src/FaserTrajectory.cxx  | 160 +++++
 .../src/FaserTruthStrategyManager.cxx         |  60 ++
 .../G4Utilities/G4UserActions/CMakeLists.txt  |  46 ++
 .../python/G4UserActionsConfDb.py             |  32 +
 .../python/G4UserActionsConfigNew.py          |  53 ++
 .../src/AthenaDebugStackingAction.cxx         | 146 ++++
 .../src/AthenaDebugStackingAction.h           |  41 ++
 .../src/AthenaStackingAction.cxx              | 183 +++++
 .../G4UserActions/src/AthenaStackingAction.h  |  87 +++
 .../src/AthenaStackingActionTool.cxx          |  83 +++
 .../src/AthenaStackingActionTool.h            |  57 ++
 .../src/AthenaTrackingAction.cxx              |  92 +++
 .../G4UserActions/src/AthenaTrackingAction.h  |  54 ++
 .../src/AthenaTrackingActionTool.cxx          |  49 ++
 .../src/AthenaTrackingActionTool.h            |  52 ++
 .../G4UserActions/src/LooperKiller.cxx        | 101 +++
 .../G4UserActions/src/LooperKiller.h          |  69 ++
 .../G4UserActions/src/LooperKillerTool.cxx    |  65 ++
 .../G4UserActions/src/LooperKillerTool.h      |  54 ++
 .../src/components/G4UserActions_entries.cxx  |   7 +
 .../ISF_Core/FaserISF_Event/CMakeLists.txt    |  37 +
 .../FaserISF_Event/FaserISFParticle.h         | 215 ++++++
 .../FaserISF_Event/FaserISFParticle.icc       |  93 +++
 .../FaserISFParticleContainer.h               |  27 +
 .../FaserISF_Event/FaserISFParticleVector.h   |  27 +
 .../FaserISF_Event/FaserParticleHelper.h      |  51 ++
 .../FaserISF_Event/IFaserTruthIncident.h      | 206 ++++++
 .../FaserISF_Event/src/FaserISFParticle.cxx   | 273 ++++++++
 .../src/FaserParticleHelper.cxx               |  34 +
 .../FaserISF_Interfaces/CMakeLists.txt        |  34 +
 .../FaserISF_Interfaces/IFaserGeoIDSvc.h      | 122 ++++
 .../IFaserInputConverter.h                    |  73 ++
 .../FaserISF_Interfaces/IFaserTruthSvc.h      |  53 ++
 .../ISF_Core/FaserISF_Services/CMakeLists.txt | 102 +++
 .../python/FaserISF_ServicesConfigNew.py      | 142 ++++
 .../FaserISF_Services/src/FaserGeoIDSvc.cxx   | 147 ++++
 .../FaserISF_Services}/src/FaserGeoIDSvc.h    |  27 +-
 .../src/FaserInputConverter.cxx               | 618 +++++++++++++++++
 .../src/FaserInputConverter.h                 | 126 ++++
 .../FaserISF_Services/src/FaserTruthSvc.cxx   | 524 +++++++++++++++
 .../FaserISF_Services/src/FaserTruthSvc.h     | 133 ++++
 .../components/FaserISF_Services_entries.cxx  |   7 +
 .../test/FaserISF_ServicesConfigNew_test.py   |  48 ++
 .../test/FaserTruthSvc_test.cxx               | 631 ++++++++++++++++++
 .../FaserISF_Services/test/TruthSvc_test.txt  |   2 +
 .../FaserISF_Geant4Event/CMakeLists.txt       |  49 ++
 .../FaserGeant4TruthIncident.h                | 124 ++++
 .../FaserISFG4GeoHelper.h                     |  29 +
 .../FaserISF_Geant4Event/FaserISFG4Helper.h   |  64 ++
 .../src/FaserGeant4TruthIncident.cxx          | 374 +++++++++++
 .../src/FaserISFG4GeoHelper.cxx               | 153 +++++
 .../src/FaserISFG4Helper.cxx                  | 115 ++++
 .../FaserISF_HepMC_Interfaces/CMakeLists.txt  |  15 +
 .../IFaserTruthStrategy.h                     |  44 ++
 .../FaserISF_HepMC_Tools/CMakeLists.txt       |  56 ++
 .../python/FaserISF_HepMC_ToolsConfigDb.py    |   1 +
 .../python/FaserISF_HepMC_ToolsConfigNew.py   | 208 ++++++
 .../src/FaserGenParticleGenericFilter.cxx     | 134 ++++
 .../src/FaserGenParticleGenericFilter.h       |  78 +++
 .../src/FaserGenParticlePositionFilter.cxx    |  95 +++
 .../src/FaserGenParticlePositionFilter.h      |  58 ++
 .../src/FaserTruthStrategy.cxx                | 166 +++++
 .../src/FaserTruthStrategy.h                  |  84 +++
 .../FaserISF_HepMC_Tools_entries.cxx          |   7 +
 Simulation/README.md                          |   2 +-
 .../src/TrackerAlignDBTool.cxx                |  12 +-
 .../data/SCT_Conditions.py                    |  31 +-
 .../src/SCT_DetectorFactory.cxx               |   8 +-
 .../TrackerIdDictFiles/data/IdDictTracker.xml |  10 +-
 .../data/IdDictTracker_Interface.xml          |  53 ++
 .../TrackerReadoutGeometry/SiNumerology.h     |   4 +-
 .../TrackerG4/FaserSCT_G4_SD/CMakeLists.txt   |   4 +-
 .../python/FaserSCT_G4_SDToolConfig.py        |   1 -
 .../FaserSCT_G4_SD/src/FaserSctSensorSD.cxx   |  12 +-
 .../src/FaserSctSensorSDTool.cxx              |   2 +-
 .../src/FaserSiHitIdHelper.cxx                |   2 +-
 .../src/TrackCollHandle_TruthTracks.cxx       |  18 +-
 .../src/TrackSystemController.cxx             |  11 +-
 .../src/vp1trackcontrollerform.ui             |   9 +-
 version.txt                                   |   1 +
 146 files changed, 9484 insertions(+), 565 deletions(-)
 create mode 100644 Neutrino/NeutrinoDetDescr/NeutrinoIdDictFiles/CMakeLists.txt
 create mode 100644 Neutrino/NeutrinoDetDescr/NeutrinoIdDictFiles/data/IdDictNeutrino.xml
 create mode 100644 Simulation/G4Faser/G4FaserAlg/src/G4FaserAlg.cxx
 create mode 100644 Simulation/G4Faser/G4FaserAlg/src/G4FaserAlg.h
 create mode 100644 Simulation/G4Faser/G4FaserAlg/src/G4FaserFluxRecorder.cxx
 create mode 100644 Simulation/G4Faser/G4FaserAlg/src/G4FaserFluxRecorder.h
 create mode 100644 Simulation/G4Faser/G4FaserAlg/src/components/G4FaserAlg_entries.cxx
 rename Simulation/G4Faser/{G4FaserApp => G4FaserAlg}/test/runG4.py (85%)
 delete mode 100644 Simulation/G4Faser/G4FaserApp/CMakeLists.txt
 create mode 100644 Simulation/G4Faser/G4FaserServices/python/G4FaserUserActionConfigNew.py
 delete mode 100644 Simulation/G4Faser/G4FaserServices/src/FaserGeoIDSvc.cxx
 delete mode 100644 Simulation/G4Faser/G4FaserServices/src/components/G4FaserServices_entries.cxx
 create mode 100644 Simulation/G4Faser/G4FaserTools/python/G4FaserToolsConfigNew.py
 create mode 100644 Simulation/G4Sim/FaserMCTruth/CMakeLists.txt
 create mode 100644 Simulation/G4Sim/FaserMCTruth/FaserMCTruth/FaserEventInformation.h
 create mode 100644 Simulation/G4Sim/FaserMCTruth/FaserMCTruth/FaserPrimaryParticleInformation.h
 create mode 100644 Simulation/G4Sim/FaserMCTruth/FaserMCTruth/FaserTrackBarcodeInfo.h
 create mode 100644 Simulation/G4Sim/FaserMCTruth/FaserMCTruth/FaserTrackHelper.h
 create mode 100644 Simulation/G4Sim/FaserMCTruth/FaserMCTruth/FaserTrackInformation.h
 create mode 100644 Simulation/G4Sim/FaserMCTruth/FaserMCTruth/FaserTruthController.h
 create mode 100644 Simulation/G4Sim/FaserMCTruth/FaserMCTruth/FaserVTrackInformation.h
 create mode 100644 Simulation/G4Sim/FaserMCTruth/FaserMCTruth/TruthEvent.h
 create mode 100644 Simulation/G4Sim/FaserMCTruth/src/FaserEventInformation.cxx
 create mode 100644 Simulation/G4Sim/FaserMCTruth/src/FaserPrimaryParticleInformation.cxx
 create mode 100644 Simulation/G4Sim/FaserMCTruth/src/FaserTrackBarcodeInfo.cxx
 create mode 100644 Simulation/G4Sim/FaserMCTruth/src/FaserTrackHelper.cxx
 create mode 100644 Simulation/G4Sim/FaserMCTruth/src/FaserTrackInformation.cxx
 create mode 100644 Simulation/G4Sim/FaserMCTruth/src/FaserTruthController.cxx
 create mode 100644 Simulation/G4Sim/FaserMCTruth/src/FaserVTrackInformation.cxx
 create mode 100644 Simulation/G4Sim/FaserMCTruthBase/CMakeLists.txt
 create mode 100644 Simulation/G4Sim/FaserMCTruthBase/FaserMCTruthBase/FaserTrajectory.h
 create mode 100644 Simulation/G4Sim/FaserMCTruthBase/FaserMCTruthBase/FaserTruthStrategyManager.h
 create mode 100644 Simulation/G4Sim/FaserMCTruthBase/src/FaserTrajectory.cxx
 create mode 100644 Simulation/G4Sim/FaserMCTruthBase/src/FaserTruthStrategyManager.cxx
 create mode 100644 Simulation/G4Utilities/G4UserActions/CMakeLists.txt
 create mode 100644 Simulation/G4Utilities/G4UserActions/python/G4UserActionsConfDb.py
 create mode 100644 Simulation/G4Utilities/G4UserActions/python/G4UserActionsConfigNew.py
 create mode 100644 Simulation/G4Utilities/G4UserActions/src/AthenaDebugStackingAction.cxx
 create mode 100644 Simulation/G4Utilities/G4UserActions/src/AthenaDebugStackingAction.h
 create mode 100644 Simulation/G4Utilities/G4UserActions/src/AthenaStackingAction.cxx
 create mode 100644 Simulation/G4Utilities/G4UserActions/src/AthenaStackingAction.h
 create mode 100644 Simulation/G4Utilities/G4UserActions/src/AthenaStackingActionTool.cxx
 create mode 100644 Simulation/G4Utilities/G4UserActions/src/AthenaStackingActionTool.h
 create mode 100644 Simulation/G4Utilities/G4UserActions/src/AthenaTrackingAction.cxx
 create mode 100644 Simulation/G4Utilities/G4UserActions/src/AthenaTrackingAction.h
 create mode 100644 Simulation/G4Utilities/G4UserActions/src/AthenaTrackingActionTool.cxx
 create mode 100644 Simulation/G4Utilities/G4UserActions/src/AthenaTrackingActionTool.h
 create mode 100644 Simulation/G4Utilities/G4UserActions/src/LooperKiller.cxx
 create mode 100644 Simulation/G4Utilities/G4UserActions/src/LooperKiller.h
 create mode 100644 Simulation/G4Utilities/G4UserActions/src/LooperKillerTool.cxx
 create mode 100644 Simulation/G4Utilities/G4UserActions/src/LooperKillerTool.h
 create mode 100644 Simulation/G4Utilities/G4UserActions/src/components/G4UserActions_entries.cxx
 create mode 100644 Simulation/ISF/ISF_Core/FaserISF_Event/CMakeLists.txt
 create mode 100644 Simulation/ISF/ISF_Core/FaserISF_Event/FaserISF_Event/FaserISFParticle.h
 create mode 100644 Simulation/ISF/ISF_Core/FaserISF_Event/FaserISF_Event/FaserISFParticle.icc
 create mode 100644 Simulation/ISF/ISF_Core/FaserISF_Event/FaserISF_Event/FaserISFParticleContainer.h
 create mode 100644 Simulation/ISF/ISF_Core/FaserISF_Event/FaserISF_Event/FaserISFParticleVector.h
 create mode 100644 Simulation/ISF/ISF_Core/FaserISF_Event/FaserISF_Event/FaserParticleHelper.h
 create mode 100644 Simulation/ISF/ISF_Core/FaserISF_Event/FaserISF_Event/IFaserTruthIncident.h
 create mode 100644 Simulation/ISF/ISF_Core/FaserISF_Event/src/FaserISFParticle.cxx
 create mode 100644 Simulation/ISF/ISF_Core/FaserISF_Event/src/FaserParticleHelper.cxx
 create mode 100644 Simulation/ISF/ISF_Core/FaserISF_Interfaces/CMakeLists.txt
 create mode 100644 Simulation/ISF/ISF_Core/FaserISF_Interfaces/FaserISF_Interfaces/IFaserGeoIDSvc.h
 create mode 100644 Simulation/ISF/ISF_Core/FaserISF_Interfaces/FaserISF_Interfaces/IFaserInputConverter.h
 create mode 100644 Simulation/ISF/ISF_Core/FaserISF_Interfaces/FaserISF_Interfaces/IFaserTruthSvc.h
 create mode 100644 Simulation/ISF/ISF_Core/FaserISF_Services/CMakeLists.txt
 create mode 100644 Simulation/ISF/ISF_Core/FaserISF_Services/python/FaserISF_ServicesConfigNew.py
 create mode 100644 Simulation/ISF/ISF_Core/FaserISF_Services/src/FaserGeoIDSvc.cxx
 rename Simulation/{G4Faser/G4FaserServices => ISF/ISF_Core/FaserISF_Services}/src/FaserGeoIDSvc.h (61%)
 create mode 100644 Simulation/ISF/ISF_Core/FaserISF_Services/src/FaserInputConverter.cxx
 create mode 100644 Simulation/ISF/ISF_Core/FaserISF_Services/src/FaserInputConverter.h
 create mode 100644 Simulation/ISF/ISF_Core/FaserISF_Services/src/FaserTruthSvc.cxx
 create mode 100644 Simulation/ISF/ISF_Core/FaserISF_Services/src/FaserTruthSvc.h
 create mode 100644 Simulation/ISF/ISF_Core/FaserISF_Services/src/components/FaserISF_Services_entries.cxx
 create mode 100644 Simulation/ISF/ISF_Core/FaserISF_Services/test/FaserISF_ServicesConfigNew_test.py
 create mode 100644 Simulation/ISF/ISF_Core/FaserISF_Services/test/FaserTruthSvc_test.cxx
 create mode 100644 Simulation/ISF/ISF_Core/FaserISF_Services/test/TruthSvc_test.txt
 create mode 100644 Simulation/ISF/ISF_Geant4/FaserISF_Geant4Event/CMakeLists.txt
 create mode 100644 Simulation/ISF/ISF_Geant4/FaserISF_Geant4Event/FaserISF_Geant4Event/FaserGeant4TruthIncident.h
 create mode 100644 Simulation/ISF/ISF_Geant4/FaserISF_Geant4Event/FaserISF_Geant4Event/FaserISFG4GeoHelper.h
 create mode 100644 Simulation/ISF/ISF_Geant4/FaserISF_Geant4Event/FaserISF_Geant4Event/FaserISFG4Helper.h
 create mode 100644 Simulation/ISF/ISF_Geant4/FaserISF_Geant4Event/src/FaserGeant4TruthIncident.cxx
 create mode 100644 Simulation/ISF/ISF_Geant4/FaserISF_Geant4Event/src/FaserISFG4GeoHelper.cxx
 create mode 100644 Simulation/ISF/ISF_Geant4/FaserISF_Geant4Event/src/FaserISFG4Helper.cxx
 create mode 100644 Simulation/ISF/ISF_HepMC/FaserISF_HepMC_Interfaces/CMakeLists.txt
 create mode 100644 Simulation/ISF/ISF_HepMC/FaserISF_HepMC_Interfaces/FaserISF_HepMC_Interfaces/IFaserTruthStrategy.h
 create mode 100644 Simulation/ISF/ISF_HepMC/FaserISF_HepMC_Tools/CMakeLists.txt
 create mode 100644 Simulation/ISF/ISF_HepMC/FaserISF_HepMC_Tools/python/FaserISF_HepMC_ToolsConfigDb.py
 create mode 100644 Simulation/ISF/ISF_HepMC/FaserISF_HepMC_Tools/python/FaserISF_HepMC_ToolsConfigNew.py
 create mode 100644 Simulation/ISF/ISF_HepMC/FaserISF_HepMC_Tools/src/FaserGenParticleGenericFilter.cxx
 create mode 100644 Simulation/ISF/ISF_HepMC/FaserISF_HepMC_Tools/src/FaserGenParticleGenericFilter.h
 create mode 100644 Simulation/ISF/ISF_HepMC/FaserISF_HepMC_Tools/src/FaserGenParticlePositionFilter.cxx
 create mode 100644 Simulation/ISF/ISF_HepMC/FaserISF_HepMC_Tools/src/FaserGenParticlePositionFilter.h
 create mode 100644 Simulation/ISF/ISF_HepMC/FaserISF_HepMC_Tools/src/FaserTruthStrategy.cxx
 create mode 100644 Simulation/ISF/ISF_HepMC/FaserISF_HepMC_Tools/src/FaserTruthStrategy.h
 create mode 100644 Simulation/ISF/ISF_HepMC/FaserISF_HepMC_Tools/src/components/FaserISF_HepMC_Tools_entries.cxx
 create mode 100644 Tracker/TrackerDetDescr/TrackerIdDictFiles/data/IdDictTracker_Interface.xml
 create mode 100644 version.txt

diff --git a/CMakeLists.txt b/CMakeLists.txt
index a30d84f4..897dc341 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,16 +1,19 @@
 cmake_minimum_required(VERSION 3.6)
+file( READ ${CMAKE_SOURCE_DIR}/version.txt _version )
+string( STRIP ${_version} _version )
+project( Calypso VERSION ${_version} LANGUAGES C CXX Fortran )
+unset( _version )
 
 set( ATLAS_PROJECT Athena
    CACHE STRING	   "The name of the project to build against" )
 
-set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
-
 find_package( Athena )
 
+set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
+
 atlas_ctest_setup()
 
-atlas_project( Calypso 1.0.0
-  USE ${ATLAS_PROJECT} ${${ATLAS_PROJECT}_VERSION} )
+atlas_project( USE ${ATLAS_PROJECT} ${${ATLAS_PROJECT}_VERSION} )
 
 lcg_generate_env( SH_FILE ${CMAKE_BINARY_DIR}/${ATLAS_PLATFORM}/env_setup.sh )
 install( FILES ${CMAKE_BINARY_DIR}/${ATLAS_PLATFORM}/env_setup.sh
diff --git a/Control/CalypsoExample/GeoModelTest/src/GeoModelTestAlg.cxx b/Control/CalypsoExample/GeoModelTest/src/GeoModelTestAlg.cxx
index 548d67c1..244a631c 100644
--- a/Control/CalypsoExample/GeoModelTest/src/GeoModelTestAlg.cxx
+++ b/Control/CalypsoExample/GeoModelTest/src/GeoModelTestAlg.cxx
@@ -19,12 +19,14 @@
 #include "GaudiKernel/PhysicalConstants.h"
 
 GeoModelTestAlg::GeoModelTestAlg(const std::string& name, ISvcLocator* pSvcLocator)
-: AthAlgorithm(name, pSvcLocator) { }
+: AthAlgorithm(name, pSvcLocator), m_numSctStations {0}
+{ }
 
 GeoModelTestAlg::~GeoModelTestAlg() { }
 
 StatusCode GeoModelTestAlg::initialize()
 {
+    m_numSctStations = std::max(0, m_lastSctStation - m_firstSctStation + 1);
     ATH_CHECK(m_field.retrieve());
     ATH_CHECK(m_alignTool.retrieve());
     return StatusCode::SUCCESS;
@@ -106,9 +108,16 @@ StatusCode GeoModelTestAlg::testSCT()
         // Test neighbors with helper function
         const IdContext& context = helper->wafer_context();
         ATH_MSG_ALWAYS("Retrieved FaserSCT_ID helper from DetStore.");
-        for (int iStation = -m_numSctStations/2; iStation <= m_numSctStations/2; iStation++)
+
+        // Print list of identifiers
+        // for (FaserSCT_ID::const_id_iterator it = helper->wafer_begin(); it != helper->wafer_end(); ++it)
+        // {
+        //     ATH_MSG_ALWAYS("Wafer ID: " << (it->get_compact() >>32));
+        // }
+
+        for (int iStation = m_firstSctStation; iStation <= m_lastSctStation; iStation++)
         {
-            if (m_numSctStations%2 == 0 && iStation == 0) continue;
+            // if (m_numSctStations%2 == 0 && iStation == 0) continue;
             for (int iPlane = 0; iPlane < m_numSctPlanesPerStation; iPlane++)
             {
                 for (int iRow = 0; iRow < m_numSctRowsPerPlane; iRow++)
@@ -305,7 +314,7 @@ StatusCode GeoModelTestAlg::testSCT()
     {
         ATH_MSG_ALWAYS("Retrieved (typed) SCT detector manager with " << sctMgr->getNumTreeTops() << " treetops directly from DetStore.");
         // Compare numerology with the "right" answers from our properties
-        if (sctMgr->numerology().numStations() != m_numSctStations || sctMgr->getNumTreeTops() != m_numSctStations)
+        if (sctMgr->numerology().numStations() != m_numSctStations || sctMgr->getNumTreeTops() != (size_t) m_numSctStations)
         {
             ATH_MSG_FATAL("Disagreement in number of SCT stations.");
             return StatusCode::FAILURE;
@@ -333,9 +342,9 @@ StatusCode GeoModelTestAlg::testSCT()
 
         // Test detector elements
         const TrackerDD::SiDetectorElementCollection* elements = sctMgr->getDetectorElementCollection();
-        for (int station = -m_numSctStations/2; station <= m_numSctStations/2; station++)
+        for (int station = m_firstSctStation; station <= m_lastSctStation; station++)
         {
-            if (m_numSctStations%2 == 0 && station == 0) continue;
+            // if (m_numSctStations%2 == 0 && station == 0) continue;
             for (int plane = 0; plane < m_numSctPlanesPerStation; plane++)
             {
                 for (int row = 0; row < m_numSctRowsPerPlane; row++)
diff --git a/Control/CalypsoExample/GeoModelTest/src/GeoModelTestAlg.h b/Control/CalypsoExample/GeoModelTest/src/GeoModelTestAlg.h
index 47aba8df..b15b41f0 100644
--- a/Control/CalypsoExample/GeoModelTest/src/GeoModelTestAlg.h
+++ b/Control/CalypsoExample/GeoModelTest/src/GeoModelTestAlg.h
@@ -36,12 +36,14 @@ class GeoModelTestAlg : public AthAlgorithm
     Gaudi::Property<int>            m_numPreshowerPlatesPerStation   {this, "NumPreshowerPlatesPerStation", 2, "Number of plates per station in the Preshower detector"};
     Gaudi::Property<int>            m_numPreshowerPmtsPerPlate       {this, "NumPreshowerPmtsPerPlate", 1, "Number of pmts per plate in the Preshower detector"};
 
-    Gaudi::Property<int>            m_numSctStations            {this, "NumSCTStations", 3, "Number of stations in the SCT detector"};
+    Gaudi::Property<int>            m_firstSctStation           {this, "FirstSCTStation", 1, "Identifier of the first SCT station (0 w/FaserNu, 1 otherwise)"};
+    Gaudi::Property<int>            m_lastSctStation            {this, "LastSCTStation", 3, "Identifier of the last SCT station (normally 3)"};
     Gaudi::Property<int>            m_numSctPlanesPerStation    {this, "NumSCTPlanesPerStation", 3, "Number of planes per station in the SCT detector"};
     Gaudi::Property<int>            m_numSctRowsPerPlane        {this, "NumSCTRowsPerPlane", 4, "Number of rows of modules per plane in the SCT detector"};
     Gaudi::Property<int>            m_numSctModulesPerRow       {this, "NumSCTModulesPerRow", 2, "Number of modules per row in the SCT detector"};
     Gaudi::Property<int>            m_numSctStripsPerSensor     {this, "NumSCTStripsPerSensor", 768,"Number of readout strips per sensor in the SCT detector"};
 
+    int m_numSctStations;
     ServiceHandle<MagField::IMagFieldSvc> m_field { this, "FieldService", "FaserFieldSvc" };
 
     ToolHandle<ITrackerAlignDBTool> m_alignTool { this, "AlignDbTool", "TrackerAlignDBTool" };
diff --git a/DetectorDescription/DetDescrCnvSvc/DetDescrCnvSvc/DetDescrCnvSvc.h b/DetectorDescription/DetDescrCnvSvc/DetDescrCnvSvc/DetDescrCnvSvc.h
index 892a9773..f0da393a 100644
--- a/DetectorDescription/DetDescrCnvSvc/DetDescrCnvSvc/DetDescrCnvSvc.h
+++ b/DetectorDescription/DetDescrCnvSvc/DetDescrCnvSvc/DetDescrCnvSvc.h
@@ -97,6 +97,7 @@ private:
     StringProperty			m_idDictName;
     StringProperty			m_idDictGlobalTag;
     StringProperty			m_idDictFASERName;
+    StringProperty			m_idDictNeutrinoName;
     StringProperty			m_idDictScintName;
     StringProperty			m_idDictTrackerName;
     StringProperty			m_idDictCaloName;
diff --git a/DetectorDescription/DetDescrCnvSvc/src/DetDescrCnvSvc.cxx b/DetectorDescription/DetDescrCnvSvc/src/DetDescrCnvSvc.cxx
index 8c71b542..22e7ed16 100644
--- a/DetectorDescription/DetDescrCnvSvc/src/DetDescrCnvSvc.cxx
+++ b/DetectorDescription/DetDescrCnvSvc/src/DetDescrCnvSvc.cxx
@@ -52,6 +52,7 @@ DetDescrCnvSvc::DetDescrCnvSvc(const std::string& name, ISvcLocator* svc)
     declareProperty("DoInitNeighbours",            m_do_neighbours);
 
     declareProperty("FaserIDFileName",             m_idDictFASERName);
+    declareProperty("NeutrinoIDFileName",          m_idDictNeutrinoName);
     declareProperty("ScintIDFileName",             m_idDictScintName);
     declareProperty("TrackerIDFileName",           m_idDictTrackerName);
     declareProperty("CaloIDFileName",              m_idDictCaloName);
diff --git a/DetectorDescription/FaserDetDescr/FaserDetDescr/FaserDetTechnology.h b/DetectorDescription/FaserDetDescr/FaserDetDescr/FaserDetTechnology.h
index 2a18fa9e..6c0a2b29 100644
--- a/DetectorDescription/FaserDetDescr/FaserDetDescr/FaserDetTechnology.h
+++ b/DetectorDescription/FaserDetDescr/FaserDetDescr/FaserDetTechnology.h
@@ -29,22 +29,26 @@ namespace FaserDetDescr {
             fUndefined                  = 0,
         // first Geometry element in enum, used in e.g. loops
             fFirstFaserDetTechnology    = 1,
+        // Neutrino
+            fFirstFaserNeutrinoTechnology = 1,
+            fFaserEmulsion                = 1,
+            fLastFaserNeutrinoTechnology  = 1,
         // Scintillator
-            fFirstFaserScintTechnology  = 1,
-            fFaserVeto                  = 1,
-            fFaserTrigger               = 2,
-            fFaserPreshower             = 3,
-            fLastFaserScintTechnology   = 3,
+            fFirstFaserScintillatorTechnology  = 2,
+            fFaserVeto                         = 2,
+            fFaserTrigger                      = 3,
+            fFaserPreshower                    = 4,
+            fLastFaserScintillatorTechnology   = 4,
         // Tracker
-            fFirstFaserTrackerTechnology = 4,
-            fFaserSCT                    = 4,
-            fLastFaserTrackerTechnology  = 4,
+            fFirstFaserTrackerTechnology = 5,
+            fFaserSCT                    = 5,
+            fLastFaserTrackerTechnology  = 5,
         // Calorimeter
-            fFirstFaserCaloTechnology    = 5,
-            fFaserECAL                   = 5,
-            fLastFaserCaloTechnology     = 5,
+            fFirstFaserCalorimeterTechnology    = 6,
+            fFaserECAL                          = 6,
+            fLastFaserCalorimeterTechnology     = 6,
         // number of defined detector technologies
-            fNumFaserDetTechnologies    = 6
+            fNumFaserDetTechnologies    = 7
    };
 
 } // end of namespace
diff --git a/DetectorDescription/FaserDetDescr/FaserDetDescr/FaserRegion.h b/DetectorDescription/FaserDetDescr/FaserDetDescr/FaserRegion.h
index 66347392..fdefad24 100644
--- a/DetectorDescription/FaserDetDescr/FaserDetDescr/FaserRegion.h
+++ b/DetectorDescription/FaserDetDescr/FaserDetDescr/FaserRegion.h
@@ -29,12 +29,14 @@ namespace FaserDetDescr {
         // first Geometry element in enum, used in e.g. loops
             fFirstFaserRegion     = 1,
         // FASER Detector setup: geometrical ones
-            fFaserScint           = 1,
-            fFaserTracker         = 2,
-            fFaserCalo            = 3,
-            fFaserCavern          = 4,
+            fFaserNeutrino        = 1,
+            fFaserScintillator    = 2,
+            fFaserTracker         = 3,
+            fFaserDipole          = 4,  // this means in the metal of the magnet, not the bore
+            fFaserCalorimeter     = 5,
+            fFaserCavern          = 6,
         // number of defined GeoIDs
-            fNumFaserRegions      = 5
+            fNumFaserRegions      = 7
    };
 
 } // end of namespace
diff --git a/DetectorDescription/FaserDetDescr/src/FaserRegionHelper.cxx b/DetectorDescription/FaserDetDescr/src/FaserRegionHelper.cxx
index 5d9193d8..35362e28 100644
--- a/DetectorDescription/FaserDetDescr/src/FaserRegionHelper.cxx
+++ b/DetectorDescription/FaserDetDescr/src/FaserRegionHelper.cxx
@@ -16,11 +16,13 @@ namespace FaserDetDescr {
 
   const char * FaserRegionHelper::getName( const FaserDetDescr::FaserRegion region ) {
 
-    if      ( region == FaserDetDescr::fFaserScint   ) return "FaserScint";
-    else if ( region == FaserDetDescr::fFaserTracker ) return "FaserTracker";
-    else if ( region == FaserDetDescr::fFaserCalo    ) return "FaserCalo";
-    else if ( region == FaserDetDescr::fFaserCavern  ) return "FaserCavern";
-    else                                               return "UndefinedFaserRegion";
+    if      ( region == FaserDetDescr::fFaserScintillator   ) return "FaserScint";
+    else if ( region == FaserDetDescr::fFaserTracker        ) return "FaserTracker";
+    else if ( region == FaserDetDescr::fFaserDipole         ) return "FaserDipole";
+    else if ( region == FaserDetDescr::fFaserCalorimeter    ) return "FaserCalo";
+    else if ( region == FaserDetDescr::fFaserNeutrino       ) return "FaserNeutrino";
+    else if ( region == FaserDetDescr::fFaserCavern         ) return "FaserCavern";
+    else                                                      return "UndefinedFaserRegion";
 
   }
 
diff --git a/DetectorDescription/GeoModel/FaserGeoModel/data/FASER_IDS.xml b/DetectorDescription/GeoModel/FaserGeoModel/data/FASER_IDS.xml
index 4b56e287..5a064dc2 100644
--- a/DetectorDescription/GeoModel/FaserGeoModel/data/FASER_IDS.xml
+++ b/DetectorDescription/GeoModel/FaserGeoModel/data/FASER_IDS.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0"?>
 <!DOCTYPE IdDict SYSTEM "IdDict.dtd" [
+  <!ENTITY Neutrino                SYSTEM "IdDictNeutrino.xml">
   <!ENTITY Scintillator            SYSTEM "IdDictScintillator.xml">
   <!ENTITY Tracker                 SYSTEM "IdDictTracker.xml">
   <!ENTITY Calorimeter             SYSTEM "IdDictCalorimeter.xml">
@@ -8,6 +9,7 @@
 
 <IdDict IdDictVersion="v1">
 
+&Neutrino;
 &Scintillator;
 &Tracker;
 &Calorimeter;
diff --git a/DetectorDescription/GeoModel/FaserGeoModel/data/IdDictFASER.xml b/DetectorDescription/GeoModel/FaserGeoModel/data/IdDictFASER.xml
index f5d2abd6..fcedadc9 100644
--- a/DetectorDescription/GeoModel/FaserGeoModel/data/IdDictFASER.xml
+++ b/DetectorDescription/GeoModel/FaserGeoModel/data/IdDictFASER.xml
@@ -1,11 +1,17 @@
 <IdDictionary name="FASER">
 
   <field name="subdet">
+    <label name="Neutrino"        value="1"  />
     <label name="Scintillator"    value="2"  />
     <label name="Tracker"         value="3"  />
     <label name="Calorimeter"     value="4"  />
  </field>
 
+  <region>
+    <range field="subdet" value="Neutrino" />
+    <dictionary name="Neutrino" />
+  </region>
+
   <region>
     <range field="subdet" value="Scintillator" />
     <dictionary name="Scintillator" />
diff --git a/DetectorDescription/GeoModel/FaserGeoModel/data/geomDB.sql b/DetectorDescription/GeoModel/FaserGeoModel/data/geomDB.sql
index 148a323a..71879199 100644
--- a/DetectorDescription/GeoModel/FaserGeoModel/data/geomDB.sql
+++ b/DetectorDescription/GeoModel/FaserGeoModel/data/geomDB.sql
@@ -104,6 +104,31 @@ CREATE TABLE IF NOT EXISTS "ELEMENTS_DATA2TAG" (
 	"ELEMENTS_DATA_ID"	SLONGLONG
 );
 --
+-- Tables for describing the emulsion detector
+--
+DROP TABLE IF EXISTS "EMULSIONTOPLEVEL_DATA";
+CREATE TABLE IF NOT EXISTS "EMULSIONTOPLEVEL_DATA" (
+	"EMULSIONTOPLEVEL_DATA_ID"	SLONGLONG UNIQUE,
+	"POSX" DOUBLE,
+	"POSY" DOUBLE,
+	"POSZ" DOUBLE,
+	"ROTX" DOUBLE,
+	"ROTY" DOUBLE,
+	"ROTZ" DOUBLE,
+	"ROTORDER" INT,
+	"LABEL" TEXT
+);
+--
+-- The DATA2TAG tables associate specific rows of the corresponding
+-- _DATA table with the referenced tag (from the HVS_TAG2NODE table).
+-- This is a many-to-many relationship: each row may belong to
+-- several tags, and each tag may apply to several rows.
+DROP TABLE IF EXISTS "EMULSIONTOPLEVEL_DATA2TAG";
+CREATE TABLE IF NOT EXISTS "EMULSIONTOPLEVEL_DATA2TAG" (
+	"EMULSIONTOPLEVEL_TAG_ID" SLONGLONG,
+	"EMULSIONTOPLEVEL_DATA_ID" SLONGLONG
+);
+--
 -- Tables for describing Veto scintillator plates (and passive radiators)
 --
 DROP TABLE IF EXISTS "VETOTOPLEVEL_DATA";
@@ -267,6 +292,33 @@ CREATE TABLE IF NOT EXISTS "PRESHOWERPLATEGENERAL_DATA2TAG" (
 -- Materials are recorded in two related nodes.
 -- One stores the name and density of the material.
 -- The second stores the composition in terms of other materials.
+--
+-- Neutrino detector materials
+DROP TABLE IF EXISTS "NEUTRINOMATERIALS_DATA";
+CREATE TABLE IF NOT EXISTS "NEUTRINOMATERIALS_DATA" (
+	"NEUTRINOMATERIALS_DATA_ID" SLONGLONG UNIQUE,
+	"NAME" TEXT,
+	"DENSITY" DOUBLE
+);
+DROP TABLE IF EXISTS "NEUTRINOMATERIALS_DATA2TAG";
+CREATE TABLE IF NOT EXISTS "NEUTRINOMATERIALS_DATA2TAG" (
+	"NEUTRINOMATERIALS_TAG_ID" SLONGLONG,
+	"NEUTRINOMATERIALS_DATA_ID" SLONGLONG
+);
+--
+DROP TABLE IF EXISTS "NEUTRINOMATCOMPONENTS_DATA";
+CREATE TABLE IF NOT EXISTS "NEUTRINOMATCOMPONENTS_DATA" (
+	"NEUTRINOMATCOMPONENTS_DATA_ID" SLONGLONG UNIQUE,
+	"MATERIAL_ID" SLONGLONG,
+	"COMPNAME" TEXT,
+	"FRACTION" DOUBLE
+);
+DROP TABLE IF EXISTS "NEUTRINOMATCOMPONENTS_DATA2TAG";
+CREATE TABLE IF NOT EXISTS "NEUTRINOMATCOMPONENTS_DATA2TAG" (
+	"NEUTRINOMATCOMPONENTS_TAG_ID" SLONGLONG,
+	"NEUTRINOMATCOMPONENTS_DATA_ID" SLONGLONG
+);
+-- Scintillator materials
 DROP TABLE IF EXISTS "SCINTMATERIALS_DATA";
 CREATE TABLE IF NOT EXISTS "SCINTMATERIALS_DATA" (
 	"SCINTMATERIALS_DATA_ID" SLONGLONG UNIQUE,
@@ -352,7 +404,23 @@ CREATE TABLE IF NOT EXISTS "FASERCOMMON_DATA2TAG" (
 	"FASERCOMMON_TAG_ID" SLONGLONG,
 	"FASERCOMMON_DATA_ID" SLONGLONG
 );
--- 
+--
+DROP TABLE IF EXISTS "EMULSIONSWITCHES_DATA";
+CREATE TABLE IF NOT EXISTS "EMULSIONSWITCHES_DATA" ( 
+	"EMULSIONSWITCHES_DATA_ID" SLONGLONG UNIQUE,
+	"DETECTORNAME" TEXT ,
+	"USEMAGFIELDSVC" INT ,
+	"COSMICLAYOUT" INT ,
+	"VERSIONNAME" TEXT ,
+	"LAYOUT" TEXT ,
+	"DESCRIPTION" TEXT
+);
+DROP TABLE IF EXISTS "EMULSIONSWITCHES_DATA2TAG";
+CREATE TABLE IF NOT EXISTS "EMULSIONSWITCHES_DATA2TAG" (
+	"EMULSIONSWITCHES_TAG_ID" SLONGLONG,
+	"EMULSIONSWITCHES_DATA_ID" SLONGLONG
+);
+--
 DROP TABLE IF EXISTS "VETOSWITCHES_DATA";
 CREATE TABLE IF NOT EXISTS "VETOSWITCHES_DATA" ( 
 	"VETOSWITCHES_DATA_ID" SLONGLONG UNIQUE,
@@ -401,6 +469,19 @@ CREATE TABLE IF NOT EXISTS "PRESHOWERSWITCHES_DATA2TAG" (
 	"PRESHOWERSWITCHES_DATA_ID" SLONGLONG
 );
 --
+DROP TABLE IF EXISTS "NEUTRINOIDENTIFIER_DATA";
+CREATE TABLE IF NOT EXISTS "NEUTRINOIDENTIFIER_DATA" ( 
+	"NEUTRINOIDENTIFIER_DATA_ID" SLONGLONG UNIQUE,
+	"DICT_NAME" TEXT ,
+	"DICT_FILENAME" TEXT ,
+	"DICT_TAG" TEXT 
+);
+DROP TABLE IF EXISTS "NEUTRINOIDENTIFIER_DATA2TAG";
+CREATE TABLE IF NOT EXISTS "NEUTRINOIDENTIFIER_DATA2TAG" (
+	"NEUTRINOIDENTIFIER_TAG_ID" SLONGLONG,
+	"NEUTRINOIDENTIFIER_DATA_ID" SLONGLONG
+);
+--
 DROP TABLE IF EXISTS "SCINTIDENTIFIER_DATA";
 CREATE TABLE IF NOT EXISTS "SCINTIDENTIFIER_DATA" ( 
 	"SCINTIDENTIFIER_DATA_ID" SLONGLONG UNIQUE,
@@ -443,149 +524,178 @@ CREATE TABLE IF NOT EXISTS "CALOIDENTIFIER_DATA2TAG" (
 -- Part 2a: HVS data
 --
 -- Data for the HVS_NODE table
-INSERT INTO "HVS_NODE" VALUES (0,   "FASER", 0, 1, NULL);
-INSERT INTO "HVS_NODE" VALUES (1,   "Scintillator", 0, 1, NULL);
-INSERT INTO "HVS_NODE" VALUES (11,  "Veto", 1, 1, NULL);
-INSERT INTO "HVS_NODE" VALUES (12,  "Trigger", 1, 1, NULL);
-INSERT INTO "HVS_NODE" VALUES (13,  "Preshower", 1, 1, NULL);
-INSERT INTO "HVS_NODE" VALUES (2,   "Tracker", 0, 1, NULL);
-INSERT INTO "HVS_NODE" VALUES (21,  "SCT", 2, 1, NULL);
-INSERT INTO "HVS_NODE" VALUES (22,  "Dipole", 2, 1, NULL);
-INSERT INTO "HVS_NODE" VALUES (210, "SctTopLevel", 21, 0, NULL);
-INSERT INTO "HVS_NODE" VALUES (211, "SctBrlModule", 21, 0, NULL);
-INSERT INTO "HVS_NODE" VALUES (212, "SctBrlSensor", 21, 0, NULL);
-INSERT INTO "HVS_NODE" VALUES (213, "SctFaserGeneral", 21, 0, NULL);
-INSERT INTO "HVS_NODE" VALUES (214, "SctSwitches", 21, 0, NULL);
-INSERT INTO "HVS_NODE" VALUES (215, "SCTMaterials", 21, 0, NULL);
-INSERT INTO "HVS_NODE" VALUES (216, "SCTMatComponents", 21, 0, NULL);
-INSERT INTO "HVS_NODE" VALUES (217, "SctConditions", 21, 0, NULL);
-INSERT INTO "HVS_NODE" VALUES (220, "DipoleTopLevel", 22, 0, NULL);
-INSERT INTO "HVS_NODE" VALUES (221, "DipoleGeneral", 22, 0, NULL);
-INSERT INTO "HVS_NODE" VALUES (224, "DipoleSwitches", 22, 0, NULL);
-INSERT INTO "HVS_NODE" VALUES (3,    "Calorimeter", 0, 1, NULL);
-INSERT INTO "HVS_NODE" VALUES (100,  "Materials", 0, 1, NULL);
-INSERT INTO "HVS_NODE" VALUES (101,  "StdMaterials", 100, 0, NULL);
-INSERT INTO "HVS_NODE" VALUES (102,  "StdMatComponents", 100, 0, NULL);
-INSERT INTO "HVS_NODE" VALUES (103,  "Elements", 100, 0, NULL);
-INSERT INTO "HVS_NODE" VALUES (1001, "VetoTopLevel", 11, 0, NULL);
-INSERT INTO "HVS_NODE" VALUES (1002, "VetoStationGeneral", 11, 0, NULL);
-INSERT INTO "HVS_NODE" VALUES (1006, "VetoPlateGeneral", 11, 0, NULL);
-INSERT INTO "HVS_NODE" VALUES (1101, "TriggerTopLevel", 12, 0, NULL);
-INSERT INTO "HVS_NODE" VALUES (1102, "TriggerStationGeneral", 12, 0, NULL);
-INSERT INTO "HVS_NODE" VALUES (1106, "TriggerPlateGeneral", 12, 0, NULL);
-INSERT INTO "HVS_NODE" VALUES (1201, "PreshowerTopLevel", 13, 0, NULL);
-INSERT INTO "HVS_NODE" VALUES (1202, "PreshowerStationGeneral", 13, 0, NULL);
-INSERT INTO "HVS_NODE" VALUES (1206, "PreshowerPlateGeneral", 13, 0, NULL);
-INSERT INTO "HVS_NODE" VALUES (1003, "ScintMaterials", 1, 0, NULL);
-INSERT INTO "HVS_NODE" VALUES (1004, "ScintMatComponents", 1, 0, NULL);
-INSERT INTO "HVS_NODE" VALUES (2003, "TrackerMaterials", 2, 0, NULL);
-INSERT INTO "HVS_NODE" VALUES (2004, "TrackerMatComponents", 2, 0, NULL);
-INSERT INTO "HVS_NODE" VALUES (3003, "CaloMaterials", 3, 0, NULL);
-INSERT INTO "HVS_NODE" VALUES (3004, "CaloMatComponents", 3, 0, NULL);
-INSERT INTO "HVS_NODE" VALUES (110,  "FaserCommon", 0, 0, NULL);
-INSERT INTO "HVS_NODE" VALUES (1100, "VetoSwitches", 11, 0, NULL );
-INSERT INTO "HVS_NODE" VALUES (1200, "TriggerSwitches", 12, 0, NULL );
-INSERT INTO "HVS_NODE" VALUES (1300, "PreshowerSwitches", 13, 0, NULL );
-INSERT INTO "HVS_NODE" VALUES (1005, "ScintIdentifier", 1, 0, NULL);
-INSERT INTO "HVS_NODE" VALUES (2005, "TrackerIdentifier", 2, 0, NULL);
-INSERT INTO "HVS_NODE" VALUES (3005, "CaloIdentifier", 3, 0, NULL);
+INSERT INTO "HVS_NODE" VALUES (0,    "FASER", 0, 1, NULL);
+INSERT INTO "HVS_NODE" VALUES (90,   "FaserCommon", 0, 0, NULL);
+INSERT INTO "HVS_NODE" VALUES (9000, "Materials", 0, 1, NULL);
+INSERT INTO "HVS_NODE" VALUES (9001, "StdMaterials", 9000, 0, NULL);
+INSERT INTO "HVS_NODE" VALUES (9002, "StdMatComponents", 9000, 0, NULL);
+INSERT INTO "HVS_NODE" VALUES (9003, "Elements", 9000, 0, NULL);
+INSERT INTO "HVS_NODE" VALUES (1,    "Neutrino", 0, 1, NULL);
+INSERT INTO "HVS_NODE" VALUES (1003, "NeutrinoMaterials", 1, 0, NULL);
+INSERT INTO "HVS_NODE" VALUES (1004, "NeutrinoMatComponents", 1, 0, NULL);
+INSERT INTO "HVS_NODE" VALUES (1005, "NeutrinoIdentifier", 1, 0, NULL);
+INSERT INTO "HVS_NODE" VALUES (11,   "Emulsion", 1, 1, NULL);
+INSERT INTO "HVS_NODE" VALUES (110,  "EmulsionTopLevel", 11, 0, NULL);
+INSERT INTO "HVS_NODE" VALUES (114,  "EmulsionSwitches", 11, 0, NULL);
+INSERT INTO "HVS_NODE" VALUES (2,    "Scintillator", 0, 1, NULL);
+INSERT INTO "HVS_NODE" VALUES (2003, "ScintMaterials", 2, 0, NULL);
+INSERT INTO "HVS_NODE" VALUES (2004, "ScintMatComponents", 2, 0, NULL);
+INSERT INTO "HVS_NODE" VALUES (2005, "ScintIdentifier", 2, 0, NULL);
+INSERT INTO "HVS_NODE" VALUES (21,   "Veto", 2, 1, NULL);
+INSERT INTO "HVS_NODE" VALUES (210,  "VetoTopLevel", 21, 0, NULL);
+INSERT INTO "HVS_NODE" VALUES (211,  "VetoStationGeneral", 21, 0, NULL);
+INSERT INTO "HVS_NODE" VALUES (212,  "VetoPlateGeneral", 21, 0, NULL);
+INSERT INTO "HVS_NODE" VALUES (214,  "VetoSwitches", 21, 0, NULL );
+INSERT INTO "HVS_NODE" VALUES (22,   "Trigger", 2, 1, NULL);
+INSERT INTO "HVS_NODE" VALUES (220,  "TriggerTopLevel", 22, 0, NULL);
+INSERT INTO "HVS_NODE" VALUES (221,  "TriggerStationGeneral", 22, 0, NULL);
+INSERT INTO "HVS_NODE" VALUES (222,  "TriggerPlateGeneral", 22, 0, NULL);
+INSERT INTO "HVS_NODE" VALUES (224,  "TriggerSwitches", 22, 0, NULL );
+INSERT INTO "HVS_NODE" VALUES (23,   "Preshower", 2, 1, NULL);
+INSERT INTO "HVS_NODE" VALUES (230,  "PreshowerTopLevel", 23, 0, NULL);
+INSERT INTO "HVS_NODE" VALUES (231,  "PreshowerStationGeneral", 23, 0, NULL);
+INSERT INTO "HVS_NODE" VALUES (232,  "PreshowerPlateGeneral", 23, 0, NULL);
+INSERT INTO "HVS_NODE" VALUES (234,  "PreshowerSwitches", 23, 0, NULL );
+INSERT INTO "HVS_NODE" VALUES (3,    "Tracker", 0, 1, NULL);
+INSERT INTO "HVS_NODE" VALUES (3003, "TrackerMaterials", 3, 0, NULL);
+INSERT INTO "HVS_NODE" VALUES (3004, "TrackerMatComponents", 3, 0, NULL);
+INSERT INTO "HVS_NODE" VALUES (3005, "TrackerIdentifier", 3, 0, NULL);
+INSERT INTO "HVS_NODE" VALUES (31,   "SCT", 3, 1, NULL);
+INSERT INTO "HVS_NODE" VALUES (310,  "SctTopLevel", 31, 0, NULL);
+INSERT INTO "HVS_NODE" VALUES (311,  "SctBrlModule", 31, 0, NULL);
+INSERT INTO "HVS_NODE" VALUES (312,  "SctBrlSensor", 31, 0, NULL);
+INSERT INTO "HVS_NODE" VALUES (313,  "SctFaserGeneral", 31, 0, NULL);
+INSERT INTO "HVS_NODE" VALUES (314,  "SctSwitches", 31, 0, NULL);
+INSERT INTO "HVS_NODE" VALUES (315,  "SCTMaterials", 31, 0, NULL);
+INSERT INTO "HVS_NODE" VALUES (316,  "SCTMatComponents", 31, 0, NULL);
+INSERT INTO "HVS_NODE" VALUES (317,  "SctConditions", 31, 0, NULL);
+INSERT INTO "HVS_NODE" VALUES (32,   "Dipole", 3, 1, NULL);
+INSERT INTO "HVS_NODE" VALUES (320,  "DipoleTopLevel", 32, 0, NULL);
+INSERT INTO "HVS_NODE" VALUES (321,  "DipoleGeneral", 32, 0, NULL);
+INSERT INTO "HVS_NODE" VALUES (324,  "DipoleSwitches", 32, 0, NULL);
+INSERT INTO "HVS_NODE" VALUES (4,    "Calorimeter", 0, 1, NULL);
+INSERT INTO "HVS_NODE" VALUES (4003, "CaloMaterials", 4, 0, NULL);
+INSERT INTO "HVS_NODE" VALUES (4004, "CaloMatComponents", 4, 0, NULL);
+INSERT INTO "HVS_NODE" VALUES (4005, "CaloIdentifier", 4, 0, NULL);
 -- Data for the HVS_TAG2NODE table
 -- Command to get midnight of current date in UT:
 -- date -u --date '00:00 today' +%s
 INSERT INTO "HVS_TAG2NODE" VALUES (0, "FASER-00", 100000, NULL, 0, 0, 1549238400000000000, NULL, 22);
-INSERT INTO "HVS_TAG2NODE" VALUES (1, "Scintillator-00", 100001, NULL, 0, 0, 1549238400000000000, NULL, 22);
-INSERT INTO "HVS_TAG2NODE" VALUES (2, "Tracker-00", 100002, NULL, 0, 0, 1549238400000000000, NULL, 22);
-INSERT INTO "HVS_TAG2NODE" VALUES (21, "SCT-00", 100026, NULL, 0, 0, 1567987200000000000, NULL, 22);
-INSERT INTO "HVS_TAG2NODE" VALUES (22, "Dipole-00", 100027, NULL, 0, 0, 1568678400000000000, NULL, 22);
-INSERT INTO "HVS_TAG2NODE" VALUES (210, "SctTopLevel-00", 106788, NULL, 0, 0, 1567987200000000000, NULL, 22);
-INSERT INTO "HVS_TAG2NODE" VALUES (211, "SctBarrelModule-00", 107003, NULL, 0, 0, 1567987200000000000, NULL, 22);
-INSERT INTO "HVS_TAG2NODE" VALUES (212, "SctBarrelSensor-00", 106730, NULL, 0, 0, 1567987200000000000, NULL, 22);
-INSERT INTO "HVS_TAG2NODE" VALUES (213, "SctFaserGeneral-00", 106789, NULL, 0, 0, 1567987200000000000, NULL, 22);
-INSERT INTO "HVS_TAG2NODE" VALUES (214, "SctSwitches-00", 107782, NULL, 0, 0, 1567987200000000000, NULL, 22);
-INSERT INTO "HVS_TAG2NODE" VALUES (215, "SctMaterials-00", 107777, NULL, 0, 0, 1567987200000000000, NULL, 22);
-INSERT INTO "HVS_TAG2NODE" VALUES (216, "SctMatComponents-00", 107778, NULL, 0, 0, 1567987200000000000, NULL, 22);
-INSERT INTO "HVS_TAG2NODE" VALUES (217, "SctConditions-00", 107779, NULL, 0, 0, 1579564800000000000, NULL, 22);
-INSERT INTO "HVS_TAG2NODE" VALUES (220, "DipoleTopLevel-00", 100029, NULL, 0, 0, 1568678400000000000, NULL, 22);
-INSERT INTO "HVS_TAG2NODE" VALUES (221, "DipoleGeneral-00", 100004, NULL, 0, 0, 1568678400000000000, NULL, 22);
-INSERT INTO "HVS_TAG2NODE" VALUES (224, "DipoleSwitches-00", 100028, NULL, 0, 0, 1568678400000000000, NULL, 22);
-INSERT INTO "HVS_TAG2NODE" VALUES (3, "Calorimeter-00", 100003, NULL, 0, 0, 1549238400000000000, NULL, 22);
-INSERT INTO "HVS_TAG2NODE" VALUES (100, "Materials-00", 100005, NULL, 0, 0, 1549238400000000000, NULL, 22);
-INSERT INTO "HVS_TAG2NODE" VALUES (101, "StdMaterials-00", 100006, NULL, 0, 0, 1549238400000000000, NULL, 22);
-INSERT INTO "HVS_TAG2NODE" VALUES (102, "StdMatComponents-00", 100007, NULL, 0, 0, 1549238400000000000, NULL, 22);
-INSERT INTO "HVS_TAG2NODE" VALUES (103, "Elements-00", 100008, NULL, 0, 0, 1549238400000000000, NULL, 22);
-INSERT INTO "HVS_TAG2NODE" VALUES (1001, "VetoTopLevel-00", 100009, NULL, 0, 0, 1567123200000000000, NULL, 22);
-INSERT INTO "HVS_TAG2NODE" VALUES (1002, "VetoStationGeneral-00", 100010, NULL, 0, 0, 1567123200000000000, NULL, 22);
-INSERT INTO "HVS_TAG2NODE" VALUES (1006, "VetoPlateGeneral-00", 100025, NULL, 0, 0, 1567209600000000000, NULL, 22);
-INSERT INTO "HVS_TAG2NODE" VALUES (1101, "TriggerTopLevel-00", 110009, NULL, 0, 0, 1581292800000000000, NULL, 22);
-INSERT INTO "HVS_TAG2NODE" VALUES (1102, "TriggerStationGeneral-00", 110010, NULL, 0, 0, 1581292800000000000, NULL, 22);
-INSERT INTO "HVS_TAG2NODE" VALUES (1106, "TriggerPlateGeneral-00", 110025, NULL, 0, 0, 1581292800000000000, NULL, 22);
-INSERT INTO "HVS_TAG2NODE" VALUES (1201, "PreshowerTopLevel-00", 120009, NULL, 0, 0, 1581292800000000000, NULL, 22);
-INSERT INTO "HVS_TAG2NODE" VALUES (1202, "PreshowerStationGeneral-00", 120010, NULL, 0, 0, 1581292800000000000, NULL, 22);
-INSERT INTO "HVS_TAG2NODE" VALUES (1206, "PreshowerPlateGeneral-00", 120025, NULL, 0, 0, 1581292800000000000, NULL, 22);
-INSERT INTO "HVS_TAG2NODE" VALUES (1003, "ScintMaterials-00", 100011, NULL, 0, 0, 1549238400000000000, NULL, 22);
-INSERT INTO "HVS_TAG2NODE" VALUES (1004, "ScintMatComponents-00", 100012, NULL, 0, 0, 1549238400000000000, NULL, 22);
-INSERT INTO "HVS_TAG2NODE" VALUES (2003, "TrackerMaterials-00", 100021, NULL, 0, 0, 1550448000000000000, NULL, 22);
-INSERT INTO "HVS_TAG2NODE" VALUES (2004, "TrackerMatComponents-00", 100022, NULL, 0, 0, 1550448000000000000, NULL, 22);
-INSERT INTO "HVS_TAG2NODE" VALUES (3003, "CaloMaterials-00", 100023, NULL, 0, 0, 1550448000000000000, NULL, 22);
-INSERT INTO "HVS_TAG2NODE" VALUES (3004, "CaloMatComponents-00", 100024, NULL, 0, 0, 1550448000000000000, NULL, 22);
-INSERT INTO "HVS_TAG2NODE" VALUES (110,  "FaserCommon-00", 100013, NULL, 0, 0, 1549324800000000000, NULL, 22);
-INSERT INTO "HVS_TAG2NODE" VALUES (1100, "VetoSwitches-00", 100014, NULL, 0, 0, 1550361600000000000 ,NULL, 22);
-INSERT INTO "HVS_TAG2NODE" VALUES (1200, "TriggerSwitches-00", 110014, NULL, 0, 0, 1581292800000000000 ,NULL, 22);
-INSERT INTO "HVS_TAG2NODE" VALUES (1300, "PreshowerSwitches-00", 120014, NULL, 0, 0, 1550361600000000000 ,NULL, 22);
-INSERT INTO "HVS_TAG2NODE" VALUES (11, "Veto-00", 100015, NULL, 0, 0, 1550448000000000000, NULL, 22);
-INSERT INTO "HVS_TAG2NODE" VALUES (12, "Trigger-00", 100019, NULL, 0, 0, 1550448000000000000, NULL, 22);
-INSERT INTO "HVS_TAG2NODE" VALUES (13, "Preshower-00", 100020, NULL, 0, 0, 1550448000000000000, NULL, 22);
-INSERT INTO "HVS_TAG2NODE" VALUES (1005, "ScintIdentifier-00", 100016, NULL, 0, 0, 1550448000000000000, NULL, 22);
-INSERT INTO "HVS_TAG2NODE" VALUES (2005, "TrackerIdentifier-00", 100017, NULL, 0, 0, 1550448000000000000, NULL, 22);
-INSERT INTO "HVS_TAG2NODE" VALUES (3005, "CaloIdentifier-00", 100018, NULL, 0, 0, 1550448000000000000, NULL, 22);
+INSERT INTO "HVS_TAG2NODE" VALUES (90,   "FaserCommon-00", 100013, NULL, 0, 0, 1549324800000000000, NULL, 22);
+INSERT INTO "HVS_TAG2NODE" VALUES (9000, "Materials-00", 100005, NULL, 0, 0, 1549238400000000000, NULL, 22);
+INSERT INTO "HVS_TAG2NODE" VALUES (9001, "StdMaterials-00", 100006, NULL, 0, 0, 1549238400000000000, NULL, 22);
+INSERT INTO "HVS_TAG2NODE" VALUES (9002, "StdMatComponents-00", 100007, NULL, 0, 0, 1549238400000000000, NULL, 22);
+INSERT INTO "HVS_TAG2NODE" VALUES (9003, "Elements-00", 100008, NULL, 0, 0, 1549238400000000000, NULL, 22);
+INSERT INTO "HVS_TAG2NODE" VALUES (1, "Neutrino-00", 100031, NULL, 0, 0, 1582416000000000000, NULL, 22);
+INSERT INTO "HVS_TAG2NODE" VALUES (11,"Emulsion-00", 100034, NULL, 0, 0, 1582416000000000000, NULL, 22);
+INSERT INTO "HVS_TAG2NODE" VALUES (110, "EmulsionTopLevel-00", 100035, NULL, 0, 0, 1582416000000000000, NULL, 22);
+INSERT INTO "HVS_TAG2NODE" VALUES (114, "EmulsionSwitches-00", 100036, NULL, 0, 0, 1582416000000000000, NULL, 22);
+INSERT INTO "HVS_TAG2NODE" VALUES (2, "Scintillator-00", 100001, NULL, 0, 0, 1549238400000000000, NULL, 22);
+INSERT INTO "HVS_TAG2NODE" VALUES (3, "Tracker-00", 100002, NULL, 0, 0, 1549238400000000000, NULL, 22);
+INSERT INTO "HVS_TAG2NODE" VALUES (31, "SCT-00", 100026, NULL, 0, 0, 1567987200000000000, NULL, 22);
+INSERT INTO "HVS_TAG2NODE" VALUES (32, "Dipole-00", 100027, NULL, 0, 0, 1568678400000000000, NULL, 22);
+INSERT INTO "HVS_TAG2NODE" VALUES (310, "SctTopLevel-00", 106788, NULL, 0, 0, 1567987200000000000, NULL, 22);
+INSERT INTO "HVS_TAG2NODE" VALUES (311, "SctBarrelModule-00", 107003, NULL, 0, 0, 1567987200000000000, NULL, 22);
+INSERT INTO "HVS_TAG2NODE" VALUES (312, "SctBarrelSensor-00", 106730, NULL, 0, 0, 1567987200000000000, NULL, 22);
+INSERT INTO "HVS_TAG2NODE" VALUES (313, "SctFaserGeneral-00", 106789, NULL, 0, 0, 1567987200000000000, NULL, 22);
+INSERT INTO "HVS_TAG2NODE" VALUES (314, "SctSwitches-00", 107782, NULL, 0, 0, 1567987200000000000, NULL, 22);
+INSERT INTO "HVS_TAG2NODE" VALUES (315, "SctMaterials-00", 107777, NULL, 0, 0, 1567987200000000000, NULL, 22);
+INSERT INTO "HVS_TAG2NODE" VALUES (316, "SctMatComponents-00", 107778, NULL, 0, 0, 1567987200000000000, NULL, 22);
+INSERT INTO "HVS_TAG2NODE" VALUES (317, "SctConditions-00", 107779, NULL, 0, 0, 1579564800000000000, NULL, 22);
+INSERT INTO "HVS_TAG2NODE" VALUES (320, "DipoleTopLevel-00", 100029, NULL, 0, 0, 1568678400000000000, NULL, 22);
+INSERT INTO "HVS_TAG2NODE" VALUES (321, "DipoleGeneral-00", 100004, NULL, 0, 0, 1568678400000000000, NULL, 22);
+INSERT INTO "HVS_TAG2NODE" VALUES (324, "DipoleSwitches-00", 100028, NULL, 0, 0, 1568678400000000000, NULL, 22);
+INSERT INTO "HVS_TAG2NODE" VALUES (4, "Calorimeter-00", 100003, NULL, 0, 0, 1549238400000000000, NULL, 22);
+INSERT INTO "HVS_TAG2NODE" VALUES (210,  "VetoTopLevel-00", 100009, NULL, 0, 0, 1567123200000000000, NULL, 22);
+INSERT INTO "HVS_TAG2NODE" VALUES (211,  "VetoStationGeneral-00", 100010, NULL, 0, 0, 1567123200000000000, NULL, 22);
+INSERT INTO "HVS_TAG2NODE" VALUES (212,  "VetoPlateGeneral-00", 100025, NULL, 0, 0, 1567209600000000000, NULL, 22);
+INSERT INTO "HVS_TAG2NODE" VALUES (220,  "TriggerTopLevel-00", 110009, NULL, 0, 0, 1581292800000000000, NULL, 22);
+INSERT INTO "HVS_TAG2NODE" VALUES (221,  "TriggerStationGeneral-00", 110010, NULL, 0, 0, 1581292800000000000, NULL, 22);
+INSERT INTO "HVS_TAG2NODE" VALUES (222,  "TriggerPlateGeneral-00", 110025, NULL, 0, 0, 1581292800000000000, NULL, 22);
+INSERT INTO "HVS_TAG2NODE" VALUES (230,  "PreshowerTopLevel-00", 120009, NULL, 0, 0, 1581292800000000000, NULL, 22);
+INSERT INTO "HVS_TAG2NODE" VALUES (231,  "PreshowerStationGeneral-00", 120010, NULL, 0, 0, 1581292800000000000, NULL, 22);
+INSERT INTO "HVS_TAG2NODE" VALUES (232,  "PreshowerPlateGeneral-00", 120025, NULL, 0, 0, 1581292800000000000, NULL, 22);
+INSERT INTO "HVS_TAG2NODE" VALUES (1003, "NeutrinoMaterials-00", 100032, NULL, 0, 0, 1582416000000000000, NULL, 22);
+INSERT INTO "HVS_TAG2NODE" VALUES (1004, "NeutrinoMatComponents-00", 100033, NULL, 0, 0, 1582416000000000000, NULL, 22);
+INSERT INTO "HVS_TAG2NODE" VALUES (2003, "ScintMaterials-00", 100011, NULL, 0, 0, 1549238400000000000, NULL, 22);
+INSERT INTO "HVS_TAG2NODE" VALUES (2004, "ScintMatComponents-00", 100012, NULL, 0, 0, 1549238400000000000, NULL, 22);
+INSERT INTO "HVS_TAG2NODE" VALUES (3003, "TrackerMaterials-00", 100021, NULL, 0, 0, 1550448000000000000, NULL, 22);
+INSERT INTO "HVS_TAG2NODE" VALUES (3004, "TrackerMatComponents-00", 100022, NULL, 0, 0, 1550448000000000000, NULL, 22);
+INSERT INTO "HVS_TAG2NODE" VALUES (4003, "CaloMaterials-00", 100023, NULL, 0, 0, 1550448000000000000, NULL, 22);
+INSERT INTO "HVS_TAG2NODE" VALUES (4004, "CaloMatComponents-00", 100024, NULL, 0, 0, 1550448000000000000, NULL, 22);
+INSERT INTO "HVS_TAG2NODE" VALUES (214,  "VetoSwitches-00", 100014, NULL, 0, 0, 1550361600000000000 ,NULL, 22);
+INSERT INTO "HVS_TAG2NODE" VALUES (224,  "TriggerSwitches-00", 110014, NULL, 0, 0, 1581292800000000000 ,NULL, 22);
+INSERT INTO "HVS_TAG2NODE" VALUES (234,  "PreshowerSwitches-00", 120014, NULL, 0, 0, 1550361600000000000 ,NULL, 22);
+INSERT INTO "HVS_TAG2NODE" VALUES (21, "Veto-00", 100015, NULL, 0, 0, 1550448000000000000, NULL, 22);
+INSERT INTO "HVS_TAG2NODE" VALUES (22, "Trigger-00", 100019, NULL, 0, 0, 1550448000000000000, NULL, 22);
+INSERT INTO "HVS_TAG2NODE" VALUES (23, "Preshower-00", 100020, NULL, 0, 0, 1550448000000000000, NULL, 22);
+INSERT INTO "HVS_TAG2NODE" VALUES (1005, "NeutrinoIdentifier-00", 100030, NULL, 0, 0, 1582416000000000000, NULL, 22);
+INSERT INTO "HVS_TAG2NODE" VALUES (2005, "ScintIdentifier-00", 100016, NULL, 0, 0, 1550448000000000000, NULL, 22);
+INSERT INTO "HVS_TAG2NODE" VALUES (3005, "TrackerIdentifier-00", 100017, NULL, 0, 0, 1550448000000000000, NULL, 22);
+INSERT INTO "HVS_TAG2NODE" VALUES (4005, "CaloIdentifier-00", 100018, NULL, 0, 0, 1550448000000000000, NULL, 22);
 -- Data for the HVS_LTAG2LTAG table
-INSERT INTO "HVS_LTAG2LTAG" VALUES (0,   100000, 1,    100001);
-INSERT INTO "HVS_LTAG2LTAG" VALUES (0,   100000, 2,    100002);
-INSERT INTO "HVS_LTAG2LTAG" VALUES (0,   100000, 3,    100003);
-INSERT INTO "HVS_LTAG2LTAG" VALUES (0,   100000, 100,  100005);
-INSERT INTO "HVS_LTAG2LTAG" VALUES (100, 100005, 101,  100006);
-INSERT INTO "HVS_LTAG2LTAG" VALUES (100, 100005, 102,  100007);
-INSERT INTO "HVS_LTAG2LTAG" VALUES (100, 100005, 103,  100008);
-INSERT INTO "HVS_LTAG2LTAG" VALUES (11,  100015, 1001, 100009);
-INSERT INTO "HVS_LTAG2LTAG" VALUES (11,  100015, 1002, 100010);
-INSERT INTO "HVS_LTAG2LTAG" VALUES (11,  100015, 1006, 100025);
-INSERT INTO "HVS_LTAG2LTAG" VALUES (12,  110015, 1101, 110009);
-INSERT INTO "HVS_LTAG2LTAG" VALUES (12,  110015, 1102, 110010);
-INSERT INTO "HVS_LTAG2LTAG" VALUES (12,  110015, 1106, 110025);
-INSERT INTO "HVS_LTAG2LTAG" VALUES (13,  120015, 1201, 120009);
-INSERT INTO "HVS_LTAG2LTAG" VALUES (13,  120015, 1202, 120010);
-INSERT INTO "HVS_LTAG2LTAG" VALUES (13,  120015, 1206, 120025);
-INSERT INTO "HVS_LTAG2LTAG" VALUES (1,   100001, 1003, 100011);
-INSERT INTO "HVS_LTAG2LTAG" VALUES (1,   100001, 1004, 100012);
-INSERT INTO "HVS_LTAG2LTAG" VALUES (2,   100002, 2003, 100021);
-INSERT INTO "HVS_LTAG2LTAG" VALUES (2,   100002, 2004, 100022);
-INSERT INTO "HVS_LTAG2LTAG" VALUES (2,   100002, 21,   100026);
-INSERT INTO "HVS_LTAG2LTAG" VALUES (21,  100026, 210,  106788);
-INSERT INTO "HVS_LTAG2LTAG" VALUES (21,  100026, 211,  107003);
-INSERT INTO "HVS_LTAG2LTAG" VALUES (21,  100026, 212,  106730);
-INSERT INTO "HVS_LTAG2LTAG" VALUES (21,  100026, 213,  106789);
-INSERT INTO "HVS_LTAG2LTAG" VALUES (21,  100026, 214,  107782);
-INSERT INTO "HVS_LTAG2LTAG" VALUES (21,  100026, 215,  107777);
-INSERT INTO "HVS_LTAG2LTAG" VALUES (21,  100026, 216,  107778);
-INSERT INTO "HVS_LTAG2LTAG" VALUES (21,  100026, 217,  107779);
-INSERT INTO "HVS_LTAG2LTAG" VALUES (2,   100002, 22,   100027);
-INSERT INTO "HVS_LTAG2LTAG" VALUES (22,  100027, 220,  100029);
-INSERT INTO "HVS_LTAG2LTAG" VALUES (22,  100027, 221,  100004);
-INSERT INTO "HVS_LTAG2LTAG" VALUES (22,  100027, 224,  100028);
-INSERT INTO "HVS_LTAG2LTAG" VALUES (3,   100003, 3003, 100023);
-INSERT INTO "HVS_LTAG2LTAG" VALUES (3,   100003, 3004, 100024);
-INSERT INTO "HVS_LTAG2LTAG" VALUES (0,   100000, 110,  100013);
-INSERT INTO "HVS_LTAG2LTAG" VALUES (1,   100001, 11,   100015);
-INSERT INTO "HVS_LTAG2LTAG" VALUES (1,   100001, 12,   100019);
-INSERT INTO "HVS_LTAG2LTAG" VALUES (1,   100001, 13,   100020);
-INSERT INTO "HVS_LTAG2LTAG" VALUES (11,  100015, 1100, 100014);
-INSERT INTO "HVS_LTAG2LTAG" VALUES (12,  110015, 1200, 110014);
-INSERT INTO "HVS_LTAG2LTAG" VALUES (13,  120015, 1300, 120014);
-INSERT INTO "HVS_LTAG2LTAG" VALUES (1,   100001, 1005, 100016);
-INSERT INTO "HVS_LTAG2LTAG" VALUES (2,   100002, 2005, 100017);
-INSERT INTO "HVS_LTAG2LTAG" VALUES (3,   100003, 3005, 100018);
+INSERT INTO "HVS_LTAG2LTAG" VALUES (0,   100000, 2,    100001);
+INSERT INTO "HVS_LTAG2LTAG" VALUES (0,   100000, 3,    100002);
+INSERT INTO "HVS_LTAG2LTAG" VALUES (0,   100000, 4,    100003);
+INSERT INTO "HVS_LTAG2LTAG" VALUES (0,    100000, 9000,  100005);
+INSERT INTO "HVS_LTAG2LTAG" VALUES (9000, 100005, 9001,  100006);
+INSERT INTO "HVS_LTAG2LTAG" VALUES (9000, 100005, 9002,  100007);
+INSERT INTO "HVS_LTAG2LTAG" VALUES (9000, 100005, 9003,  100008);
+INSERT INTO "HVS_LTAG2LTAG" VALUES (1,   100031,  11,  100034);
+INSERT INTO "HVS_LTAG2LTAG" VALUES (11,  100034, 110,  100035);
+INSERT INTO "HVS_LTAG2LTAG" VALUES (11,  100034, 114,  100036);
+INSERT INTO "HVS_LTAG2LTAG" VALUES (1,   100031, 1003, 100032);
+INSERT INTO "HVS_LTAG2LTAG" VALUES (1,   100031, 1004, 100033);
+INSERT INTO "HVS_LTAG2LTAG" VALUES (21,  100015, 210,  100009);
+INSERT INTO "HVS_LTAG2LTAG" VALUES (21,  100015, 211,  100010);
+INSERT INTO "HVS_LTAG2LTAG" VALUES (21,  100015, 212,  100025);
+INSERT INTO "HVS_LTAG2LTAG" VALUES (22,  110015, 220,  110009);
+INSERT INTO "HVS_LTAG2LTAG" VALUES (22,  110015, 221,  110010);
+INSERT INTO "HVS_LTAG2LTAG" VALUES (22,  110015, 222,  110025);
+INSERT INTO "HVS_LTAG2LTAG" VALUES (23,  120015, 230,  120009);
+INSERT INTO "HVS_LTAG2LTAG" VALUES (23,  120015, 231,  120010);
+INSERT INTO "HVS_LTAG2LTAG" VALUES (23,  120015, 232,  120025);
+INSERT INTO "HVS_LTAG2LTAG" VALUES (2,   100001, 2003, 100011);
+INSERT INTO "HVS_LTAG2LTAG" VALUES (2,   100001, 2004, 100012);
+INSERT INTO "HVS_LTAG2LTAG" VALUES (3,   100002, 3003, 100021);
+INSERT INTO "HVS_LTAG2LTAG" VALUES (3,   100002, 3004, 100022);
+INSERT INTO "HVS_LTAG2LTAG" VALUES (3,   100002, 31,   100026);
+INSERT INTO "HVS_LTAG2LTAG" VALUES (31,  100026, 310,  106788);
+INSERT INTO "HVS_LTAG2LTAG" VALUES (31,  100026, 311,  107003);
+INSERT INTO "HVS_LTAG2LTAG" VALUES (31,  100026, 312,  106730);
+INSERT INTO "HVS_LTAG2LTAG" VALUES (31,  100026, 313,  106789);
+INSERT INTO "HVS_LTAG2LTAG" VALUES (31,  100026, 314,  107782);
+INSERT INTO "HVS_LTAG2LTAG" VALUES (31,  100026, 315,  107777);
+INSERT INTO "HVS_LTAG2LTAG" VALUES (31,  100026, 316,  107778);
+INSERT INTO "HVS_LTAG2LTAG" VALUES (31,  100026, 317,  107779);
+INSERT INTO "HVS_LTAG2LTAG" VALUES (3,   100002, 32,   100027);
+INSERT INTO "HVS_LTAG2LTAG" VALUES (32,  100027, 320,  100029);
+INSERT INTO "HVS_LTAG2LTAG" VALUES (32,  100027, 321,  100004);
+INSERT INTO "HVS_LTAG2LTAG" VALUES (32,  100027, 324,  100028);
+INSERT INTO "HVS_LTAG2LTAG" VALUES (4,   100003, 4003, 100023);
+INSERT INTO "HVS_LTAG2LTAG" VALUES (4,   100003, 4004, 100024);
+INSERT INTO "HVS_LTAG2LTAG" VALUES (0,   100000, 90,   100013);
+INSERT INTO "HVS_LTAG2LTAG" VALUES (2,   100001, 21,   100015);
+INSERT INTO "HVS_LTAG2LTAG" VALUES (2,   100001, 22,   100019);
+INSERT INTO "HVS_LTAG2LTAG" VALUES (2,   100001, 23,   100020);
+INSERT INTO "HVS_LTAG2LTAG" VALUES (21,  100015, 214,  100014);
+INSERT INTO "HVS_LTAG2LTAG" VALUES (22,  110015, 224,  110014);
+INSERT INTO "HVS_LTAG2LTAG" VALUES (23,  120015, 234,  120014);
+INSERT INTO "HVS_LTAG2LTAG" VALUES (1,   100031, 1005, 100030);
+INSERT INTO "HVS_LTAG2LTAG" VALUES (2,   100001, 2005, 100016);
+INSERT INTO "HVS_LTAG2LTAG" VALUES (3,   100002, 3005, 100017);
+INSERT INTO "HVS_LTAG2LTAG" VALUES (4,   100003, 4005, 100018);
 -- Data for the HVS_TAGCACHE table
 INSERT INTO "HVS_TAGCACHE" VALUES ("FASER-00", "FASER",              "FASER-00",                100000);
+INSERT INTO "HVS_TAGCACHE" VALUES ("FASER-00", "FaserCommon",        "FaserCommon-00",          100013);
+INSERT INTO "HVS_TAGCACHE" VALUES ("FASER-00", "Materials",          "Materials-00",            100005);
+INSERT INTO "HVS_TAGCACHE" VALUES ("FASER-00", "StdMaterials",       "StdMaterials-00",         100006);
+INSERT INTO "HVS_TAGCACHE" VALUES ("FASER-00", "StdMatComponents",   "StdMatComponents-00",     100007);
+INSERT INTO "HVS_TAGCACHE" VALUES ("FASER-00", "Elements",           "Elements-00",             100008);
+INSERT INTO "HVS_TAGCACHE" VALUES ("FASER-00", "Neutrino",           "Neutrino-00",             100031);
+INSERT INTO "HVS_TAGCACHE" VALUES ("FASER-00", "Emulsion",           "Emulsion-00",             100034);
+INSERT INTO "HVS_TAGCACHE" VALUES ("FASER-00", "EmulsionTopLevel",   "EmulsionTopLevel-00",     100035);
+INSERT INTO "HVS_TAGCACHE" VALUES ("FASER-00", "EmulsionSwitches",   "EmulsionSwitches-00",     100036);
 INSERT INTO "HVS_TAGCACHE" VALUES ("FASER-00", "Scintillator",       "Scintillator-00",         100001);
 INSERT INTO "HVS_TAGCACHE" VALUES ("FASER-00", "Tracker",            "Tracker-00",              100002);
 INSERT INTO "HVS_TAGCACHE" VALUES ("FASER-00", "SCT",                "SCT-00",                  100026);
@@ -602,10 +712,6 @@ INSERT INTO "HVS_TAGCACHE" VALUES ("FASER-00", "DipoleTopLevel",     "DipoleTopL
 INSERT INTO "HVS_TAGCACHE" VALUES ("FASER-00", "DipoleGeneral",      "DipoleGeneral-00",        100004);
 INSERT INTO "HVS_TAGCACHE" VALUES ("FASER-00", "DipoleSwitches",     "DipoleSwitches-00",       100028);
 INSERT INTO "HVS_TAGCACHE" VALUES ("FASER-00", "Calorimeter",        "Calorimeter-00",          100003);
-INSERT INTO "HVS_TAGCACHE" VALUES ("FASER-00", "Materials",          "Materials-00",            100005);
-INSERT INTO "HVS_TAGCACHE" VALUES ("FASER-00", "StdMaterials",       "StdMaterials-00",         100006);
-INSERT INTO "HVS_TAGCACHE" VALUES ("FASER-00", "StdMatComponents",   "StdMatComponents-00",     100007);
-INSERT INTO "HVS_TAGCACHE" VALUES ("FASER-00", "Elements",           "Elements-00",             100008);
 INSERT INTO "HVS_TAGCACHE" VALUES ("FASER-00", "VetoTopLevel",       "VetoTopLevel-00",         100009);
 INSERT INTO "HVS_TAGCACHE" VALUES ("FASER-00", "VetoStationGeneral", "VetoStationGeneral-00",   100010);
 INSERT INTO "HVS_TAGCACHE" VALUES ("FASER-00", "VetoPlateGeneral",   "VetoPlateGeneral-00",     100025);
@@ -615,19 +721,21 @@ INSERT INTO "HVS_TAGCACHE" VALUES ("FASER-00", "TriggerPlateGeneral",   "Trigger
 INSERT INTO "HVS_TAGCACHE" VALUES ("FASER-00", "PreshowerTopLevel",     "PreshowerTopLevel-00",         120009);
 INSERT INTO "HVS_TAGCACHE" VALUES ("FASER-00", "PreshowerStationGeneral", "PreshowerStationGeneral-00",   120010);
 INSERT INTO "HVS_TAGCACHE" VALUES ("FASER-00", "PreshowerPlateGeneral",   "PreshowerPlateGeneral-00",     120025);
+INSERT INTO "HVS_TAGCACHE" VALUES ("FASER-00", "NeutrinoMaterials",     "NeutrinoMaterials-00",       100032);
+INSERT INTO "HVS_TAGCACHE" VALUES ("FASER-00", "NeutrinoMatComponents", "NeutrinoMatComponents-00",   100033);
 INSERT INTO "HVS_TAGCACHE" VALUES ("FASER-00", "ScintMaterials",     "ScintMaterials-00",       100011);
 INSERT INTO "HVS_TAGCACHE" VALUES ("FASER-00", "ScintMatComponents", "ScintMatComponents-00",   100012);
 INSERT INTO "HVS_TAGCACHE" VALUES ("FASER-00", "TrackerMaterials",     "TrackerMaterials-00",     100021);
 INSERT INTO "HVS_TAGCACHE" VALUES ("FASER-00", "TrackerMatComponents", "TrackerMatComponents-00", 100022);
 INSERT INTO "HVS_TAGCACHE" VALUES ("FASER-00", "CaloMaterials",     "CaloMaterials-00",         100023);
 INSERT INTO "HVS_TAGCACHE" VALUES ("FASER-00", "CaloMatComponents", "CaloMatComponents-00",     100024);
-INSERT INTO "HVS_TAGCACHE" VALUES ("FASER-00", "FaserCommon",        "FaserCommon-00",          100013);
 INSERT INTO "HVS_TAGCACHE" VALUES ("FASER-00", "VetoSwitches",       "VetoSwitches-00",         100014);
 INSERT INTO "HVS_TAGCACHE" VALUES ("FASER-00", "TriggerSwitches",    "TriggerSwitches-00",      110014);
 INSERT INTO "HVS_TAGCACHE" VALUES ("FASER-00", "PreshowerSwitches",  "PreshowerSwitches-00",    120014);
 INSERT INTO "HVS_TAGCACHE" VALUES ("FASER-00", "Veto",               "Veto-00",                 100015);
 INSERT INTO "HVS_TAGCACHE" VALUES ("FASER-00", "Trigger",            "Trigger-00",              100019);
 INSERT INTO "HVS_TAGCACHE" VALUES ("FASER-00", "Preshower",          "Preshower-00",            100020);
+INSERT INTO "HVS_TAGCACHE" VALUES ("FASER-00", "NeutrinoIdentifier", "NeutrinoIdentifier-00",   100030);
 INSERT INTO "HVS_TAGCACHE" VALUES ("FASER-00", "ScintIdentifier",    "ScintIdentifier-00",      100016);
 INSERT INTO "HVS_TAGCACHE" VALUES ("FASER-00", "TrackerIdentifier",  "TrackerIdentifier-00",    100017);
 INSERT INTO "HVS_TAGCACHE" VALUES ("FASER-00", "CaloIdentifier",     "CaloIdentifier-00",       100018);
@@ -1244,6 +1352,10 @@ INSERT INTO "PRESHOWERSWITCHES_DATA" VALUES  (0, "Preshower", 1, 0, "GEO", "Deve
 INSERT INTO "PRESHOWERSWITCHES_DATA2TAG" VALUES (120014, 0);
 --
 --
+INSERT INTO "NEUTRINOIDENTIFIER_DATA" VALUES (0, "Neutrino", "NeutrinoIdDictFiles/IdDictNeutrino.xml", "Baseline layout");
+INSERT INTO "NEUTRINOIDENTIFIER_DATA2TAG" VALUES (100030, 0);
+--
+--
 INSERT INTO "SCINTIDENTIFIER_DATA" VALUES (0, "Scintillator", "ScintIdDictFiles/IdDictScintillator.xml", "Baseline layout");
 INSERT INTO "SCINTIDENTIFIER_DATA2TAG" VALUES (100016, 0);
 --
diff --git a/DetectorDescription/GeoModel/GeoModelFaserUtilities/src/DecodeFaserVersionKey.cxx b/DetectorDescription/GeoModel/GeoModelFaserUtilities/src/DecodeFaserVersionKey.cxx
index 5c6b489c..cd85de94 100644
--- a/DetectorDescription/GeoModel/GeoModelFaserUtilities/src/DecodeFaserVersionKey.cxx
+++ b/DetectorDescription/GeoModel/GeoModelFaserUtilities/src/DecodeFaserVersionKey.cxx
@@ -35,8 +35,14 @@ void DecodeFaserVersionKey::defineTag(const T* svc, const std::string & node)
   std::string nodeOverrideTag;
   std::string scintOverrideTag; // Scint has two levels.
   std::string trackerOverrideTag;
+  std::string neutrinoOverrideTag;
   if (node == "FASER") {
     nodeOverrideTag = "";
+  } else if (node == "Neutrino") {
+    nodeOverrideTag = svc->neutrinoVersionOverride();
+  } else if (node == "Emulsion") {
+    neutrinoOverrideTag = svc->neutrinoVersionOverride();
+    nodeOverrideTag = svc->emulsionVersionOverride();    
   } else if (node == "Scintillator") {
     nodeOverrideTag = svc->scintVersionOverride();
   } else if (node == "Veto") {
@@ -67,6 +73,19 @@ void DecodeFaserVersionKey::defineTag(const T* svc, const std::string & node)
   m_tag = svc->faserVersion();
   m_node = "FASER";
   
+  // If neutrinoOverrideTag is specified (and is not just "CUSTOM") then override with the neutrino tag.
+  std::string neutrinoTag;
+  if (!neutrinoOverrideTag.empty()) {
+    // We dont care about the return value (custom = true/false). We only take notice of the custom 
+    // flag if the override is at the node we have selected. Ie we only look at nodeOverrideTag 
+    // in order to set m_custom. At any rate, we have to remove the CUSTOM string if it is present.
+    getCustomTag(neutrinoOverrideTag, neutrinoTag);
+  }
+  if (!neutrinoTag.empty()) {
+    m_tag = neutrinoTag;
+    m_node = "Neutrino";
+  }
+
   // If scintOverrideTag is specified (and is not just "CUSTOM") then override with the scint tag.
   std::string scintTag;
   if (!scintOverrideTag.empty()) {
diff --git a/DetectorDescription/GeoModel/GeoModelInterfaces/GeoModelInterfaces/IGeoDbTagSvc.h b/DetectorDescription/GeoModel/GeoModelInterfaces/GeoModelInterfaces/IGeoDbTagSvc.h
index 172e0e9f..e4e86248 100644
--- a/DetectorDescription/GeoModel/GeoModelInterfaces/GeoModelInterfaces/IGeoDbTagSvc.h
+++ b/DetectorDescription/GeoModel/GeoModelInterfaces/GeoModelInterfaces/IGeoDbTagSvc.h
@@ -28,6 +28,8 @@ class IGeoDbTagSvc : virtual public IInterface {
   static const InterfaceID& interfaceID() {return IID_IGeoDbTagSvc;}
 
   virtual const std::string & faserVersion()                    const =0;
+  virtual const std::string & neutrinoVersion()                 const =0;
+  virtual const std::string & emulsionVersion()                 const =0;
   virtual const std::string & scintVersion()                    const =0;
   virtual const std::string & vetoVersion()                     const =0; 
   virtual const std::string & triggerVersion()                  const =0; 
@@ -39,6 +41,8 @@ class IGeoDbTagSvc : virtual public IInterface {
   // virtual const std::string & magFieldVersion()                 const =0;
   // virtual const std::string & cavernInfraVersion()              const =0;
   
+  virtual const std::string & neutrinoVersionOverride()         const =0;
+  virtual const std::string & emulsionVersionOverride()         const =0;
   virtual const std::string & scintVersionOverride()            const =0;
   virtual const std::string & vetoVersionOverride()             const =0;
   virtual const std::string & triggerVersionOverride()          const =0;
diff --git a/DetectorDescription/GeoModel/GeoModelInterfaces/GeoModelInterfaces/IGeoModelSvc.h b/DetectorDescription/GeoModel/GeoModelInterfaces/GeoModelInterfaces/IGeoModelSvc.h
index f1151664..8b2d442c 100644
--- a/DetectorDescription/GeoModel/GeoModelInterfaces/GeoModelInterfaces/IGeoModelSvc.h
+++ b/DetectorDescription/GeoModel/GeoModelInterfaces/GeoModelInterfaces/IGeoModelSvc.h
@@ -26,6 +26,8 @@ public:
 
 
     virtual const std::string & faserVersion()         const =0;
+    virtual const std::string & neutrinoVersion()      const =0;
+    virtual const std::string & emulsionVersion()      const =0;
     virtual const std::string & scintVersion()         const =0;
     virtual const std::string & vetoVersion()          const =0;
     virtual const std::string & triggerVersion()       const =0;
@@ -37,6 +39,8 @@ public:
     // virtual const std::string & magFieldVersion()      const =0;
     // virtual const std::string & cavernInfraVersion()   const =0;
 
+    virtual const std::string & neutrinoVersionOverride()  const =0;
+    virtual const std::string & emulsionVersionOverride()  const =0;
     virtual const std::string & scintVersionOverride()     const =0;
     virtual const std::string & vetoVersionOverride()      const =0;
     virtual const std::string & triggerVersionOverride()   const =0;
diff --git a/DetectorDescription/GeoModel/GeoModelSvc/src/GeoDbTagSvc.cxx b/DetectorDescription/GeoModel/GeoModelSvc/src/GeoDbTagSvc.cxx
index 5ef46ab1..3ccdb51d 100644
--- a/DetectorDescription/GeoModel/GeoModelSvc/src/GeoDbTagSvc.cxx
+++ b/DetectorDescription/GeoModel/GeoModelSvc/src/GeoDbTagSvc.cxx
@@ -67,6 +67,15 @@ StatusCode GeoDbTagSvc::setupTags()
   }
 
   // Get subsystem tags
+  m_NeutrinoVersion = (m_NeutrinoVersionOverride.empty() 
+		    ? rdbAccessSvc->getChildTag("Neutrino", m_FaserVersion, "FASER", "FASERDD") 
+		    : m_NeutrinoVersionOverride);
+
+  m_EmulsionVersion = (m_EmulsionVersionOverride.empty() 
+		    ? rdbAccessSvc->getChildTag("Emulsion", m_NeutrinoVersion, "Neutrino", "FASERDD") 
+		    : m_EmulsionVersionOverride);
+
+
   m_ScintVersion = (m_ScintVersionOverride.empty() 
 		    ? rdbAccessSvc->getChildTag("Scintillator", m_FaserVersion, "FASER", "FASERDD") 
 		    : m_ScintVersionOverride);
diff --git a/DetectorDescription/GeoModel/GeoModelSvc/src/GeoDbTagSvc.h b/DetectorDescription/GeoModel/GeoModelSvc/src/GeoDbTagSvc.h
index ae018ab5..d965325d 100644
--- a/DetectorDescription/GeoModel/GeoModelSvc/src/GeoDbTagSvc.h
+++ b/DetectorDescription/GeoModel/GeoModelSvc/src/GeoDbTagSvc.h
@@ -28,6 +28,8 @@ class GeoDbTagSvc : public AthService, virtual public IGeoDbTagSvc
  protected:
 
   void setFaserVersion(const std::string& tag)                     { m_FaserVersion=tag; }
+  void setNeutrinoVersionOverride(const std::string& tag)          { m_NeutrinoVersionOverride=tag; }
+  void setEmulsionVersionOverride(const std::string& tag)          { m_EmulsionVersionOverride=tag; }
   void setScintVersionOverride(const std::string& tag)             { m_ScintVersionOverride=tag; }
   void setVetoVersionOverride(const std::string& tag)              { m_VetoVersionOverride=tag; }
   void setTriggerVersionOverride(const std::string& tag)           { m_TriggerVersionOverride=tag; }
@@ -44,6 +46,8 @@ class GeoDbTagSvc : public AthService, virtual public IGeoDbTagSvc
  private:
   // ______________________________ IGeoDbTagSvc ____________________________________
   const std::string & faserVersion()                     const { return m_FaserVersion; }
+  const std::string & neutrinoVersionOverride()          const { return m_NeutrinoVersionOverride; }
+  const std::string & emulsionVersionOverride()          const { return m_EmulsionVersionOverride; }
   const std::string & scintVersionOverride()             const { return m_ScintVersionOverride; }
   const std::string & vetoVersionOverride()              const { return m_VetoVersionOverride; }
   const std::string & triggerVersionOverride()           const { return m_TriggerVersionOverride; }
@@ -55,6 +59,8 @@ class GeoDbTagSvc : public AthService, virtual public IGeoDbTagSvc
   // const std::string & magFieldVersionOverride()          const { return m_MagFieldVersionOverride; }
   // const std::string & cavernInfraVersionOverride()       const { return m_CavernInfraVersionOverride; }
 
+  const std::string & neutrinoVersion()                  const { return m_NeutrinoVersion; }
+  const std::string & emulsionVersion()                  const { return m_EmulsionVersion; }
   const std::string & scintVersion()                     const { return m_ScintVersion; }
   const std::string & vetoVersion()                      const { return m_VetoVersion; }
   const std::string & triggerVersion()                   const { return m_TriggerVersion; }
@@ -71,6 +77,8 @@ class GeoDbTagSvc : public AthService, virtual public IGeoDbTagSvc
   // _________________________ Private data Members _______________________________
   std::string m_FaserVersion;
 
+  std::string m_NeutrinoVersion;
+  std::string m_EmulsionVersion;
   std::string m_ScintVersion;
   std::string m_VetoVersion;
   std::string m_TriggerVersion;
@@ -82,6 +90,8 @@ class GeoDbTagSvc : public AthService, virtual public IGeoDbTagSvc
   // std::string m_MagFieldVersion;
   // std::string m_CavernInfraVersion;
 
+  std::string m_NeutrinoVersionOverride;
+  std::string m_EmulsionVersionOverride;
   std::string m_ScintVersionOverride;
   std::string m_VetoVersionOverride;
   std::string m_TriggerVersionOverride;
diff --git a/DetectorDescription/GeoModel/GeoModelSvc/src/GeoModelSvc.cxx b/DetectorDescription/GeoModel/GeoModelSvc/src/GeoModelSvc.cxx
index 2278e5ab..a2d3fe7b 100644
--- a/DetectorDescription/GeoModel/GeoModelSvc/src/GeoModelSvc.cxx
+++ b/DetectorDescription/GeoModel/GeoModelSvc/src/GeoModelSvc.cxx
@@ -54,6 +54,8 @@ GeoModelSvc::GeoModelSvc(const std::string& name,ISvcLocator* svc)
   declareProperty( "DetectorTools",               m_detectorTools);
   declareProperty( "PrintMaterials",              m_printMaterials);
   declareProperty( "FaserVersion",                m_FaserVersion);
+  declareProperty( "NeutrinoVersionOverride",     m_NeutrinoVersionOverride);
+  declareProperty( "EmulsionVersionOverride",     m_EmulsionVersionOverride);
   declareProperty( "ScintVersionOverride",        m_ScintVersionOverride);
   declareProperty( "VetoVersionOverride",         m_VetoVersionOverride);
   declareProperty( "TriggerVersionOverride",      m_TriggerVersionOverride);
@@ -239,6 +241,8 @@ StatusCode GeoModelSvc::geoInit()
 {
   ATH_MSG_DEBUG("** Building geometry configuration: ");
   ATH_MSG_DEBUG("* FASER     tag: " << m_FaserVersion);
+  ATH_MSG_DEBUG("* Neutrino  tag: " << m_NeutrinoVersionOverride);
+  ATH_MSG_DEBUG("* Emulsion  tag: " << m_EmulsionVersionOverride);
   ATH_MSG_DEBUG("* Scint     tag: " << m_ScintVersionOverride);
   ATH_MSG_DEBUG("* Veto      tag: " << m_VetoVersionOverride);
   ATH_MSG_DEBUG("* Trigger   tag: " << m_TriggerVersionOverride);
@@ -307,6 +311,8 @@ StatusCode GeoModelSvc::geoInit()
   }
 
   dbTagSvc->setFaserVersion(m_FaserVersion);
+  dbTagSvc->setNeutrinoVersionOverride(m_NeutrinoVersionOverride);
+  dbTagSvc->setEmulsionVersionOverride(m_EmulsionVersionOverride);
   dbTagSvc->setScintVersionOverride(m_ScintVersionOverride);
   dbTagSvc->setVetoVersionOverride(m_VetoVersionOverride);
   dbTagSvc->setTriggerVersionOverride(m_TriggerVersionOverride);
@@ -478,6 +484,10 @@ StatusCode GeoModelSvc::compareTags(IOVSVC_CALLBACK_ARGS)
         tagsMatch = m_FaserVersion == pair.second;
       }
     }
+    else if(tagPairName=="GeoNeutrino")
+      tagsMatch = m_NeutrinoVersionOverride == pair.second;
+    else if(tagPairName=="GeoEmulsion")
+      tagsMatch = m_EmulsionVersionOverride == pair.second;
     else if(tagPairName=="GeoScint")
       tagsMatch = m_ScintVersionOverride == pair.second;
     else if(tagPairName=="GeoVeto")
@@ -503,6 +513,8 @@ StatusCode GeoModelSvc::compareTags(IOVSVC_CALLBACK_ARGS)
       << "*** *** Geometry configured through jobOptions does not match TagInfo tags! *** ***" << endmsg;
     ATH_MSG_INFO("** Job Option configuration: ");
     ATH_MSG_INFO("* FASER       tag: " << m_FaserVersion);
+    ATH_MSG_INFO("* Neutrino    tag: " << m_NeutrinoVersionOverride);
+    ATH_MSG_INFO("*   Emulsion  tag: " << m_EmulsionVersionOverride);
     ATH_MSG_INFO("* Scint       tag: " << m_ScintVersionOverride);
     ATH_MSG_INFO("*   Veto      tag: " << m_VetoVersionOverride);
     ATH_MSG_INFO("*   Trigger   tag: " << m_TriggerVersionOverride);
@@ -518,22 +530,26 @@ StatusCode GeoModelSvc::compareTags(IOVSVC_CALLBACK_ARGS)
       std::string tagPairName = pair.first;
       if(tagPairName=="GeoFaser")
         ATH_MSG_INFO("*FASER   tag: " << pair.second);
+      else if(tagPairName=="GeoNeutrino")
+        ATH_MSG_INFO("*Neutrino tag: " << pair.second);
+      else if(tagPairName=="GeoEmulsion")
+        ATH_MSG_INFO("*Emulsion   tag: " << pair.second);
       else if(tagPairName=="GeoScint")
-        ATH_MSG_INFO("*Scint   tag: " << pair.second);
+        ATH_MSG_INFO("*Scint    tag: " << pair.second);
       else if(tagPairName=="GeoVeto")
-        ATH_MSG_INFO("*Veto      tag: " << pair.second);
+        ATH_MSG_INFO("*Veto       tag: " << pair.second);
       else if(tagPairName=="GeoTrigger")
-        ATH_MSG_INFO("*Trigger   tag: " << pair.second);
+        ATH_MSG_INFO("*Trigger    tag: " << pair.second);
       else if(tagPairName=="GeoPreshower")
-        ATH_MSG_INFO("*Preshower tag: " << pair.second);
+        ATH_MSG_INFO("*Preshower  tag: " << pair.second);
       else if(tagPairName=="GeoTracker")
-        ATH_MSG_INFO("*Tracker tag: " << pair.second);
+        ATH_MSG_INFO("*Tracker  tag: " << pair.second);
       else if(tagPairName=="GeoSCT")
-        ATH_MSG_INFO("*SCT tag: " << pair.second);
+        ATH_MSG_INFO("*SCT        tag: " << pair.second);
       else if(tagPairName=="GeoDipole")
-        ATH_MSG_INFO("*Dipole tag: " << pair.second);
+        ATH_MSG_INFO("*Dipole     tag: " << pair.second);
       else if(tagPairName=="GeoCalo")
-        ATH_MSG_INFO("*Calo    tag: " << pair.second);
+        ATH_MSG_INFO("*Calo     tag: " << pair.second);
       // else if(tagPairName=="GeoMagField")
       //   ATH_MSG_INFO("*MagField  tag: " << pair.second);
       // else if(tagPairName=="GeoCavernInfra")
@@ -566,6 +582,20 @@ StatusCode GeoModelSvc::fillTagInfo() const
     return StatusCode::FAILURE; 
   }
 
+  if(m_NeutrinoVersionOverride != "") {
+    if(m_tagInfoMgr->addTag("GeoNeutrino",m_NeutrinoVersionOverride).isFailure()) {
+      ATH_MSG_ERROR("GeoModelSvc Neutrino tag: " << m_NeutrinoVersionOverride << " not added to TagInfo ");
+      return StatusCode::FAILURE; 
+    }
+  } 
+
+  if(m_EmulsionVersionOverride != "") {
+    if(m_tagInfoMgr->addTag("GeoEmulsion",m_EmulsionVersionOverride).isFailure()) {
+      ATH_MSG_ERROR("GeoModelSvc Emulsion tag: " << m_EmulsionVersionOverride << " not added to TagInfo " );
+      return StatusCode::FAILURE;
+    }
+  }
+
   if(m_ScintVersionOverride != "") {
     if(m_tagInfoMgr->addTag("GeoScint",m_ScintVersionOverride).isFailure()) {
       ATH_MSG_ERROR("GeoModelSvc Scint tag: " << m_ScintVersionOverride << " not added to TagInfo ");
diff --git a/DetectorDescription/GeoModel/GeoModelSvc/src/GeoModelSvc.h b/DetectorDescription/GeoModel/GeoModelSvc/src/GeoModelSvc.h
index 0a78e275..94449b94 100644
--- a/DetectorDescription/GeoModel/GeoModelSvc/src/GeoModelSvc.h
+++ b/DetectorDescription/GeoModel/GeoModelSvc/src/GeoModelSvc.h
@@ -72,6 +72,8 @@ private:
 
     std::string           m_FaserVersion;
 
+    std::string           m_NeutrinoVersionOverride;
+    std::string           m_EmulsionVersionOverride;
     std::string           m_ScintVersionOverride;
     std::string           m_VetoVersionOverride;
     std::string           m_TriggerVersionOverride;
@@ -96,6 +98,8 @@ private:
     bool          m_ignoreTagSupport;             // If true then don't check SUPPORT flag for ATLAS tag
 
     const std::string & faserVersion()             const {return m_FaserVersion; }
+    const std::string & neutrinoVersionOverride()  const {return m_NeutrinoVersionOverride; }
+    const std::string & emulsionVersionOverride()  const {return m_EmulsionVersionOverride; }
     const std::string & scintVersionOverride()     const {return m_ScintVersionOverride; }
     const std::string & vetoVersionOverride()      const {return m_VetoVersionOverride; }
     const std::string & triggerVersionOverride()   const {return m_TriggerVersionOverride  ;}
@@ -107,6 +111,8 @@ private:
     // const std::string & magFieldVersionOverride()     const {return m_MagFieldVersionOverride  ;}
     // const std::string & cavernInfraVersionOverride()  const {return m_CavernInfraVersionOverride  ;}
 
+    const std::string & neutrinoVersion()      const {return m_geoDbTagSvc->neutrinoVersion(); }
+    const std::string & emulsionVersion()      const {return m_geoDbTagSvc->emulsionVersion(); }
     const std::string & scintVersion()         const {return m_geoDbTagSvc->scintVersion(); }
     const std::string & vetoVersion()          const {return m_geoDbTagSvc->vetoVersion(); }
     const std::string & triggerVersion()       const {return m_geoDbTagSvc->triggerVersion(); }
diff --git a/DetectorDescription/GeoModel/GeoModelSvc/src/RDBMaterialManager.cxx b/DetectorDescription/GeoModel/GeoModelSvc/src/RDBMaterialManager.cxx
index 00465e95..3746cfac 100644
--- a/DetectorDescription/GeoModel/GeoModelSvc/src/RDBMaterialManager.cxx
+++ b/DetectorDescription/GeoModel/GeoModelSvc/src/RDBMaterialManager.cxx
@@ -171,6 +171,21 @@ StatusCode RDBMaterialManager::readMaterialsFromDB(ISvcLocator* pSvcLocator)
     m_stdmaterials = iAccessSvc->getRecordsetPtr("StdMaterials","Materials-00","Materials", "FASERDD");
   }
   
+  // --- Neutrino materials
+  DecodeFaserVersionKey keyNeutrino(iGeoModel, "Neutrino");
+  m_neutrinomatcomponents = iAccessSvc->getRecordsetPtr("NeutrinoMatComponents",keyNeutrino.tag(),keyNeutrino.node(),"FASERDD");
+  if(m_neutrinomatcomponents->size()==0) {
+    if(log.level()<=MSG::WARNING)
+      log << MSG::WARNING << " Getting NeutrinoMatComponents with default tag" <<endmsg;
+    m_neutrinomatcomponents = iAccessSvc->getRecordsetPtr("NeutrinoMatComponents","NeutrinoMatComponents-00", "", "FASERDD");
+  }
+  m_neutrinomaterials = iAccessSvc->getRecordsetPtr("NeutrinoMaterials",keyNeutrino.tag(),keyNeutrino.node(), "FASERDD");
+  if(m_neutrinomaterials->size()==0) {
+    if(log.level()<=MSG::WARNING)
+      log << MSG::WARNING << " Getting NeutrinoMaterials with default tag" <<endmsg;
+    m_neutrinomaterials = iAccessSvc->getRecordsetPtr("NeutrinoMaterials","NeutrinoMaterials-00", "", "FASERDD");
+  }
+  
   // --- Scintillator materials
   DecodeFaserVersionKey keyScintillator(iGeoModel, "Scintillator");
   m_scintmatcomponents = iAccessSvc->getRecordsetPtr("ScintMatComponents",keyScintillator.tag(),keyScintillator.node(),"FASERDD");
@@ -413,6 +428,13 @@ GeoMaterial* RDBMaterialManager::getMaterial(const std::string & name) {
       tmp_matcomponents = m_stdmatcomponents;
       data_id = "STDMATERIALS_DATA_ID";
     }
+  else if(name.find("neutrino",0) == 0)
+    {
+      detector = "neutrino";
+      tmp_materials = m_neutrinomaterials;
+      tmp_matcomponents = m_neutrinomatcomponents;
+      data_id = "NEUTRINOMATERIALS_DATA_ID";
+    }
   else if(name.find("scint",0) == 0)
     {
       detector = "scint";
@@ -587,6 +609,13 @@ const GeoMaterial*  RDBMaterialManager:: getMaterial(const std::string &name) co
       tmp_matcomponents = m_stdmatcomponents;
       data_id = "STDMATERIALS_DATA_ID";
     }
+  else if(name.find("neutrino",0) == 0)
+    {
+      detector = "neutrino";
+      tmp_materials = m_neutrinomaterials;
+      tmp_matcomponents = m_neutrinomatcomponents;
+      data_id = "NEUTRINOMATERIALS_DATA_ID";
+    }
   else if(name.find("scint",0) == 0)
     {
       detector = "scint";
diff --git a/DetectorDescription/GeoModel/GeoModelSvc/src/RDBMaterialManager.h b/DetectorDescription/GeoModel/GeoModelSvc/src/RDBMaterialManager.h
index ec34b734..4e64f5dc 100644
--- a/DetectorDescription/GeoModel/GeoModelSvc/src/RDBMaterialManager.h
+++ b/DetectorDescription/GeoModel/GeoModelSvc/src/RDBMaterialManager.h
@@ -83,6 +83,8 @@ class RDBMaterialManager: public StoredMaterialManager {
   
   IRDBRecordset_ptr m_stdmaterials;
   IRDBRecordset_ptr m_stdmatcomponents;
+  IRDBRecordset_ptr m_neutrinomaterials;
+  IRDBRecordset_ptr m_neutrinomatcomponents;
   IRDBRecordset_ptr m_scintmaterials;
   IRDBRecordset_ptr m_scintmatcomponents;
   IRDBRecordset_ptr m_trackermaterials;
diff --git a/DetectorDescription/IdDictDetDescrCnv/src/IdDictDetDescrCnv.cxx b/DetectorDescription/IdDictDetDescrCnv/src/IdDictDetDescrCnv.cxx
index 3dc2b94a..2d3ced32 100644
--- a/DetectorDescription/IdDictDetDescrCnv/src/IdDictDetDescrCnv.cxx
+++ b/DetectorDescription/IdDictDetDescrCnv/src/IdDictDetDescrCnv.cxx
@@ -66,7 +66,7 @@ IdDictDetDescrCnv::initialize()
     }
     
     // Must set indet tag to EMPTY
-    m_scintIDTag = "EMPTY";
+    // m_scintIDTag = "EMPTY";
     
     return StatusCode::SUCCESS; 
 }
@@ -338,16 +338,16 @@ IdDictDetDescrCnv::parseXMLDescription()
         // NOTE: the internal tag for IdDict is global, but is only
         // used for InDet and thus is defined by InDet
         std::string tag;
-        if (m_scintIDTag == "EMPTY") {
-            sc = getTag(tag);
-            if (!sc.isSuccess()) {
-                log << MSG::DEBUG << " no tag found " 
-                    << endmsg;
-                tag = "";  // force empty tag
-            } 
-        } else {
-            tag = m_scintIDTag;
-        }
+        // if (m_scintIDTag == "EMPTY") {
+        //     sc = getTag(tag);
+        //     if (!sc.isSuccess()) {
+        //         log << MSG::DEBUG << " no tag found " 
+        //             << endmsg;
+        //         tag = "";  // force empty tag
+        //     } 
+        // } else {
+        //     tag = m_scintIDTag;
+        // }
 
         log << MSG::DEBUG << "Attempting to parse dictionary " << m_idDictName <<
             " with tag: " << ( tag == "" ? "default" : tag) << endmsg;
@@ -578,6 +578,24 @@ IdDictDetDescrCnv::getFileNamesFromProperties(IProperty* propertyServer)
             << endmsg;
     }
 
+    // Neutrino Ids
+    property = StringProperty("NeutrinoIDFileName", "");
+    sc = propertyServer->getProperty(&property);
+    if (!sc.isSuccess()) {
+        log << MSG::ERROR << "unable to get NeutrinoIDFileName: found " 
+            << property.value()
+            << endmsg;
+        return sc;
+    }
+    else {
+        m_neutrinoIDFileName = property.value();
+        std::string fileName = m_neutrinoIDFileName;
+        if (fileName == "") fileName = "<not given>";
+        log << MSG::DEBUG << "NeutrinoIDFileName:  " 
+            << fileName
+            << endmsg;
+    }
+
     // Scint Ids
     property = StringProperty("ScintIDFileName", "");
     sc = propertyServer->getProperty(&property);
@@ -775,16 +793,44 @@ IdDictDetDescrCnv::getFileNamesFromTags()
     //  inDetCustom = true;
     //} else {
 
+    std::string        dictName;
+    const IRDBRecord*  idDictTable = nullptr;
+
+    // Get Neutrino
+    DecodeFaserVersionKey detectorKey(geoModelSvc, "Neutrino");
+    log << MSG::DEBUG << "From Version Tag: " 
+	<< detectorKey.tag()  << " at Node: " << detectorKey.node() << endmsg;
+    IRDBRecordset_ptr idDictSet   = rdbAccessSvc->getRecordsetPtr("NeutrinoIdentifier",
+								  detectorKey.tag(), 
+								  detectorKey.node(),
+                                  "FASERDD");
+    // Size == 0 if not found
+    if (idDictSet->size()) {
+      idDictTable       = (*idDictSet)[0];
+      dictName          = idDictTable->getString("DICT_NAME");
+      m_neutrinoIDFileName = idDictTable->getString("DICT_FILENAME");
+      // NOTE: the internal tag for IdDict is global, but is
+      // only used for InDet and thus is defined by InDet
+    //   if(!idDictTable->isFieldNull("DICT_TAG")) {
+    //     m_neutrinoIDTag    = idDictTable->getString("DICT_TAG");
+    //   }
+      m_neutrinoIdDictTag  = idDictSet->tagName();
+      log << MSG::DEBUG << " using dictionary:  " << dictName 
+	  << ", file: " <<  m_neutrinoIDFileName  
+	//   << ", with internal tag: " << m_neutrinoIDTag
+	  << ", dictionary tag: " << m_neutrinoIdDictTag
+	  << endmsg;
+    }
+    else log << MSG::WARNING << " no record set found - using default dictionary " << endmsg;
+
     // Get Scint
-    DecodeFaserVersionKey detectorKey(geoModelSvc, "Scintillator");
+    detectorKey = DecodeFaserVersionKey(geoModelSvc, "Scintillator");
     log << MSG::DEBUG << "From Version Tag: " 
 	<< detectorKey.tag()  << " at Node: " << detectorKey.node() << endmsg;
-    IRDBRecordset_ptr idDictSet   = rdbAccessSvc->getRecordsetPtr("ScintIdentifier",
+    idDictSet   = rdbAccessSvc->getRecordsetPtr("ScintIdentifier",
 								  detectorKey.tag(), 
 								  detectorKey.node(),
                                   "FASERDD");
-    std::string        dictName;
-    const IRDBRecord*  idDictTable = 0;
     // Size == 0 if not found
     if (idDictSet->size()) {
       idDictTable       = (*idDictSet)[0];
@@ -792,13 +838,13 @@ IdDictDetDescrCnv::getFileNamesFromTags()
       m_scintIDFileName = idDictTable->getString("DICT_FILENAME");
       // NOTE: the internal tag for IdDict is global, but is
       // only used for InDet and thus is defined by InDet
-      if(!idDictTable->isFieldNull("DICT_TAG")) {
-        m_scintIDTag    = idDictTable->getString("DICT_TAG");
-      }
+    //   if(!idDictTable->isFieldNull("DICT_TAG")) {
+    //     m_scintIDTag    = idDictTable->getString("DICT_TAG");
+    //   }
       m_scintIdDictTag  = idDictSet->tagName();
       log << MSG::DEBUG << " using dictionary:  " << dictName 
 	  << ", file: " <<  m_scintIDFileName  
-	  << ", with internal tag: " << m_scintIDTag
+	//   << ", with internal tag: " << m_scintIDTag
 	  << ", dictionary tag: " << m_scintIdDictTag
 	  << endmsg;
     }
@@ -862,25 +908,31 @@ IdDictDetDescrCnv::registerFilesWithParser()
 
     if ("" != m_faserIDFileName) {
         m_parser->register_external_entity("FASER", m_faserIDFileName);
-        log << MSG::INFO << "Reading FASER            IdDict file "
+        log << MSG::INFO << "Reading FASER         IdDict file "
             << m_faserIDFileName
             << endmsg;
     }
+    if ("" != m_neutrinoIDFileName) {
+        m_parser->register_external_entity("Neutrino", m_neutrinoIDFileName);
+        log << MSG::INFO << "Reading Neutrino      IdDict file "
+            << m_neutrinoIDFileName
+            << endmsg;
+    }
     if ("" != m_scintIDFileName) {
         m_parser->register_external_entity("Scintillator", m_scintIDFileName);
-        log << MSG::INFO << "Reading Scintillator     IdDict file "
+        log << MSG::INFO << "Reading Scintillator  IdDict file "
             << m_scintIDFileName
             << endmsg;
     }
     if ("" != m_trackerIDFileName) {
         m_parser->register_external_entity("Tracker", m_trackerIDFileName);
-        log << MSG::INFO << "Reading Tracker   IdDict file "
+        log << MSG::INFO << "Reading Tracker       IdDict file "
             << m_trackerIDFileName
             << endmsg;
     }
     if ("" != m_caloIDFileName) {
         m_parser->register_external_entity("Calorimeter", m_caloIDFileName);
-        log << MSG::INFO << "Reading Calorimeter  IdDict file "
+        log << MSG::INFO << "Reading Calorimeter   IdDict file "
             << m_caloIDFileName
             << endmsg;
     }
@@ -913,6 +965,21 @@ IdDictDetDescrCnv::registerInfoWithDicts()
             << m_faserIDFileName << " " << m_faserIdDictTag
             << endmsg;
     }
+    if ("" != m_neutrinoIDFileName) {
+        // Find Neutrino:
+        IdDictDictionary* dict = mgr.find_dictionary("Neutrino");  
+        if (!dict) {
+            log << MSG::ERROR 
+                << "unable to find idDict for Neutrino" 
+                << endmsg;
+            return StatusCode::FAILURE;
+        }
+        dict->set_file_name(m_neutrinoIDFileName);
+        dict->set_dict_tag (m_neutrinoIdDictTag);
+        log << MSG::DEBUG << "For Neutrino idDict, setting file/tag: "
+            << m_neutrinoIDFileName << " " << m_neutrinoIdDictTag
+            << endmsg;
+    }
     if ("" != m_scintIDFileName) {
         // Find Scint:
         IdDictDictionary* dict = mgr.find_dictionary("Scintillator");  
diff --git a/DetectorDescription/IdDictDetDescrCnv/src/IdDictDetDescrCnv.h b/DetectorDescription/IdDictDetDescrCnv/src/IdDictDetDescrCnv.h
index 319bbbb7..51585a56 100644
--- a/DetectorDescription/IdDictDetDescrCnv/src/IdDictDetDescrCnv.h
+++ b/DetectorDescription/IdDictDetDescrCnv/src/IdDictDetDescrCnv.h
@@ -100,6 +100,9 @@ private:
     /// File to be read for top-level subsystem ids values
     std::string   m_faserIDFileName;
 
+    /// File to be read for Neutrino ids
+    std::string   m_neutrinoIDFileName;
+
     /// File to be read for Scint ids
     std::string   m_scintIDFileName;
 
@@ -125,6 +128,9 @@ private:
     /// Tag of RDB record for Atlas top-level ids
     std::string   m_faserIdDictTag;
 
+    /// Tag of RDB record for Neutrino ids
+    std::string   m_neutrinoIdDictTag;
+
     /// Tag of RDB record for Scint ids
     std::string   m_scintIdDictTag;
 
@@ -141,7 +147,7 @@ private:
     // std::string   m_forwardIdDictTag;
 
     /// Internal Scint id tag
-    std::string   m_scintIDTag;
+    // std::string   m_scintIDTag;
     
 };
 
diff --git a/Neutrino/NeutrinoDetDescr/NeutrinoIdDictFiles/CMakeLists.txt b/Neutrino/NeutrinoDetDescr/NeutrinoIdDictFiles/CMakeLists.txt
new file mode 100644
index 00000000..2c24a95a
--- /dev/null
+++ b/Neutrino/NeutrinoDetDescr/NeutrinoIdDictFiles/CMakeLists.txt
@@ -0,0 +1,10 @@
+################################################################################
+# Package: NeutrinoIdDictFiles
+################################################################################
+
+# Declare the package name:
+atlas_subdir( NeutrinoIdDictFiles )
+
+# Install files from the package:
+atlas_install_xmls( data/*.xml )
+
diff --git a/Neutrino/NeutrinoDetDescr/NeutrinoIdDictFiles/data/IdDictNeutrino.xml b/Neutrino/NeutrinoDetDescr/NeutrinoIdDictFiles/data/IdDictNeutrino.xml
new file mode 100644
index 00000000..9faa43cf
--- /dev/null
+++ b/Neutrino/NeutrinoDetDescr/NeutrinoIdDictFiles/data/IdDictNeutrino.xml
@@ -0,0 +1,18 @@
+<IdDictionary name="Neutrino">
+
+  <field name="part">
+    <label name="Emulsion" value="1" />
+  </field>
+
+  <field name="side">
+    <label name="Upstream" value="0" />
+    <label name="Downstream" value="1" />
+  </field>
+
+  <region>
+    <range field="part" value="Emulsion" />
+    <range field="film" minvalue="0" maxvalue="999" />
+    <range field="side" values="Upstream Downstream" />
+  </region>
+
+</IdDictionary>
\ No newline at end of file
diff --git a/Scintillator/ScintDetDescr/PreshowerGeoModel/src/PreshowerDetectorFactory.cxx b/Scintillator/ScintDetDescr/PreshowerGeoModel/src/PreshowerDetectorFactory.cxx
index 13c00ff3..02a6c671 100644
--- a/Scintillator/ScintDetDescr/PreshowerGeoModel/src/PreshowerDetectorFactory.cxx
+++ b/Scintillator/ScintDetDescr/PreshowerGeoModel/src/PreshowerDetectorFactory.cxx
@@ -177,7 +177,6 @@ void PreshowerDetectorFactory::create(GeoPhysVol *world)
     GeoVPhysVol* stationA_PV = stationA.build(id);
     GeoAlignableTransform* stationA_Transform = new GeoAlignableTransform(preshowerTransform * preshowerGeneral->partTransform(stationA_Label));
 
-    msg(MSG::INFO) << stationA_Transform->getTransform().translation() << endmsg;
     GeoNameTag* topLevelNameTag = new GeoNameTag("Preshower");
     scint->add(topLevelNameTag);
     scint->add(new GeoIdentifierTag(0));
diff --git a/Scintillator/ScintG4/PreshowerG4_SD/CMakeLists.txt b/Scintillator/ScintG4/PreshowerG4_SD/CMakeLists.txt
index 7b777c99..385164f2 100644
--- a/Scintillator/ScintG4/PreshowerG4_SD/CMakeLists.txt
+++ b/Scintillator/ScintG4/PreshowerG4_SD/CMakeLists.txt
@@ -11,7 +11,7 @@ atlas_depends_on_subdirs( PRIVATE
                           GaudiKernel
                           Scintillator/ScintSimEvent
                           Simulation/G4Atlas/G4AtlasTools
-                          Simulation/G4Sim/MCTruth
+                          Simulation/G4Sim/FaserMCTruth
                            )
 
 # External dependencies:
@@ -24,7 +24,7 @@ atlas_add_component( PreshowerG4_SD
                      src/*.cxx
                      src/components/*.cxx
                      INCLUDE_DIRS ${GEANT4_INCLUDE_DIRS} ${XERCESC_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS}
-                     LINK_LIBRARIES ${GEANT4_LIBRARIES} ${XERCESC_LIBRARIES} ${CLHEP_LIBRARIES} StoreGateLib SGtests GaudiKernel ScintSimEvent G4AtlasToolsLib MCTruth )
+                     LINK_LIBRARIES ${GEANT4_LIBRARIES} ${XERCESC_LIBRARIES} ${CLHEP_LIBRARIES} StoreGateLib SGtests GaudiKernel ScintSimEvent G4AtlasToolsLib FaserMCTruth )
 
 atlas_add_test( PreshowerG4_SDToolConfig_test
                 SCRIPT test/PreshowerG4_SDToolConfig_test.py
diff --git a/Scintillator/ScintG4/PreshowerG4_SD/src/PreshowerSensorSD.cxx b/Scintillator/ScintG4/PreshowerG4_SD/src/PreshowerSensorSD.cxx
index fbfa521a..123f36c6 100644
--- a/Scintillator/ScintG4/PreshowerG4_SD/src/PreshowerSensorSD.cxx
+++ b/Scintillator/ScintG4/PreshowerG4_SD/src/PreshowerSensorSD.cxx
@@ -12,7 +12,7 @@
 #include "PreshowerSensorSD.h"
 
 // athena includes
-#include "MCTruth/TrackHelper.h"
+#include "FaserMCTruth/FaserTrackHelper.h"
 
 // Geant4 includes
 #include "G4Step.hh"
@@ -94,7 +94,7 @@ G4bool PreshowerSensorSD::ProcessHits(G4Step* aStep, G4TouchableHistory* /*ROhis
   int plate = 0;
   this->indexMethod(myTouch, station, plate);
   // get the HepMcParticleLink from the TrackHelper
-  TrackHelper trHelp(aStep->GetTrack());
+  FaserTrackHelper trHelp(aStep->GetTrack());
   m_HitColl->Emplace(lP1,
                      lP2,
                      edep,
diff --git a/Scintillator/ScintG4/TriggerG4_SD/CMakeLists.txt b/Scintillator/ScintG4/TriggerG4_SD/CMakeLists.txt
index 41e528f8..aa07da6a 100644
--- a/Scintillator/ScintG4/TriggerG4_SD/CMakeLists.txt
+++ b/Scintillator/ScintG4/TriggerG4_SD/CMakeLists.txt
@@ -11,7 +11,7 @@ atlas_depends_on_subdirs( PRIVATE
                           GaudiKernel
                           Scintillator/ScintSimEvent
                           Simulation/G4Atlas/G4AtlasTools
-                          Simulation/G4Sim/MCTruth
+                          Simulation/G4Sim/FaserMCTruth
                            )
 
 # External dependencies:
@@ -24,7 +24,7 @@ atlas_add_component( TriggerG4_SD
                      src/*.cxx
                      src/components/*.cxx
                      INCLUDE_DIRS ${GEANT4_INCLUDE_DIRS} ${XERCESC_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS}
-                     LINK_LIBRARIES ${GEANT4_LIBRARIES} ${XERCESC_LIBRARIES} ${CLHEP_LIBRARIES} StoreGateLib SGtests GaudiKernel ScintSimEvent G4AtlasToolsLib MCTruth )
+                     LINK_LIBRARIES ${GEANT4_LIBRARIES} ${XERCESC_LIBRARIES} ${CLHEP_LIBRARIES} StoreGateLib SGtests GaudiKernel ScintSimEvent G4AtlasToolsLib FaserMCTruth )
 
 atlas_add_test( TriggerG4_SDToolConfig_test
                 SCRIPT test/TriggerG4_SDToolConfig_test.py
diff --git a/Scintillator/ScintG4/TriggerG4_SD/src/TriggerSensorSD.cxx b/Scintillator/ScintG4/TriggerG4_SD/src/TriggerSensorSD.cxx
index 516cd37e..fb07226f 100644
--- a/Scintillator/ScintG4/TriggerG4_SD/src/TriggerSensorSD.cxx
+++ b/Scintillator/ScintG4/TriggerG4_SD/src/TriggerSensorSD.cxx
@@ -12,7 +12,7 @@
 #include "TriggerSensorSD.h"
 
 // athena includes
-#include "MCTruth/TrackHelper.h"
+#include "FaserMCTruth/FaserTrackHelper.h"
 
 // Geant4 includes
 #include "G4Step.hh"
@@ -56,6 +56,12 @@ G4bool TriggerSensorSD::ProcessHits(G4Step* aStep, G4TouchableHistory* /*ROhist*
   // Get the Touchable History:
   //
   const G4TouchableHistory *myTouch = dynamic_cast<const G4TouchableHistory*>(aStep->GetPreStepPoint()->GetTouchable());
+  // for (G4int level = 0; level <= myTouch->GetHistoryDepth(); level++)
+  // {
+  //   G4cout << "Trigger hit at level " << level << 
+  //     " in physical volume named " << myTouch->GetVolume(level)->GetName() << 
+  //     " with logical volume name " << myTouch->GetVolume(level)->GetLogicalVolume()->GetName() << G4endl;
+  // }
   //
   // Get the hit coordinates. Start and End Point
   //
@@ -94,7 +100,7 @@ G4bool TriggerSensorSD::ProcessHits(G4Step* aStep, G4TouchableHistory* /*ROhist*
   int plate = 0;
   this->indexMethod(myTouch, station, plate);
   // get the HepMcParticleLink from the TrackHelper
-  TrackHelper trHelp(aStep->GetTrack());
+  FaserTrackHelper trHelp(aStep->GetTrack());
   m_HitColl->Emplace(lP1,
                      lP2,
                      edep,
diff --git a/Scintillator/ScintG4/VetoG4_SD/CMakeLists.txt b/Scintillator/ScintG4/VetoG4_SD/CMakeLists.txt
index 5598c4ea..2338c04e 100644
--- a/Scintillator/ScintG4/VetoG4_SD/CMakeLists.txt
+++ b/Scintillator/ScintG4/VetoG4_SD/CMakeLists.txt
@@ -11,7 +11,7 @@ atlas_depends_on_subdirs( PRIVATE
                           GaudiKernel
                           Scintillator/ScintSimEvent
                           Simulation/G4Atlas/G4AtlasTools
-                          Simulation/G4Sim/MCTruth
+                          Simulation/G4Sim/FaserMCTruth
                            )
 
 # External dependencies:
@@ -24,7 +24,7 @@ atlas_add_component( VetoG4_SD
                      src/*.cxx
                      src/components/*.cxx
                      INCLUDE_DIRS ${GEANT4_INCLUDE_DIRS} ${XERCESC_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS}
-                     LINK_LIBRARIES ${GEANT4_LIBRARIES} ${XERCESC_LIBRARIES} ${CLHEP_LIBRARIES} StoreGateLib SGtests GaudiKernel ScintSimEvent G4AtlasToolsLib MCTruth )
+                     LINK_LIBRARIES ${GEANT4_LIBRARIES} ${XERCESC_LIBRARIES} ${CLHEP_LIBRARIES} StoreGateLib SGtests GaudiKernel ScintSimEvent G4AtlasToolsLib FaserMCTruth )
 
 atlas_add_test( VetoG4_SDToolConfig_test
                 SCRIPT test/VetoG4_SDToolConfig_test.py
diff --git a/Scintillator/ScintG4/VetoG4_SD/src/VetoSensorSD.cxx b/Scintillator/ScintG4/VetoG4_SD/src/VetoSensorSD.cxx
index af5d5287..523cb342 100644
--- a/Scintillator/ScintG4/VetoG4_SD/src/VetoSensorSD.cxx
+++ b/Scintillator/ScintG4/VetoG4_SD/src/VetoSensorSD.cxx
@@ -12,7 +12,7 @@
 #include "VetoSensorSD.h"
 
 // athena includes
-#include "MCTruth/TrackHelper.h"
+#include "FaserMCTruth/FaserTrackHelper.h"
 
 // Geant4 includes
 #include "G4Step.hh"
@@ -94,7 +94,7 @@ G4bool VetoSensorSD::ProcessHits(G4Step* aStep, G4TouchableHistory* /*ROhist*/)
   int plate = 0;
   this->indexMethod(myTouch, station, plate);
   // get the HepMcParticleLink from the TrackHelper
-  TrackHelper trHelp(aStep->GetTrack());
+  FaserTrackHelper trHelp(aStep->GetTrack());
   m_HitColl->Emplace(lP1,
                      lP2,
                      edep,
diff --git a/Simulation/G4Faser/G4FaserAlg/CMakeLists.txt b/Simulation/G4Faser/G4FaserAlg/CMakeLists.txt
index 66f8d8f3..24998f6b 100644
--- a/Simulation/G4Faser/G4FaserAlg/CMakeLists.txt
+++ b/Simulation/G4Faser/G4FaserAlg/CMakeLists.txt
@@ -16,9 +16,10 @@ atlas_depends_on_subdirs( PUBLIC
                           DetectorDescription/GeoModel/GeoModelInterfaces
                           Event/EventInfo
                           Generators/GeneratorObjects
+                          Simulation/G4Atlas/G4AtlasAlg
                           Simulation/G4Atlas/G4AtlasInterfaces
-                          Simulation/G4Sim/MCTruthBase
-                          Simulation/ISF/ISF_Core/ISF_Interfaces
+                          Simulation/G4Sim/FaserMCTruthBase
+                          Simulation/ISF/ISF_Core/FaserISF_Interfaces
                           Simulation/Barcode/BarcodeInterfaces)
 
 # External dependencies:
@@ -30,23 +31,23 @@ find_package( Eigen )
 
 # G4AtlasAlgLib library
 
-#atlas_add_library( G4FaserAlgLib
-#                     src/*.cxx
-#                     PUBLIC_HEADERS G4AtlasAlg
-#                     INCLUDE_DIRS ${GEANT4_INCLUDE_DIRS} ${EIGEN_INCLUDE_DIRS} ${XERCESC_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS}
-# ${HEPMC_INCLUDE_DIRS}
-#                     LINK_LIBRARIES ${GEANT4_LIBRARIES} ${EIGEN_LIBRARIES} ${XERCESC_LIBRARIES} ${CLHEP_LIBRARIES} ${HEPMC_LIBRARIES} AthenaBaseComps AthenaKernel GaudiKernel G4AtlasInterfaces SGTools StoreGateLib SGtests EventInfo GeneratorObjects MCTruthBaseLib )
-#
+atlas_add_library( G4FaserAlgLib
+                     src/*.cxx
+                     NO_PUBLIC_HEADERS
+                     INCLUDE_DIRS ${GEANT4_INCLUDE_DIRS} ${EIGEN_INCLUDE_DIRS} ${XERCESC_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS} ${HEPMC_INCLUDE_DIRS}
+                     LINK_LIBRARIES ${GEANT4_LIBRARIES} ${EIGEN_LIBRARIES} ${XERCESC_LIBRARIES} ${CLHEP_LIBRARIES} ${HEPMC_LIBRARIES} G4AtlasAlgLib AthenaBaseComps AthenaKernel GaudiKernel G4AtlasInterfaces SGTools StoreGateLib SGtests EventInfo GeneratorObjects FaserMCTruthBaseLib )
+
 # Component(s) in the package:
-#atlas_add_component( G4FaserAlg
-#                     src/components/*.cxx
-#                     PUBLIC_HEADERS G4FaserAlg
-#                     INCLUDE_DIRS ${GEANT4_INCLUDE_DIRS} ${EIGEN_INCLUDE_DIRS} ${XERCESC_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS} ${HEPMC_INCLUDE_DIRS}
-#                     LINK_LIBRARIES ${GEANT4_LIBRARIES} ${EIGEN_LIBRARIES} ${XERCESC_LIBRARIES} ${CLHEP_LIBRARIES} ${HEPMC_LIBRARIES} AthenaBaseComps AthenaKernel GaudiKernel G4AtlasInterfaces G4FaserAlgLib SGTools StoreGateLib SGtests EventInfo GeneratorObjects MCTruthBaseLib )
-
-#atlas_add_test( G4FaserAlgConfig_Test
-#                SCRIPT test/runG4.py
-#                PROPERTIES TIMEOUT 300 )
+atlas_add_component( G4FaserAlg
+                     src/components/*.cxx
+                     NO_PUBLIC_HEADERS
+                     INCLUDE_DIRS ${GEANT4_INCLUDE_DIRS} ${EIGEN_INCLUDE_DIRS} ${XERCESC_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS} ${HEPMC_INCLUDE_DIRS}
+                     LINK_LIBRARIES ${GEANT4_LIBRARIES} ${EIGEN_LIBRARIES} ${XERCESC_LIBRARIES} ${CLHEP_LIBRARIES} ${HEPMC_LIBRARIES} AthenaBaseComps AthenaKernel GaudiKernel G4AtlasInterfaces G4FaserAlgLib G4AtlasAlgLib SGTools StoreGateLib SGtests EventInfo GeneratorObjects FaserMCTruthBaseLib )
+
+atlas_add_test( G4FaserAlgConfig_Test
+                SCRIPT test/runG4.py
+                PROPERTIES TIMEOUT 300 
+                PROPERTIES WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
 
 # Install files from the package:
 atlas_install_python_modules( python/*.py )
diff --git a/Simulation/G4Faser/G4FaserAlg/python/G4FaserAlgConfigNew.py b/Simulation/G4Faser/G4FaserAlg/python/G4FaserAlgConfigNew.py
index f69c2a83..56b16258 100644
--- a/Simulation/G4Faser/G4FaserAlg/python/G4FaserAlgConfigNew.py
+++ b/Simulation/G4Faser/G4FaserAlg/python/G4FaserAlgConfigNew.py
@@ -6,23 +6,16 @@ from AthenaCommon.AppMgr import *
 #
 #  Manager classes for detector geometry and sensitive detectors
 #
-from G4FaserServices.G4FaserServicesConfigNew import DetectorGeometrySvcCfg, FaserGeoIDSvcCfg
-from G4FaserTools.G4FaserToolsConfig import getSensitiveDetectorMasterTool
+from G4FaserServices.G4FaserServicesConfigNew import DetectorGeometrySvcCfg
+from G4FaserTools.G4FaserToolsConfigNew import SensitiveDetectorMasterToolCfg
+from G4FaserServices.G4FaserUserActionConfigNew import UserActionSvcCfg
+# from G4AtlasApps.G4Atlas_MetadataNew import writeSimulationParametersMetadata
 #
 #  Framework utilities
 #
-from ISF_Services.ISF_ServicesConfigNew import MC15aPlusTruthServiceCfg, InputConverterCfg
+from FaserISF_Services.FaserISF_ServicesConfigNew import FaserTruthServiceCfg, FaserGeoIDSvcCfg, FaserInputConverterCfg
 #
-#  The GeoIDSvcCfg call is a disaster, bringing in tons of ATLAS-specific
-#  stuff that would have to be rewritten; instead, we define FASER as being
-#  unconditionally in the "undefined" ATLAS region; this may eventually limit
-#  the granularity of truth strategies we can use
-#
-#from ISF_Services.ISF_ServicesConfigNew import GeoIDSvcCfg
-#
-from  G4AtlasAlg.G4AtlasAlgConf import G4AtlasAlg
-
-#to still migrate: getAthenaStackingActionTool, getAthenaTrackingActionTool
+from  G4FaserAlg.G4FaserAlgConf import G4FaserAlg
 
 def G4FaserAlgCfg(ConfigFlags, name='G4FaserAlg', **kwargs):
     #
@@ -43,7 +36,7 @@ def G4FaserAlgCfg(ConfigFlags, name='G4FaserAlg', **kwargs):
     #
     #  Record the particle flux during the simulation
     #
-    # if ConfigFlags.Sim.RecordFlux:
+    #if ConfigFlags.Sim.RecordFlux:
     kwargs.setdefault('RecordFlux' , ConfigFlags.Sim.RecordFlux)
     #
     #  Treatment of bad events
@@ -67,32 +60,38 @@ def G4FaserAlgCfg(ConfigFlags, name='G4FaserAlg', **kwargs):
 
     kwargs.setdefault("RandomGenerator", "athena")
     #
-    #  Multi-threading settinggs
+    #  Multi-threading settings
     #
     is_hive = ConfigFlags.Concurrency.NumThreads > 1
     kwargs.setdefault('MultiThreading', is_hive)
     #
     #  What truth information to save?
     #
-    accMCTruth = MC15aPlusTruthServiceCfg(ConfigFlags)
+    accMCTruth = FaserTruthServiceCfg(ConfigFlags)
     result.merge(accMCTruth)
-    kwargs.setdefault('TruthRecordService', result.getService("ISF_MC15aPlusTruthService"))
+    kwargs.setdefault('TruthRecordService', result.getService("FaserISF_TruthService"))
     #kwargs.setdefault('TruthRecordService', ConfigFlags.Sim.TruthStrategy) # TODO need to have manual override (simFlags.TruthStrategy.TruthServiceName())
     #
-    #  Run-time geometry navigation for truth filtering - the ISF service is incompatible with FASER
-    #
-    # accGeoID = GeoIDSvcCfg(ConfigFlags)
-    # result.merge(accGeoID)
-    # kwargs.setdefault('GeoIDSvc', result.getService('ISF_GeoIDSvc'))
-    accGeoID = FaserGeoIDSvcCfg(ConfigFlags)
-    result.merge(accGeoID)
-    kwargs.setdefault('GeoIDSvc', result.getService('ISF_FaserGeoIDSvc'))
-    #
     #  Converts generator particles to a proprietary type managed by ISF
     #
-    accInputConverter = InputConverterCfg(ConfigFlags)
+    accInputConverter = FaserInputConverterCfg(ConfigFlags)
     result.merge(accInputConverter)
-    kwargs.setdefault('InputConverter', result.getService("ISF_InputConverter"))
+    kwargs.setdefault('InputConverter', result.getService("ISF_FaserInputConverter"))
+    #
+    # Sensitive detector master tool
+    #
+    accSensitiveDetector = SensitiveDetectorMasterToolCfg(ConfigFlags)
+    result.merge(accSensitiveDetector)
+    kwargs.setdefault('SenDetMasterTool', result.getPublicTool("SensitiveDetectorMasterTool")) #NOTE - is still a public tool
+    #
+    #Write MetaData container
+    #
+    #result.merge(writeSimulationParametersMetadata(ConfigFlags))
+    #
+    #User action services (Slow...)
+    #
+    result.merge( UserActionSvcCfg(ConfigFlags) )
+    kwargs.setdefault('UserActionSvc', result.getService( "G4UA::UserActionSvc") )
     #
     #  Output level
     #
@@ -106,66 +105,10 @@ def G4FaserAlgCfg(ConfigFlags, name='G4FaserAlg', **kwargs):
     #    print verbosities
     kwargs.setdefault('Verbosities', verbosities)
     #
-    # Set commands for the G4AtlasAlg
+    # Set commands for the G4FaserAlg
     #
     kwargs.setdefault("G4Commands", ConfigFlags.Sim.G4Commands)
-    #
-    # Default to using all known sensitive detectors
-    #
-    # result.addPublicTool(getSensitiveDetectorMasterTool())
-    # kwargs.setdefault("SenDetMasterTool", result.getPublicTool("SensitiveDetectorMasterTool"))
 
-    result.addEventAlgo(G4AtlasAlg(name, **kwargs))
+    result.addEventAlgo(G4FaserAlg(name, **kwargs))
     return result
 
-if __name__ == '__main__':
-  from AthenaConfiguration.MainServicesConfig import MainServicesSerialCfg
-  import os
-
-  # Set up logging and config behaviour
-  from AthenaCommon.Logging import log
-  from AthenaCommon.Constants import DEBUG
-  from AthenaCommon.Configurable import Configurable
-  log.setLevel(DEBUG)
-  Configurable.configurableRun3Behavior = 1
-
-
-  #import config flags
-  from AthenaConfiguration.AllConfigFlags import ConfigFlags
-  
-  from AthenaConfiguration.TestDefaults import defaultTestFiles
-  inputDir = defaultTestFiles.d
-  ConfigFlags.Input.Files = defaultTestFiles.EVNT
-
-  ConfigFlags.Sim.WorldRRange = 15000
-  ConfigFlags.Sim.WorldZRange = 27000 #change defaults?
-  ConfigFlags.Detector.SimulateForward = False
-  # Finalize 
-  ConfigFlags.lock()
-
-  ## Initialize a new component accumulator
-  cfg = MainServicesSerialCfg()
-
-  #add the algorithm
-  cfg.merge(G4FaserAlgCfg(ConfigFlags))
-
-  # Dump config
-  cfg.getService("StoreGateSvc").Dump = True
-  cfg.getService("ConditionStore").Dump = True
-  cfg.printConfig(withDetails=True, summariseProps = True)
-  ConfigFlags.dump()
-
-
-  # Execute and finish
-  sc = cfg.run(maxEvents=3)
-  # Success should be 0
-  os.sys.exit(not sc.isSuccess())
-
-  #f=open("test.pkl","w")
-  #cfg.store(f) 
-  #f.close()
-
-
-
-  print(cfg._publicTools)
-  print("-----------------finished----------------------")
diff --git a/Simulation/G4Faser/G4FaserAlg/src/G4FaserAlg.cxx b/Simulation/G4Faser/G4FaserAlg/src/G4FaserAlg.cxx
new file mode 100644
index 00000000..448aa3a7
--- /dev/null
+++ b/Simulation/G4Faser/G4FaserAlg/src/G4FaserAlg.cxx
@@ -0,0 +1,433 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+// Local includes
+#include "G4FaserAlg.h"
+#include "G4FaserFluxRecorder.h"
+
+#include "AthenaKernel/RNGWrapper.h"
+
+// Can we safely include all of these?
+#include "G4AtlasAlg/G4AtlasMTRunManager.h"
+#include "G4AtlasAlg/G4AtlasWorkerRunManager.h"
+#include "G4AtlasAlg/G4AtlasUserWorkerThreadInitialization.h"
+#include "G4AtlasAlg/G4AtlasRunManager.h"
+
+// Geant4 includes
+#include "G4StateManager.hh"
+#include "G4TransportationManager.hh"
+#include "G4RunManagerKernel.hh"
+#include "G4EventManager.hh"
+#include "G4Navigator.hh"
+#include "G4PropagatorInField.hh"
+#include "G4TrackingManager.hh"
+#include "G4StackManager.hh"
+#include "G4UImanager.hh"
+#include "G4ScoringManager.hh"
+#include "G4VUserPhysicsList.hh"
+#include "G4VModularPhysicsList.hh"
+#include "G4ParallelWorldPhysics.hh"
+
+// CLHEP includes
+#include "CLHEP/Random/RandomEngine.h"
+
+// Athena includes
+#include "StoreGate/ReadHandle.h"
+#include "StoreGate/WriteHandle.h"
+#include "EventInfo/EventInfo.h"
+#include "FaserMCTruthBase/FaserTruthStrategyManager.h"
+#include "GeoModelInterfaces/IGeoModelSvc.h"
+#include "GaudiKernel/IThreadInitTool.h"
+#include "GeneratorObjects/HepMcParticleLink.h"
+
+// call_once mutexes
+#include <mutex>
+static std::once_flag initializeOnceFlag;
+static std::once_flag finalizeOnceFlag;
+static std::once_flag releaseGeoModelOnceFlag;
+
+/////////////////////////////////////////////////////////////////////////////
+
+
+G4FaserAlg::G4FaserAlg(const std::string& name, ISvcLocator* pSvcLocator)
+  : AthAlgorithm(name, pSvcLocator)
+{
+  // Verbosities
+  declareProperty("Verbosities", m_verbosities);
+}
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+
+StatusCode G4FaserAlg::initialize()
+{
+  ATH_MSG_DEBUG("Start of initialize()");
+
+  // Create the scoring manager if requested
+  if (m_recordFlux) G4ScoringManager::GetScoringManager();
+
+  // One-time initialization
+  try {
+    std::call_once(initializeOnceFlag, &G4FaserAlg::initializeOnce, this);
+  }
+  catch(const std::exception& e) {
+    ATH_MSG_ERROR("Failure in G4FaserAlg::initializeOnce: " << e.what());
+    return StatusCode::FAILURE;
+  }
+
+  ATH_CHECK( m_rndmGenSvc.retrieve() );
+  ATH_CHECK( m_userActionSvc.retrieve() );
+
+  ATH_CHECK(m_senDetTool.retrieve());
+  ATH_CHECK(m_fastSimTool.retrieve());
+
+  // Truth
+  ATH_CHECK( m_truthRecordSvc.retrieve() );
+  ATH_MSG_INFO( "- Using ISF TruthRecordSvc : " << m_truthRecordSvc.typeAndName() );
+
+  FaserTruthStrategyManager* sManager = FaserTruthStrategyManager::GetStrategyManager();
+  sManager->SetISFTruthSvc( &(*m_truthRecordSvc) );
+
+  // I/O
+  ATH_CHECK( m_inputTruthCollectionKey.initialize());
+  ATH_CHECK( m_outputTruthCollectionKey.initialize());
+
+  ATH_CHECK(m_inputConverter.retrieve());
+
+  ATH_MSG_DEBUG("End of initialize()");
+  return StatusCode::SUCCESS;
+}
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+void G4FaserAlg::initializeOnce()
+{
+  // Assign physics list
+  if(m_physListSvc.retrieve().isFailure()) {
+    throw std::runtime_error("Could not initialize ATLAS PhysicsListSvc!");
+  }
+
+  // Create the (master) run manager
+  if(m_useMT) {
+#ifdef G4MULTITHREADED
+    auto* runMgr = G4AtlasMTRunManager::GetG4AtlasMTRunManager();
+    m_physListSvc->SetPhysicsList();
+    runMgr->SetDetGeoSvc( m_detGeoSvc.typeAndName() );
+    runMgr->SetFastSimMasterTool(m_fastSimTool.typeAndName() );
+    runMgr->SetPhysListSvc( m_physListSvc.typeAndName() );
+    // Worker Thread initialization used to create worker run manager on demand.
+    std::unique_ptr<G4AtlasUserWorkerThreadInitialization> workerInit =
+      std::make_unique<G4AtlasUserWorkerThreadInitialization>();
+    workerInit->SetUserActionSvc( m_userActionSvc.typeAndName() );
+    workerInit->SetDetGeoSvc( m_detGeoSvc.typeAndName() );
+    workerInit->SetSDMasterTool( m_senDetTool.typeAndName() );
+    workerInit->SetFastSimMasterTool( m_fastSimTool.typeAndName() );
+    runMgr->SetUserInitialization( workerInit.release() );
+#else
+    throw std::runtime_error("Trying to use multi-threading in non-MT build!");
+#endif
+  }
+  // Single-threaded run manager
+  else {
+    auto* runMgr = G4AtlasRunManager::GetG4AtlasRunManager();
+    m_physListSvc->SetPhysicsList();
+    runMgr->SetRecordFlux( m_recordFlux, std::make_unique<G4FaserFluxRecorder>() );
+    runMgr->SetLogLevel( int(msg().level()) ); // Synch log levels
+    runMgr->SetUserActionSvc( m_userActionSvc.typeAndName() );
+    runMgr->SetDetGeoSvc( m_detGeoSvc.typeAndName() );
+    runMgr->SetSDMasterTool(m_senDetTool.typeAndName() );
+    runMgr->SetFastSimMasterTool(m_fastSimTool.typeAndName() );
+    runMgr->SetPhysListSvc(m_physListSvc.typeAndName() );
+  }
+
+  // G4 user interface commands
+  G4UImanager *ui = G4UImanager::GetUIpointer();
+
+  // Load custom libraries
+  if (!m_libList.empty()) {
+    ATH_MSG_INFO("G4FaserAlg specific libraries requested ");
+    std::string temp="/load "+m_libList;
+    ui->ApplyCommand(temp);
+  }
+  // Load custom physics
+  if (!m_physList.empty()) {
+    ATH_MSG_INFO("requesting a specific physics list "<< m_physList);
+    std::string temp="/Physics/GetPhysicsList "+m_physList;
+    ui->ApplyCommand(temp);
+  }
+  // Load custom magnetic field
+  if (!m_fieldMap.empty()) {
+    ATH_MSG_INFO("requesting a specific field map "<< m_fieldMap);
+    ATH_MSG_INFO("the field is initialized straight away");
+    std::string temp="/MagneticField/Select "+m_fieldMap;
+    ui->ApplyCommand(temp);
+    ui->ApplyCommand("/MagneticField/Initialize");
+  }
+
+  // Send UI commands
+  ATH_MSG_DEBUG("G4 Command: Trying at the end of initializeOnce()");
+  for (auto g4command : m_g4commands) {
+    int returnCode = ui->ApplyCommand( g4command );
+    commandLog(returnCode, g4command);
+  }
+
+  // Code from G4AtlasSvc
+  auto* rm = G4RunManager::GetRunManager();
+  if(!rm) {
+    throw std::runtime_error("Run manager retrieval has failed");
+  }
+  rm->Initialize();     // Initialization differs slightly in multi-threading.
+  // TODO: add more details about why this is here.
+  if(!m_useMT && rm->ConfirmBeamOnCondition()) {
+    rm->RunInitialization();
+  }
+
+  ATH_MSG_INFO( "retireving the Detector Geometry Service" );
+  if(m_detGeoSvc.retrieve().isFailure()) {
+    throw std::runtime_error("Could not initialize ATLAS DetectorGeometrySvc!");
+  }
+
+  if(m_userLimitsSvc.retrieve().isFailure()) {
+    throw std::runtime_error("Could not initialize ATLAS UserLimitsSvc!");
+  }
+
+  if (m_activateParallelGeometries) {
+    G4VModularPhysicsList* thePhysicsList=dynamic_cast<G4VModularPhysicsList*>(m_physListSvc->GetPhysicsList());
+    if (!thePhysicsList) {
+      throw std::runtime_error("Failed dynamic_cast!! this is not a G4VModularPhysicsList!");
+    }
+#if G4VERSION_NUMBER >= 1010
+    std::vector<std::string>& parallelWorldNames=m_detGeoSvc->GetParallelWorldNames();
+    for (auto& it: parallelWorldNames) {
+      thePhysicsList->RegisterPhysics(new G4ParallelWorldPhysics(it,true));
+    }
+#endif
+  }
+
+  return;
+}
+
+void G4FaserAlg::initializeG4()
+{
+  if (m_verbosities.size()>0) {
+    G4TransportationManager *tm = G4TransportationManager::GetTransportationManager();
+    G4RunManagerKernel *rmk = G4RunManagerKernel::GetRunManagerKernel();
+    G4EventManager *em = G4EventManager::GetEventManager();
+
+    auto itr = m_verbosities.end();
+    if ((itr = m_verbosities.find("Navigator")) != m_verbosities.end()) {
+      tm->GetNavigatorForTracking()->SetVerboseLevel( atof(itr->second.data()) );
+    }
+    if ((itr = m_verbosities.find("Propagator")) != m_verbosities.end()) {
+      tm->GetPropagatorInField()->SetVerboseLevel( atof(itr->second.data()) );
+    }
+    if ((itr = m_verbosities.find("Tracking")) != m_verbosities.end()) {
+      rmk->GetTrackingManager()->SetVerboseLevel( atof(itr->second.data()) );
+    }
+    if ((itr = m_verbosities.find("Stepping")) != m_verbosities.end()) {
+      rmk->GetTrackingManager()->GetSteppingManager()->
+        SetVerboseLevel( atof(itr->second.data()) );
+    }
+    if ((itr = m_verbosities.find("Stacking")) != m_verbosities.end()) {
+      rmk->GetStackManager()->SetVerboseLevel( atof(itr->second.data()) );
+    }
+    if ((itr = m_verbosities.find("Event")) != m_verbosities.end()) {
+      em->SetVerboseLevel( atof(itr->second.data()) );
+    }
+  } // End of the setting of verbosities
+
+}
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+
+StatusCode G4FaserAlg::finalize()
+{
+  ATH_MSG_DEBUG(std::endl<<std::endl<<std::endl);
+  ATH_MSG_INFO("++++++++++++  G4FaserAlg finalized  ++++++++++++" <<std::endl<<std::endl);
+
+  // One time finalization
+  try {
+    std::call_once(finalizeOnceFlag, &G4FaserAlg::finalizeOnce, this);
+  }
+  catch(const std::exception& e) {
+    ATH_MSG_ERROR("Failure in G4FaserAlg::finalizeOnce: " << e.what());
+    return StatusCode::FAILURE;
+  }
+
+  return StatusCode::SUCCESS;
+}
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+void G4FaserAlg::finalizeOnce()
+{
+  ATH_MSG_DEBUG("\t terminating the current G4 run");
+  auto runMgr = G4RunManager::GetRunManager();
+  runMgr->RunTermination();
+}
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+
+StatusCode G4FaserAlg::execute()
+{
+  static int n_Event=0;
+  ATH_MSG_DEBUG("++++++++++++  G4FaserAlg execute  ++++++++++++");
+
+#ifdef G4MULTITHREADED
+  // In some rare cases, TBB may create more physical worker threads than
+  // were requested via the pool size.  This can happen at any time.
+  // In that case, those extra threads will not have had the thread-local
+  // initialization done, leading to a crash.  Try to detect that and do
+  // the initialization now if needed.
+  if (G4TransportationManager::GetTransportationManager()->GetNavigatorForTracking()->GetWorldVolume() == nullptr)
+  {
+    ToolHandle<IThreadInitTool> ti ("G4ThreadInitTool", nullptr);
+    ATH_CHECK( ti.retrieve() );
+    ti->initThread();
+  }
+#endif
+
+  n_Event += 1;
+
+  if (n_Event<=10 || (n_Event%100) == 0) {
+    ATH_MSG_ALWAYS("G4FaserAlg: Event num. "  << n_Event << " start processing");
+  }
+
+  // tell TruthService we're starting a new event
+  ATH_CHECK( m_truthRecordSvc->initializeTruthCollection() );
+
+  // Release GeoModel Geometry if necessary
+  if (m_releaseGeoModel) {
+    try {
+      std::call_once(releaseGeoModelOnceFlag, &G4FaserAlg::releaseGeoModel, this);
+    }
+    catch(const std::exception& e) {
+      ATH_MSG_ERROR("Failure in G4FaserAlg::releaseGeoModel: " << e.what());
+      return StatusCode::FAILURE;
+    }
+  }
+
+  // Set the RNG to use for this event. We need to reset it for MT jobs
+  // because of the mismatch between Gaudi slot-local and G4 thread-local RNG.
+  ATHRNG::RNGWrapper* rngWrapper = m_rndmGenSvc->getEngine(this);
+  rngWrapper->setSeed( name(), Gaudi::Hive::currentContext() );
+  G4Random::setTheEngine(*rngWrapper);
+
+  ATH_MSG_DEBUG("Calling SimulateG4Event");
+
+  ATH_CHECK(m_senDetTool->BeginOfAthenaEvent());
+
+  SG::ReadHandle<McEventCollection> inputTruthCollection(m_inputTruthCollectionKey);
+  if (!inputTruthCollection.isValid()) {
+    ATH_MSG_FATAL("Unable to read input GenEvent collection " << inputTruthCollection.name() << " in store " << inputTruthCollection.store());
+    return StatusCode::FAILURE;
+  }
+  ATH_MSG_DEBUG("Found input GenEvent collection " << inputTruthCollection.name() << " in store " << inputTruthCollection.store());
+  // create copy
+  SG::WriteHandle<McEventCollection> outputTruthCollection(m_outputTruthCollectionKey);
+  ATH_CHECK(outputTruthCollection.record(std::make_unique<McEventCollection>(*inputTruthCollection)));
+  if (!outputTruthCollection.isValid()) {
+    ATH_MSG_FATAL("Unable to record output GenEvent collection " << outputTruthCollection.name() << " in store " << outputTruthCollection.store());
+    return StatusCode::FAILURE;
+
+  }
+  ATH_MSG_DEBUG("Recorded output GenEvent collection " << outputTruthCollection.name() << " in store " << outputTruthCollection.store());
+  G4Event *inputEvent{};
+  ATH_CHECK( m_inputConverter->convertHepMCToG4Event(*outputTruthCollection, inputEvent, HepMcParticleLink::find_enumFromKey(outputTruthCollection.name())) );
+
+  bool abort = false;
+  // Worker run manager
+  // Custom class has custom method call: ProcessEvent.
+  // So, grab custom singleton class directly, rather than base.
+  // Maybe that should be changed! Then we can use a base pointer.
+  if(m_useMT) {
+#ifdef G4MULTITHREADED
+    auto* workerRM = G4AtlasWorkerRunManager::GetG4AtlasWorkerRunManager();
+    abort = workerRM->ProcessEvent(inputEvent);
+#else
+    ATH_MSG_ERROR("Trying to use multi-threading in non-MT build!");
+    return StatusCode::FAILURE;
+#endif
+  }
+  else {
+    auto* workerRM = G4AtlasRunManager::GetG4AtlasRunManager();
+    abort = workerRM->ProcessEvent(inputEvent);
+  }
+  if (abort) {
+    ATH_MSG_WARNING("Event was aborted !! ");
+    ATH_MSG_WARNING("Simulation will now go on to the next event ");
+    if (m_killAbortedEvents) {
+      ATH_MSG_WARNING("setFilterPassed is now False");
+      setFilterPassed(false);
+    }
+    if (m_flagAbortedEvents) {
+      // FIXME This code is updating an object which is already in
+      // StoreGate, which is not really allowed. The long term
+      // solution is to switch Simulation to use xAOD::EventInfo, then
+      // use an SG::WriteDecorHandle (when available) to set the error
+      // state.
+      const DataHandle<EventInfo> eic = 0;
+      if ( sgSvc()->retrieve( eic ).isFailure() || !eic ) {
+        ATH_MSG_WARNING( "Failed to retrieve EventInfo" );
+      }
+      else {
+        // Gotta cast away the const... sadface
+        EventInfo *ei = const_cast< EventInfo * > (&(*eic));
+        ei->setErrorState(EventInfo::Core,EventInfo::Error);
+        ATH_MSG_WARNING( "Set error state in event info!" );
+      }
+    }
+  }
+
+  // Register all of the collections if there are any new-style SDs
+  ATH_CHECK(m_senDetTool->EndOfAthenaEvent());
+  ATH_CHECK(m_fastSimTool->EndOfAthenaEvent());
+
+  for (size_t iEvt = 0; iEvt < outputTruthCollection->size(); ++iEvt)
+  {
+    outputTruthCollection->at(iEvt)->print(msg(MSG::DEBUG).stream());
+  }
+
+  ATH_CHECK( m_truthRecordSvc->releaseEvent() );
+
+  return StatusCode::SUCCESS;
+}
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+
+void G4FaserAlg::releaseGeoModel()
+{
+  ISvcLocator *svcLocator = Gaudi::svcLocator(); // from Bootstrap
+  IGeoModelSvc *geoModel(nullptr);
+  if(svcLocator->service("GeoModelSvc",geoModel).isFailure()) {
+    ATH_MSG_WARNING( " ----> Unable to retrieve GeoModelSvc" );
+  }
+  else {
+    if(geoModel->clear().isFailure()) {
+      ATH_MSG_WARNING( " ----> GeoModelSvc::clear() failed" );
+    }
+    else {
+      ATH_MSG_INFO( " ----> GeoModelSvc::clear() succeeded " );
+    }
+  }
+  m_releaseGeoModel=false; // Don't do that again...
+  return;
+}
+
+void G4FaserAlg::commandLog(int returnCode, const std::string& commandString) const
+{
+  switch(returnCode) {
+  case 0: { ATH_MSG_DEBUG("G4 Command: " << commandString << " - Command Succeeded"); } break;
+  case 100: { ATH_MSG_ERROR("G4 Command: " << commandString << " - Command Not Found!"); } break;
+  case 200: {
+    auto* stateManager = G4StateManager::GetStateManager();
+    ATH_MSG_DEBUG("G4 Command: " << commandString << " - Illegal Application State (" <<
+                    stateManager->GetStateString(stateManager->GetCurrentState()) << ")!");
+  } break;
+  case 300: { ATH_MSG_ERROR("G4 Command: " << commandString << " - Parameter Out of Range!"); } break;
+  case 400: { ATH_MSG_ERROR("G4 Command: " << commandString << " - Parameter Unreadable!"); } break;
+  case 500: { ATH_MSG_ERROR("G4 Command: " << commandString << " - Parameter Out of Candidates!"); } break;
+  case 600: { ATH_MSG_ERROR("G4 Command: " << commandString << " - Alias Not Found!"); } break;
+  default: { ATH_MSG_ERROR("G4 Command: " << commandString << " - Unknown Status!"); } break;
+  }
+
+}
diff --git a/Simulation/G4Faser/G4FaserAlg/src/G4FaserAlg.h b/Simulation/G4Faser/G4FaserAlg/src/G4FaserAlg.h
new file mode 100644
index 00000000..cf18bac1
--- /dev/null
+++ b/Simulation/G4Faser/G4FaserAlg/src/G4FaserAlg.h
@@ -0,0 +1,140 @@
+/*
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef G4FASERALG_G4FaserAlg_H
+#define G4FASERALG_G4FaserAlg_H
+
+// Base class header
+#include "AthenaBaseComps/AthAlgorithm.h"
+
+// STL headers
+#include <map>
+#include <string>
+
+// Gaudi headers
+#include "GaudiKernel/ServiceHandle.h"
+#include "GaudiKernel/ToolHandle.h"
+
+// Athena headers
+#include "StoreGate/ReadHandleKey.h"
+#include "StoreGate/WriteHandleKey.h"
+#include "AthenaKernel/IAthRNGSvc.h"
+#include "G4AtlasInterfaces/IUserActionSvc.h"
+#include "G4AtlasInterfaces/IDetectorGeometrySvc.h"
+#include "G4AtlasInterfaces/ISensitiveDetectorMasterTool.h"
+#include "G4AtlasInterfaces/IFastSimulationMasterTool.h"
+#include "G4AtlasInterfaces/IPhysicsListSvc.h"
+#include "G4AtlasInterfaces/IUserLimitsSvc.h"
+#include "GeneratorObjects/McEventCollection.h"
+
+// ISF includes
+#include "FaserISF_Interfaces/IFaserTruthSvc.h"
+#include "FaserISF_Interfaces/IFaserInputConverter.h"
+
+/// @class G4FaserAlg
+/// @brief Primary Calypso algorithm for FASER simulation.
+///
+/// During initialization, this class sets up several things, including:
+/// - the FASER (master) run manager
+/// - physics list assignment to G4
+/// - detector construction (currently FADS::FadsDetectorConstruction)
+///
+/// During the event loop, it handles processing of the event by
+/// invoking the (worker) run manager.
+///
+class G4FaserAlg : public AthAlgorithm
+{
+
+public:
+
+  /// Standard algorithm constructor
+  G4FaserAlg(const std::string& name, ISvcLocator* pSvcLocator);
+
+  /// Virtual destructor
+  virtual ~G4FaserAlg() {  };
+
+  /// this Alg is Clonable (for AthenaMT)
+  bool isClonable() const override { return true; }
+
+  /// @brief Initialize the algorithm.
+  ///
+  /// Here we setup several things for simulation, including:
+  /// - force intialization of the UserActionSvc
+  /// - apply custom G4 UI commands (like custom physics list)
+  /// - configure the particle generator and random generator svc
+  StatusCode initialize() override;
+
+  /// Finalize the algorithm and invoke G4 run termination.
+  StatusCode finalize() override;
+
+  /// @brief Simulate one Athena event.
+  StatusCode execute() override;
+
+  /// Poorly named possibly unused method which sets some verbosities.
+  void initializeG4();
+
+  /// G4 initialization called only by the first alg instance.
+  /// This is done (for now) because we get multiple alg instances in hive.
+  void initializeOnce();
+
+  /// G4 finalization called only by the first alg instance.
+  /// This is done (for now) because we get multiple alg instances in hive.
+  void finalizeOnce();
+
+private:
+
+  /// This command prints a message about a G4Command depending on its returnCode
+  void commandLog(int returnCode, const std::string& commandString) const;
+
+  /// Releases the GeoModel geometry from memory once it has been used
+  /// to build the G4 geometry and is no-longer required
+  void releaseGeoModel();
+
+  /// @name Configurable Properties
+  /// @{
+  Gaudi::Property<bool> m_killAbortedEvents{this, "KillAbortedEvents", false, ""};
+  Gaudi::Property<bool> m_flagAbortedEvents{this, "FlagAbortedEvents", false, ""};
+  SG::ReadHandleKey<McEventCollection>    m_inputTruthCollectionKey{this, "InputTruthCollection", "BeamTruthEvent", "Input hard scatter collection"}; //!< input hard scatter collection
+  SG::WriteHandleKey<McEventCollection>   m_outputTruthCollectionKey{this, "OutputTruthCollection", "TruthEvent", "Output hard scatter truth collection"};//!< output hard scatter truth collection
+  /// Central Truth Service
+  ServiceHandle<ISF::IFaserTruthSvc> m_truthRecordSvc{this, "TruthRecordService", "ISF_FaserTruthRecordSvc", ""};
+
+  /// Verbosity settings for Geant4
+  std::map<std::string,std::string> m_verbosities;
+  /// @}
+
+  /// @name Configurable Properties (common with TransportTool)
+  /// @{
+  Gaudi::Property<std::string> m_libList{this, "Dll", "", ""};
+  Gaudi::Property<std::string> m_physList{this, "Physics", "", ""};
+  Gaudi::Property<std::string> m_fieldMap{this, "FieldMap", "", ""};
+  Gaudi::Property<std::string> m_rndmGen{this, "RandomGenerator", "athena", ""};
+  Gaudi::Property<bool> m_releaseGeoModel{this, "ReleaseGeoModel", true, ""};
+  Gaudi::Property<bool> m_recordFlux{this, "RecordFlux", false, ""};
+  /// Commands to send to the G4 UI
+  Gaudi::Property<std::vector<std::string> > m_g4commands{this, "G4Commands", {}, "Commands to send to the G4UI"};
+  /// Activate multi-threading configuration
+  Gaudi::Property<bool> m_useMT{this,"MultiThreading",  false, "Multi-threading specific settings"};
+  Gaudi::Property<bool> m_activateParallelGeometries{this, "ActivateParallelWorlds", false, "Toggle on/off the G4 parallel geometry system"};
+  /// Random number service
+  ServiceHandle<IAthRNGSvc> m_rndmGenSvc{this, "AtRndmGenSvc", "AthRNGSvc", ""}; // TODO rename property
+  ///
+  ServiceHandle<IUserLimitsSvc> m_userLimitsSvc{this, "UserLimitsSvc", "UserLimitsSvc", ""};
+  /// User Action Service
+  ServiceHandle<G4UA::IUserActionSvc> m_userActionSvc{this, "UserActionSvc", "G4UA::UserActionSvc", ""};
+  /// Detector Geometry Service (builds G4 Geometry)
+  ServiceHandle<IDetectorGeometrySvc> m_detGeoSvc{this, "DetGeoSvc", "DetectorGeometrySvc", ""};
+  /// Service to convert ISF_Particles into a G4Event
+  ServiceHandle<ISF::IFaserInputConverter> m_inputConverter{this, "InputConverter", "ISF_FaserInputConverter", ""};
+  /// Physics List Tool
+  ServiceHandle<IPhysicsListSvc> m_physListSvc{this, "PhysicsListSvc", "PhysicsListSvc", ""};
+  /// Sensitive Detector Master Tool
+  PublicToolHandle<ISensitiveDetectorMasterTool> m_senDetTool{this, "SenDetMasterTool", "SensitiveDetectorMasterTool", ""};
+  /// Fast Simulation Master Tool
+  PublicToolHandle<IFastSimulationMasterTool> m_fastSimTool{this, "FastSimMasterTool", "FastSimulationMasterTool", ""};
+  /// @}
+
+};
+
+#endif// G4FASERALG_G4FaserAlg_H
diff --git a/Simulation/G4Faser/G4FaserAlg/src/G4FaserFluxRecorder.cxx b/Simulation/G4Faser/G4FaserAlg/src/G4FaserFluxRecorder.cxx
new file mode 100644
index 00000000..634f6552
--- /dev/null
+++ b/Simulation/G4Faser/G4FaserAlg/src/G4FaserFluxRecorder.cxx
@@ -0,0 +1,121 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "G4FaserFluxRecorder.h"
+
+#include "G4Event.hh"
+#include "G4GeometryManager.hh"
+#include "G4HCofThisEvent.hh"
+#include "G4LogicalVolumeStore.hh"
+#include "G4ParallelWorldScoringProcess.hh"
+#include "G4ParticleTable.hh"
+#include "G4ProcessManager.hh"
+#include "G4RegionStore.hh"
+#include "G4Run.hh"
+#include "G4ScoringManager.hh"
+#include "G4StateManager.hh"
+#include "G4TransportationManager.hh"
+#include "G4UImanager.hh"
+#include "G4UserRunAction.hh"
+#include "G4Version.hh"
+
+void G4FaserFluxRecorder::InitializeFluxRecording()
+{
+  G4UImanager *ui = G4UImanager::GetUIpointer();
+  ui->ApplyCommand("/run/setCutForAGivenParticle proton 0 mm");
+
+  G4ScoringManager* ScM = G4ScoringManager::GetScoringManagerIfExist();
+
+  if(!ScM) { return; }
+
+  ui->ApplyCommand("/score/create/cylinderMesh cylMesh_1");
+  //                        R  Z(-24 to 24)
+  ui->ApplyCommand("/score/mesh/cylinderSize 12. 24. m");
+  //                iR iZ
+  //ui->ApplyCommand("/score/mesh/nBin 1 1 1");
+  ui->ApplyCommand("/score/mesh/nBin 120 480 1");
+
+  ui->ApplyCommand("/score/quantity/energyDeposit eDep");
+
+  ui->ApplyCommand("/score/quantity/cellFlux CF_photon");
+  ui->ApplyCommand("/score/filter/particle photonFilter gamma");
+  // above 2 line crete tally for cell flux for gamma
+
+  ui->ApplyCommand("/score/quantity/cellFlux CF_neutron");
+  ui->ApplyCommand("/score/filter/particle neutronFilter neutron");
+
+  ui->ApplyCommand("/score/quantity/cellFlux CF_HEneutron");
+  ui->ApplyCommand("/score/filter/particleWithKineticEnergy HEneutronFilter 20 7000000 MeV neutron");
+
+  ui->ApplyCommand("/score/quantity/doseDeposit dose");
+
+  ui->ApplyCommand("/score/close");
+  ui->ApplyCommand("/score/list");
+
+  G4int nPar = ScM->GetNumberOfMesh();
+
+  if(nPar<1) { return; }
+
+  G4ParticleTable::G4PTblDicIterator* particleIterator
+    = G4ParticleTable::GetParticleTable()->GetIterator();
+
+  for(G4int iw=0;iw<nPar;iw++) {
+    G4VScoringMesh* mesh = ScM->GetMesh(iw);
+    G4VPhysicalVolume* pWorld
+      = G4TransportationManager::GetTransportationManager()
+      ->IsWorldExisting(ScM->GetWorldName(iw));
+    if(!pWorld) {
+      pWorld = G4TransportationManager::GetTransportationManager()
+        ->GetParallelWorld(ScM->GetWorldName(iw));
+      pWorld->SetName(ScM->GetWorldName(iw));
+
+      G4ParallelWorldScoringProcess* theParallelWorldScoringProcess
+        = new G4ParallelWorldScoringProcess(ScM->GetWorldName(iw));
+      theParallelWorldScoringProcess->SetParallelWorld(ScM->GetWorldName(iw));
+
+      particleIterator->reset();
+      while( (*particleIterator)() ) {
+        G4ParticleDefinition* particle = particleIterator->value();
+        G4ProcessManager* pmanager = particle->GetProcessManager();
+        if(pmanager) {
+          pmanager->AddProcess(theParallelWorldScoringProcess);
+          pmanager->SetProcessOrderingToLast(theParallelWorldScoringProcess, idxAtRest);
+          pmanager->SetProcessOrderingToSecond(theParallelWorldScoringProcess, idxAlongStep);
+          pmanager->SetProcessOrderingToLast(theParallelWorldScoringProcess, idxPostStep);
+        }
+      }
+    }
+
+    mesh->Construct(pWorld);
+  }
+  return;
+}
+
+void G4FaserFluxRecorder::RecordFlux(const G4Event* currentEvent)
+{
+  G4ScoringManager* ScM = G4ScoringManager::GetScoringManagerIfExist();
+  if(ScM) {
+    G4int nPar = ScM->GetNumberOfMesh();
+    G4HCofThisEvent* HCE = currentEvent->GetHCofThisEvent();
+    if(HCE && nPar>0) {
+      G4int nColl = HCE->GetCapacity();
+      for(G4int i=0;i<nColl;i++) {
+        G4VHitsCollection* HC = HCE->GetHC(i);
+        if(HC) { ScM->Accumulate(HC); }
+      }
+    }
+  }
+  return;
+}
+
+void G4FaserFluxRecorder::WriteFluxInformation()
+{
+  G4UImanager *ui=G4UImanager::GetUIpointer();
+  ui->ApplyCommand("/score/dumpQuantityToFile cylMesh_1 eDep edep.txt");
+  ui->ApplyCommand("/score/dumpQuantityToFile cylMesh_1 CF_neutron neutron.txt");
+  ui->ApplyCommand("/score/dumpQuantityToFile cylMesh_1 CF_HEneutron HEneutron.txt");
+  ui->ApplyCommand("/score/dumpQuantityToFile cylMesh_1 CF_photon photon.txt");
+  ui->ApplyCommand("/score/dumpQuantityToFile cylMesh_1 dose dose.txt");
+  return;
+}
diff --git a/Simulation/G4Faser/G4FaserAlg/src/G4FaserFluxRecorder.h b/Simulation/G4Faser/G4FaserAlg/src/G4FaserFluxRecorder.h
new file mode 100644
index 00000000..41db95c7
--- /dev/null
+++ b/Simulation/G4Faser/G4FaserAlg/src/G4FaserFluxRecorder.h
@@ -0,0 +1,25 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef G4FaserFluxRecorder_H
+#define G4FaserFluxRecorder_H
+
+#include "G4AtlasInterfaces/IFluxRecorder.h"
+
+class G4FaserFluxRecorder: public IFluxRecorder {
+
+public:
+  /// @name Methods related to flux recording
+  /// @{
+  /// Initialize flux recording
+  void InitializeFluxRecording() override final;
+  /// Record fluxes from current event
+  void RecordFlux(const G4Event*) override final;
+  /// Dump flux information to text files
+  void WriteFluxInformation() override final;
+  /// @}
+
+};
+
+#endif
diff --git a/Simulation/G4Faser/G4FaserAlg/src/components/G4FaserAlg_entries.cxx b/Simulation/G4Faser/G4FaserAlg/src/components/G4FaserAlg_entries.cxx
new file mode 100644
index 00000000..ecba80c1
--- /dev/null
+++ b/Simulation/G4Faser/G4FaserAlg/src/components/G4FaserAlg_entries.cxx
@@ -0,0 +1,3 @@
+#include "../G4FaserAlg.h"
+
+DECLARE_COMPONENT( G4FaserAlg )
diff --git a/Simulation/G4Faser/G4FaserApp/test/runG4.py b/Simulation/G4Faser/G4FaserAlg/test/runG4.py
similarity index 85%
rename from Simulation/G4Faser/G4FaserApp/test/runG4.py
rename to Simulation/G4Faser/G4FaserAlg/test/runG4.py
index 06157d9f..aa062a79 100644
--- a/Simulation/G4Faser/G4FaserApp/test/runG4.py
+++ b/Simulation/G4Faser/G4FaserAlg/test/runG4.py
@@ -19,12 +19,6 @@ if __name__ == "__main__":
     from FaserGeoModel.FaserGeoModelConfig import FaserGeometryCfg
     from G4FaserAlg.G4FaserAlgConfigNew import G4FaserAlgCfg
     from G4FaserServices.G4FaserServicesConfigNew import G4GeometryNotifierSvcCfg
-    from G4AtlasTools.G4AtlasToolsConf import SensitiveDetectorMasterTool
-    from G4FaserTools.G4FaserToolsConfig import generateSensitiveDetectorList
-    from VetoG4_SD.VetoG4_SDToolConfig import VetoSensorSDCfg
-    from TriggerG4_SD.TriggerG4_SDToolConfig import TriggerSensorSDCfg
-    from PreshowerG4_SD.PreshowerG4_SDToolConfig import PreshowerSensorSDCfg
-    from FaserSCT_G4_SD.FaserSCT_G4_SDToolConfig import SctSensorSDCfg
 #
 # Set up logging and new style config
 #
@@ -122,24 +116,11 @@ if __name__ == "__main__":
     acc.getEventAlgo("OutputStreamHITS").AcceptAlgs = ["G4FaserAlg"]               # optional
     acc.getEventAlgo("OutputStreamHITS").WritingTool.ProcessingTag = "StreamHITS"  # required
 #
-#  Here is the "manual" configuration of the Geant4 pieces
+#  Here is the configuration of the Geant4 pieces
 #    
     acc.merge(FaserGeometryCfg(ConfigFlags))
     acc.merge(G4FaserAlgCfg(ConfigFlags))
-    algo = acc.getEventAlgo("G4FaserAlg")
-    veto, vetosd = VetoSensorSDCfg(ConfigFlags)
-    trigger, triggersd = TriggerSensorSDCfg(ConfigFlags)
-    preshower, preshowersd = PreshowerSensorSDCfg(ConfigFlags)
-    sct, sctsd = SctSensorSDCfg(ConfigFlags)
-    sendet = SensitiveDetectorMasterTool(SensitiveDetectors = [vetosd,triggersd,preshowersd,sctsd])
-    acc.addPublicTool(sendet)
-    algo.SenDetMasterTool = sendet
-    acc.merge(veto)
-    acc.merge(trigger)
-    acc.merge(preshower)
-    acc.merge(sct)
     acc.addService(G4GeometryNotifierSvcCfg(ConfigFlags, ActivateLVNotifier=True))
-
 #
 # Verbosity
 #
diff --git a/Simulation/G4Faser/G4FaserApp/CMakeLists.txt b/Simulation/G4Faser/G4FaserApp/CMakeLists.txt
deleted file mode 100644
index 8382ef9a..00000000
--- a/Simulation/G4Faser/G4FaserApp/CMakeLists.txt
+++ /dev/null
@@ -1,55 +0,0 @@
-################################################################################
-# Package: G4FaserApp
-################################################################################
-
-# Declare the package name:
-atlas_subdir( G4FaserApp )
-
-# Declare the package's dependencies:
-atlas_depends_on_subdirs( PUBLIC
-                          GaudiKernel
-                          PRIVATE
-                          Control/AthenaBaseComps
-                          Control/AthenaKernel
-                          Control/SGTools
-                          Control/StoreGate
-                          DetectorDescription/GeoModel/GeoModelInterfaces
-                          Event/EventInfo
-                          Generators/GeneratorObjects
-                          Simulation/G4Atlas/G4AtlasInterfaces
-                          Simulation/G4Atlas/G4AtlasAlgs
-                          Simulation/G4Sim/MCTruthBase
-                          Simulation/ISF/ISF_Core/ISF_Interfaces
-                          Simulation/Barcode/BarcodeInterfaces)
-
-# External dependencies:
-find_package( CLHEP )
-find_package( Geant4 )
-find_package( HepMC )
-find_package( XercesC )
-find_package( Eigen )
-
-# G4AtlasAlgLib library
-
-#atlas_add_library( G4AtlasAlgLib
-#                     src/*.cxx
-#                     PUBLIC_HEADERS G4AtlasAlg
-#                     INCLUDE_DIRS ${GEANT4_INCLUDE_DIRS} ${EIGEN_INCLUDE_DIRS} ${XERCESC_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS}
-# ${HEPMC_INCLUDE_DIRS}
-#                     LINK_LIBRARIES ${GEANT4_LIBRARIES} ${EIGEN_LIBRARIES} ${XERCESC_LIBRARIES} ${CLHEP_LIBRARIES} ${HEPMC_LIBRARIES} AthenaBaseComps AthenaKernel GaudiKernel G4AtlasInterfaces SGTools StoreGateLib SGtests EventInfo GeneratorObjects MCTruthBaseLib )
-#
-# Component(s) in the package:
-#atlas_add_component( G4AtlasAlg
-#                     src/components/*.cxx
-#                     PUBLIC_HEADERS G4AtlasAlg
-#                     INCLUDE_DIRS ${GEANT4_INCLUDE_DIRS} ${EIGEN_INCLUDE_DIRS} ${XERCESC_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS} ${HEPMC_INCLUDE_DIRS}
-#                     LINK_LIBRARIES ${GEANT4_LIBRARIES} ${EIGEN_LIBRARIES} ${XERCESC_LIBRARIES} ${CLHEP_LIBRARIES} ${HEPMC_LIBRARIES} AthenaBaseComps AthenaKernel GaudiKernel G4AtlasInterfaces G4AtlasAlgLib SGTools StoreGateLib SGtests EventInfo GeneratorObjects MCTruthBaseLib )
-
-atlas_add_test( G4FaserAlgConfig_Test
-                SCRIPT test/runG4.py
-                PROPERTIES TIMEOUT 300 
-                PROPERTIES WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
-
-# Install files from the package:
-atlas_install_python_modules( python/*.py )
-atlas_install_scripts( test/*.py )
diff --git a/Simulation/G4Faser/G4FaserServices/CMakeLists.txt b/Simulation/G4Faser/G4FaserServices/CMakeLists.txt
index 36c0adb7..0a697736 100644
--- a/Simulation/G4Faser/G4FaserServices/CMakeLists.txt
+++ b/Simulation/G4Faser/G4FaserServices/CMakeLists.txt
@@ -14,12 +14,12 @@ atlas_depends_on_subdirs( PUBLIC
                           DetectorDescription/AtlasDetDescr
                           Generators/GeneratorObjects
                           Generators/TruthUtils
-                          Simulation/G4Sim/MCTruth
+                          Simulation/G4Sim/FaserMCTruth
                           Simulation/G4Sim/SimHelpers
                           Simulation/G4Sim/TrackRecord
-                          Simulation/ISF/ISF_Core/ISF_Event
-                          Simulation/ISF/ISF_Core/ISF_Interfaces
-                          Simulation/ISF/ISF_HepMC/ISF_HepMC_Interfaces
+                          Simulation/ISF/ISF_Core/FaserISF_Event
+                          Simulation/ISF/ISF_Core/FaserISF_Interfaces
+                          Simulation/ISF/ISF_HepMC/FaserISF_HepMC_Interfaces
                           Tools/PmbCxxUtils )
 
 # External dependencies:
@@ -31,11 +31,11 @@ find_package( HepPDT )
 find_package( ROOT COMPONENTS Core Tree MathCore Hist RIO pthread )
 
 # Component(s) in the package:
-atlas_add_component( G4FaserServices
-                     src/*.cxx
-                     src/components/*.cxx
-                     INCLUDE_DIRS ${ROOT_INCLUDE_DIRS} ${GEANT4_INCLUDE_DIRS} ${HEPMC_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS} ${HEPPDT_INCLUDE_DIRS}
-                     LINK_LIBRARIES ${ROOT_LIBRARIES} ${GEANT4_LIBRARIES} ${HEPMC_LIBRARIES} ${CLHEP_LIBRARIES} ${HEPPDT_LIBRARIES} GaudiKernel AthenaBaseComps StoreGateLib SGtests GeneratorObjects MCTruth SimHelpers ISF_Event ISF_Interfaces PmbCxxUtils TruthUtils )
+#atlas_add_component( G4FaserServices
+#                     src/*.cxx
+#                     src/components/*.cxx
+#                     INCLUDE_DIRS ${ROOT_INCLUDE_DIRS} ${GEANT4_INCLUDE_DIRS} ${HEPMC_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS} ${HEPPDT_INCLUDE_DIRS}
+#                     LINK_LIBRARIES ${ROOT_LIBRARIES} ${GEANT4_LIBRARIES} ${HEPMC_LIBRARIES} ${CLHEP_LIBRARIES} ${HEPPDT_LIBRARIES} GaudiKernel AthenaBaseComps StoreGateLib SGtests GeneratorObjects FaserMCTruth SimHelpers FaserISF_Event FaserISF_Interfaces PmbCxxUtils TruthUtils )
 
 
 # Install files from the package:
diff --git a/Simulation/G4Faser/G4FaserServices/python/G4FaserServicesConfigNew.py b/Simulation/G4Faser/G4FaserServices/python/G4FaserServicesConfigNew.py
index 6b12511c..115634e5 100644
--- a/Simulation/G4Faser/G4FaserServices/python/G4FaserServicesConfigNew.py
+++ b/Simulation/G4Faser/G4FaserServices/python/G4FaserServicesConfigNew.py
@@ -9,7 +9,6 @@ from G4AtlasServices.G4AtlasServicesConf import DetectorGeometrySvc, G4AtlasSvc,
 #  Physics region tools
 #
 from G4FaserTools.G4PhysicsRegionConfigNew import ScintillatorPhysicsRegionToolCfg, TrackerPhysicsRegionToolCfg #, FaserCaloPhysicsRegionToolCfg
-from G4FaserServices.G4FaserServicesConf import ISF__FaserGeoIDSvc
 #
 #  Geometry tools
 #
@@ -21,15 +20,10 @@ from G4FaserTools.G4FieldConfigNew import FASERFieldManagerToolCfg, VetoFieldMan
 #
 #  Future field managers (?)
 #
-# from G4FaserTools.G4FieldConfigNew import TriggerFieldManagerToolCfg, PreshowerFieldManagerToolCfg, UpstreamDipoleFieldManagerToolCfg, CentralDipoleFieldManagerToolCfg, DownstreamDipleFieldManagerToolCfg, FaserCaloFieldManagerToolCfg
-from G4FaserTools.G4FieldConfigNew import TrackerFieldManagerToolCfg
+# from G4FaserTools.G4FieldConfigNew import UpstreamDipoleFieldManagerToolCfg, CentralDipoleFieldManagerToolCfg, DownstreamDipleFieldManagerToolCfg, FaserCaloFieldManagerToolCfg
+from G4FaserTools.G4FieldConfigNew import TrackerFieldManagerToolCfg, DipoleFieldManagerToolCfg
 #
 #
-def FaserGeoIDSvcCfg(ConfigFlags, name="ISF_FaserGeoIDSvc", **kwargs):
-    result = ComponentAccumulator()
-    # with ISF volume definitions
-    result.addService(ISF__FaserGeoIDSvc(name, **kwargs))
-    return result
 #
 def getFASER_RegionCreatorList(ConfigFlags):
     regionCreatorList = []
@@ -71,6 +65,10 @@ def FASER_FieldMgrListCfg(ConfigFlags):
     #     acc = DownstreamDipoleFieldManagerToolCfg(ConfigFlags)
     #     tool  = result.popToolsAndMerge(acc)
     #     fieldMgrList += [tool]
+    if ConfigFlags.Detector.SimulateDipole:
+        acc = DipoleFieldManagerToolCfg(ConfigFlags)
+        tool  = result.popToolsAndMerge(acc)
+        fieldMgrList += [tool]    
     if ConfigFlags.Detector.SimulateVeto:
         acc = VetoFieldManagerToolCfg(ConfigFlags)
         tool  = result.popToolsAndMerge(acc)
diff --git a/Simulation/G4Faser/G4FaserServices/python/G4FaserUserActionConfigNew.py b/Simulation/G4Faser/G4FaserServices/python/G4FaserUserActionConfigNew.py
new file mode 100644
index 00000000..cf994348
--- /dev/null
+++ b/Simulation/G4Faser/G4FaserServices/python/G4FaserUserActionConfigNew.py
@@ -0,0 +1,80 @@
+# Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+
+from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator
+# from FaserMCTruthBase.FaserMCTruthBaseConfigNew import MCTruthSteppingActionToolCfg
+
+from G4AtlasServices.G4AtlasServicesConf import G4UA__UserActionSvc
+
+from G4UserActions.G4UserActionsConfigNew import AthenaStackingActionToolCfg, AthenaTrackingActionToolCfg
+
+
+# New function for all user action types
+def getDefaultActions(ConfigFlags):
+    result = ComponentAccumulator()
+
+    actions = []
+
+    #
+    # System stacking action
+    # This is used to apply cuts to the particles that are processed
+    # potentially ignoring some particles
+    #
+    actions += [result.popToolsAndMerge( AthenaStackingActionToolCfg(ConfigFlags)  )]
+    
+    #
+    # Tracking action
+    # This creates a trajectory that's updated with each step, and registers
+    # secondary particles into the truth record.
+    #
+    actions += [result.popToolsAndMerge( AthenaTrackingActionToolCfg(ConfigFlags) )]
+
+    # Some truth handling actions (and timing)
+    # if not ConfigFlags.Sim.ISFRun:
+    #     actions += [
+    #                 #result.popToolsAndMerge( AthenaTrackingActionToolCfg(ConfigFlags) ),
+    #                 result.popToolsAndMerge( MCTruthSteppingActionToolCfg(ConfigFlags) )
+    #                 #'G4UA::G4SimTimerTool']
+    #                 ]
+    # # Track counter
+    # #actions += ['G4UA::G4TrackCounterTool']
+
+    # # Cosmic Perigee action
+    # if ConfigFlags.Beam.Type == 'cosmics' and ConfigFlags.Sim.CavernBG:
+    #     actions += ['G4UA::CosmicPerigeeActionTool']
+    # # Cosmic filter
+    # if ConfigFlags.Beam.Type == 'cosmics' and not ConfigFlags.Sim.ISFRun:
+    #     actions += ['G4UA::G4CosmicFilterTool']
+    # if ConfigFlags.Sim.StoppedParticleFile:
+    #     actions += ['G4UA::StoppedParticleFilterTool',
+    #                 'G4UA::StoppedParticleActionTool']
+    # # Hit wrapper action
+    # if ConfigFlags.Sim.CavernBG == 'Read':
+    #     actions += ['G4UA::HitWrapperTool']
+    # # Photon killer
+    # if ConfigFlags.Sim.PhysicsList == 'QGSP_BERT_HP':
+    #     actions += ['G4UA::PhotonKillerTool']
+    # # Calo calibration default processing
+    # if ConfigFlags.Sim.CalibrationRun == 'LAr+Tile':
+    #     actions+=['G4UA::CaloG4::CalibrationDefaultProcessingTool']
+
+    return actions
+
+def UserActionSvcCfg(ConfigFlags, name="G4UA::UserActionSvc", **kwargs):
+    """
+    Get the standard UA svc configurable with all default actions added.
+    This function is normally called by the configured factory, not users.
+    """
+    result = ComponentAccumulator()
+
+    #how to convert this flag?
+    from G4AtlasApps.SimFlags import simFlags
+    optActions = simFlags.OptionalUserActionList.get_Value()
+    # new user action tools
+    kwargs.setdefault('UserActionTools',
+                      getDefaultActions(ConfigFlags) + optActions['General'])
+
+    # placeholder for more advanced config, if needed
+    result.addService ( G4UA__UserActionSvc(name, **kwargs) )
+
+    return result
+    
diff --git a/Simulation/G4Faser/G4FaserServices/src/FaserGeoIDSvc.cxx b/Simulation/G4Faser/G4FaserServices/src/FaserGeoIDSvc.cxx
deleted file mode 100644
index 7958b3ac..00000000
--- a/Simulation/G4Faser/G4FaserServices/src/FaserGeoIDSvc.cxx
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
-*/
-
-///////////////////////////////////////////////////////////////////
-// GeoIDSvc.cxx, (c) ATLAS Detector software
-///////////////////////////////////////////////////////////////////
-
-// class header include
-#include "FaserGeoIDSvc.h"
-
-// framework includes
-#include "GaudiKernel/Bootstrap.h"
-#include "GaudiKernel/ISvcLocator.h"
-
-// DetectorDescription
-#include "AtlasDetDescr/AtlasRegionHelper.h"
-
-// STL includes
-#include <algorithm>
-
-/** Constructor **/
-ISF::FaserGeoIDSvc::FaserGeoIDSvc(const std::string& name,ISvcLocator* svc) :
-  base_class(name,svc)
-{ }
-
-
-/** Destructor **/
-ISF::FaserGeoIDSvc::~FaserGeoIDSvc()
-{ }
-
-
-// Athena algtool's Hooks
-StatusCode  ISF::FaserGeoIDSvc::initialize()
-{
-  ATH_MSG_INFO("initialize() ...");
-
-   ATH_MSG_INFO("initialize() successful");
-  return StatusCode::SUCCESS;
-}
-
-
-StatusCode  ISF::FaserGeoIDSvc::finalize() {
-  ATH_MSG_INFO("finalize() ...");
-
-  ATH_MSG_INFO("finalize() successful");
-  return StatusCode::SUCCESS;
-}
-
-
-ISF::InsideType ISF::FaserGeoIDSvc::inside(const Amg::Vector3D& , AtlasDetDescr::AtlasRegion geoID) const {
-
-// Only one answer...
-  return (geoID == AtlasDetDescr::fUndefinedAtlasRegion ? ISF::fInside : ISF::fOutside);
-}
-
-
-AtlasDetDescr::AtlasRegion ISF::FaserGeoIDSvc::identifyGeoID(const Amg::Vector3D& ) const {
-
-// Only one answer...
-  return AtlasDetDescr::fUndefinedAtlasRegion;
-}
-
-
-AtlasDetDescr::AtlasRegion ISF::FaserGeoIDSvc::identifyNextGeoID(const Amg::Vector3D& ,
-                                                            const Amg::Vector3D& ) const {
-
-// Only one answer...
-  return AtlasDetDescr::fUndefinedAtlasRegion;
-}
-
diff --git a/Simulation/G4Faser/G4FaserServices/src/components/G4FaserServices_entries.cxx b/Simulation/G4Faser/G4FaserServices/src/components/G4FaserServices_entries.cxx
deleted file mode 100644
index 0b310990..00000000
--- a/Simulation/G4Faser/G4FaserServices/src/components/G4FaserServices_entries.cxx
+++ /dev/null
@@ -1,3 +0,0 @@
-#include "../FaserGeoIDSvc.h"
-
-DECLARE_COMPONENT( ISF::FaserGeoIDSvc )
diff --git a/Simulation/G4Faser/G4FaserTools/python/G4FaserToolsConfigNew.py b/Simulation/G4Faser/G4FaserTools/python/G4FaserToolsConfigNew.py
new file mode 100644
index 00000000..b05da95e
--- /dev/null
+++ b/Simulation/G4Faser/G4FaserTools/python/G4FaserToolsConfigNew.py
@@ -0,0 +1,82 @@
+# Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+from __future__ import print_function
+from AthenaConfiguration.ComponentFactory import CompFactory
+
+
+from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator
+from AthenaCommon import CfgMgr
+SensitiveDetectorMasterTool=CompFactory.SensitiveDetectorMasterTool
+
+from VetoG4_SD.VetoG4_SDToolConfig import VetoSensorSDCfg
+from TriggerG4_SD.TriggerG4_SDToolConfig import TriggerSensorSDCfg
+from PreshowerG4_SD.PreshowerG4_SDToolConfig import PreshowerSensorSDCfg
+from FaserSCT_G4_SD.FaserSCT_G4_SDToolConfig import SctSensorSDCfg
+
+def generateScintSensitiveDetectorList(ConfigFlags):
+
+    result = ComponentAccumulator()
+    SensitiveDetectorList=[]
+
+    if ConfigFlags.Detector.SimulateVeto:
+        accVeto,toolVeto = VetoSensorSDCfg(ConfigFlags)
+        SensitiveDetectorList += [ toolVeto ]
+        result.merge(accVeto)
+    
+    if ConfigFlags.Detector.SimulateTrigger:
+        accTrigger,toolTrigger = TriggerSensorSDCfg(ConfigFlags)
+        SensitiveDetectorList += [ toolTrigger ]
+        result.merge(accTrigger)
+    
+    if ConfigFlags.Detector.SimulatePreshower:
+        accPreshower,toolPreshower = PreshowerSensorSDCfg(ConfigFlags)
+        SensitiveDetectorList += [ toolPreshower ]
+        result.merge(accPreshower)
+    
+    return result, SensitiveDetectorList #List of tools here now! (CALL IT TOOL LIST?)
+
+def generateTrackerSensitiveDetectorList(ConfigFlags):
+
+    result = ComponentAccumulator()
+    SensitiveDetectorList=[]
+
+    if ConfigFlags.Detector.SimulateFaserSCT:
+        accSCT,toolSCT = SctSensorSDCfg(ConfigFlags)
+        SensitiveDetectorList += [ toolSCT ]
+        result.merge(accSCT)
+        
+    return result, SensitiveDetectorList #List of tools here now! (CALL IT TOOL LIST?)
+
+
+# def generateEnvelopeSensitiveDetectorList(ConfigFlags):
+#     SensitiveDetectorList=[]
+#     if ConfigFlags.Beam.Type == 'cosmics' and not ConfigFlags.Sim.ReadTR:
+#         SensitiveDetectorList+=['CosmicRecord']
+#     return SensitiveDetectorList
+
+def generateSensitiveDetectorList(ConfigFlags):
+    result = ComponentAccumulator()
+    SensitiveDetectorList=[]
+    # SensitiveDetectorList += generateEnvelopeSensitiveDetectorList(ConfigFlags) # to update
+
+    acc_ScintSensitiveDetector, ScintSensitiveDetectorList = generateScintSensitiveDetectorList(ConfigFlags)
+    SensitiveDetectorList += ScintSensitiveDetectorList
+
+    acc_TrackerSensitiveDetector, TrackerSensitiveDetectorList = generateTrackerSensitiveDetectorList(ConfigFlags)
+    SensitiveDetectorList += TrackerSensitiveDetectorList
+
+    result.merge(acc_ScintSensitiveDetector)
+    result.merge(acc_TrackerSensitiveDetector)
+
+    result.setPrivateTools(SensitiveDetectorList)
+    return result
+
+def SensitiveDetectorMasterToolCfg(ConfigFlags, name="SensitiveDetectorMasterTool", **kwargs):
+    result = ComponentAccumulator()
+    accSensitiveDetector = generateSensitiveDetectorList(ConfigFlags)
+    kwargs.setdefault("SensitiveDetectors", result.popToolsAndMerge(accSensitiveDetector)) #list of tools
+
+    result.addPublicTool(SensitiveDetectorMasterTool(name, **kwargs)) #note -this is still a public tool
+    return result
+
+def getEmptySensitiveDetectorMasterTool(name="EmptySensitiveDetectorMasterTool", **kwargs):
+    return CfgMgr.SensitiveDetectorMasterTool(name, **kwargs)
diff --git a/Simulation/G4Faser/G4FaserTools/python/G4FieldConfigNew.py b/Simulation/G4Faser/G4FaserTools/python/G4FieldConfigNew.py
index 60b13be2..0bfaf6b6 100644
--- a/Simulation/G4Faser/G4FaserTools/python/G4FieldConfigNew.py
+++ b/Simulation/G4Faser/G4FaserTools/python/G4FieldConfigNew.py
@@ -99,7 +99,7 @@ def VetoFieldManagerToolCfg(ConfigFlags, name='VetoFieldManager', **kwargs):
 
 
 def TriggerFieldManagerToolCfg(ConfigFlags, name='TriggerFieldManager', **kwargs):
-    kwargs.setdefault("LogicalVolumes", ['Trigger::Trigger'])
+    kwargs.setdefault("LogicalVolumes", ['Trigger::TriggerStationA'])
     #kwargs.setdefault('DeltaChord',         0.00001)
     kwargs.setdefault('DeltaIntersection',  0.00001)
     kwargs.setdefault('DeltaOneStep',       0.0001)
@@ -110,7 +110,7 @@ def TriggerFieldManagerToolCfg(ConfigFlags, name='TriggerFieldManager', **kwargs
 
 
 def PreshowerFieldManagerToolCfg(ConfigFlags, name='PreshowerFieldManager', **kwargs):
-    kwargs.setdefault("LogicalVolumes", ['Preshower::Preshower'])
+    kwargs.setdefault("LogicalVolumes", ['Preshower::PreshowerStationA'])
     #kwargs.setdefault('DeltaChord',         0.00001)
     kwargs.setdefault('DeltaIntersection',  0.00001)
     kwargs.setdefault('DeltaOneStep',       0.0001)
@@ -130,6 +130,17 @@ def TrackerFieldManagerToolCfg(ConfigFlags, name='TrackerFieldManager', **kwargs
     # return BasicDetectorConstantFieldManagerToolCfg(ConfigFlags, name, **kwargs)
     return BasicDetectorFieldManagerToolCfg(ConfigFlags, name, **kwargs)
 
+def DipoleFieldManagerToolCfg(ConfigFlags, name='DipoleFieldManager', **kwargs):
+    kwargs.setdefault("LogicalVolumes", ['Dipole::Dipole'])
+    #kwargs.setdefault('DeltaChord',         0.00001)
+    kwargs.setdefault('DeltaIntersection',  0.00001)
+    kwargs.setdefault('DeltaOneStep',       0.0001)
+    kwargs.setdefault('MaximumEpsilonStep', 0.001)
+    kwargs.setdefault('MinimumEpsilonStep', 0.00001)
+    # return BasicDetectorConstantFieldManagerToolCfg(ConfigFlags, name, **kwargs)
+    return BasicDetectorFieldManagerToolCfg(ConfigFlags, name, **kwargs)
+
+
 # def BeamPipeFieldManagerToolCfg(ConfigFlags, name='BeamPipeFieldManager', **kwargs):
 #     kwargs.setdefault("LogicalVolumes", ['BeamPipe::BeamPipe'])
 #     #kwargs.setdefault('DeltaChord',         0.00001)
diff --git a/Simulation/G4Sim/FaserMCTruth/CMakeLists.txt b/Simulation/G4Sim/FaserMCTruth/CMakeLists.txt
new file mode 100644
index 00000000..0b51decf
--- /dev/null
+++ b/Simulation/G4Sim/FaserMCTruth/CMakeLists.txt
@@ -0,0 +1,30 @@
+################################################################################
+# Package: FaserMCTruth
+################################################################################
+
+# Declare the package name:
+atlas_subdir( FaserMCTruth )
+
+# Declare the package's dependencies:
+atlas_depends_on_subdirs( PUBLIC
+                          Control/AthenaKernel
+                          Generators/GeneratorObjects
+                          PRIVATE
+                          Simulation/ISF/ISF_Core/FaserISF_Event
+                          Simulation/ISF/ISF_Core/ISF_Event
+                          Simulation/G4Sim/SimHelpers )
+
+# External dependencies:
+find_package( CLHEP )
+find_package( Geant4 )
+find_package( HepMC )
+find_package( XercesC )
+
+# Component(s) in the package:
+atlas_add_library( FaserMCTruth
+                   src/*.cxx
+                   PUBLIC_HEADERS FaserMCTruth
+                   INCLUDE_DIRS ${GEANT4_INCLUDE_DIRS} ${XERCESC_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS} ${HEPMC_INCLUDE_DIRS}
+                   DEFINITIONS ${CLHEP_DEFINITIONS}
+                   LINK_LIBRARIES ${GEANT4_LIBRARIES} ${XERCESC_LIBRARIES} ${CLHEP_LIBRARIES} ${HEPMC_LIBRARIES} AthenaKernel GeneratorObjects
+                   PRIVATE_LINK_LIBRARIES ISF_Event FaserISF_Event SimHelpers )
diff --git a/Simulation/G4Sim/FaserMCTruth/FaserMCTruth/FaserEventInformation.h b/Simulation/G4Sim/FaserMCTruth/FaserMCTruth/FaserEventInformation.h
new file mode 100644
index 00000000..0ef0b9c6
--- /dev/null
+++ b/Simulation/G4Sim/FaserMCTruth/FaserMCTruth/FaserEventInformation.h
@@ -0,0 +1,61 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef FaserEventInformation_H
+#define FaserEventInformation_H
+
+#include "HepMC/GenEvent.h"
+#include "G4ThreeVector.hh"
+#include "G4VUserEventInformation.hh"
+
+class FaserEventInformation: public G4VUserEventInformation {
+public:
+        FaserEventInformation(): G4VUserEventInformation(),m_nrOfPrimaryParticles(0),
+                        m_nrOfPrimaryVertices(0),m_secondaryParticleBarCode(200000),
+                        m_secondaryVertexBarCode(-200000),m_theEvent(0),
+                        m_currentPrimary(0),m_currentlyTraced(0),
+                        m_last_processed_barcode(0),m_last_processed_step(0) {}
+        HepMC::GenEvent* GetHepMCEvent() ;
+        void SetHepMCEvent(HepMC::GenEvent*);
+        int GetNrOfPrimaryParticles() const;
+        void SetNrOfPrimaryParticles(int nr);
+        int GetNrOfPrimaryVertices() const;
+        void SetNrOfPrimaryVertices(int nr);
+        void SetVertexPosition(const G4ThreeVector);
+        const G4ThreeVector GetVertexPosition() const;
+        void Print() const {}
+
+        void SetCurrentPrimary(HepMC::GenParticle *p) {m_currentPrimary=p;}
+
+        void SetCurrentlyTraced(HepMC::GenParticle *p) {m_currentlyTraced=p;}
+
+        HepMC::GenParticle *GetCurrentPrimary() const {return m_currentPrimary;}
+
+        HepMC::GenParticle *GetCurrentlyTraced() const {return m_currentlyTraced;}
+        int SecondaryParticleBarCode() {m_secondaryParticleBarCode++;
+                                        return m_secondaryParticleBarCode;}
+        int SecondaryVertexBarCode() {m_secondaryVertexBarCode--;
+                                      return m_secondaryVertexBarCode;}
+        int GetLastProcessedBarcode() const { return m_last_processed_barcode; }
+        void SetLastProcessedBarcode(int b) { m_last_processed_barcode = b; }
+        int GetLastProcessedStep() const { return m_last_processed_step; }
+        void SetLastProcessedStep(int s) { m_last_processed_step = s; }
+
+private:
+        G4ThreeVector m_vertexPosition;
+        int m_nrOfPrimaryParticles;
+        int m_nrOfPrimaryVertices;
+        int m_secondaryParticleBarCode;
+        int m_secondaryVertexBarCode;
+        HepMC::GenEvent *m_theEvent;
+        HepMC::GenParticle *m_currentPrimary;
+        HepMC::GenParticle *m_currentlyTraced;
+        // These two are used by calibration hits as event-level flags
+        // They correspond to the last barcode and step processed by an SD
+        // Both are needed, because a particle might have only one step
+        int m_last_processed_barcode;
+        int m_last_processed_step;
+};
+
+#endif
diff --git a/Simulation/G4Sim/FaserMCTruth/FaserMCTruth/FaserPrimaryParticleInformation.h b/Simulation/G4Sim/FaserMCTruth/FaserMCTruth/FaserPrimaryParticleInformation.h
new file mode 100644
index 00000000..535c8517
--- /dev/null
+++ b/Simulation/G4Sim/FaserMCTruth/FaserMCTruth/FaserPrimaryParticleInformation.h
@@ -0,0 +1,38 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef FaserPrimaryParticleInformation_H
+#define FaserPrimaryParticleInformation_H
+
+#include "G4VUserPrimaryParticleInformation.hh"
+#include "HepMC/GenEvent.h"
+
+namespace ISF {
+  class FaserISFParticle;
+}
+
+class FaserPrimaryParticleInformation: public G4VUserPrimaryParticleInformation {
+public:
+	FaserPrimaryParticleInformation();
+	FaserPrimaryParticleInformation(const HepMC::GenParticle*, const ISF::FaserISFParticle* isp=0);
+	const HepMC::GenParticle *GetHepMCParticle() const;
+	int GetParticleBarcode() const;
+	void SuggestBarcode(int bc);
+	void SetParticle(const HepMC::GenParticle*);
+	void Print() const {}
+	int GetRegenerationNr() {return  m_regenerationNr;}
+	void SetRegenerationNr(int i) {m_regenerationNr=i;}
+
+	void SetISFParticle(const ISF::FaserISFParticle* isp);
+	const ISF::FaserISFParticle* GetISFParticle() const;
+
+private:
+	const HepMC::GenParticle *m_theParticle;
+	const ISF::FaserISFParticle* m_theISFParticle;
+
+	int m_regenerationNr;
+	int m_barcode;
+};
+
+#endif
diff --git a/Simulation/G4Sim/FaserMCTruth/FaserMCTruth/FaserTrackBarcodeInfo.h b/Simulation/G4Sim/FaserMCTruth/FaserMCTruth/FaserTrackBarcodeInfo.h
new file mode 100644
index 00000000..ba66de39
--- /dev/null
+++ b/Simulation/G4Sim/FaserMCTruth/FaserMCTruth/FaserTrackBarcodeInfo.h
@@ -0,0 +1,30 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef FaserTrackBarcodeInfo_H
+#define FaserTrackBarcodeInfo_H
+
+#include "FaserVTrackInformation.h"
+
+namespace ISF {
+  class FaserISFParticle;
+}
+
+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;
+
+private:
+	const ISF::FaserISFParticle *m_theBaseISFParticle;
+	int m_barcode;
+	bool m_returnedToISF;
+};
+
+
+#endif // FaserTrackBarcodeInfo_H
diff --git a/Simulation/G4Sim/FaserMCTruth/FaserMCTruth/FaserTrackHelper.h b/Simulation/G4Sim/FaserMCTruth/FaserMCTruth/FaserTrackHelper.h
new file mode 100644
index 00000000..4af26c9e
--- /dev/null
+++ b/Simulation/G4Sim/FaserMCTruth/FaserMCTruth/FaserTrackHelper.h
@@ -0,0 +1,26 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef FaserTrackHelper_H
+#define FaserTrackHelper_H
+
+#include "G4Track.hh"
+#include "FaserMCTruth/FaserTrackInformation.h"
+#include "GeneratorObjects/HepMcParticleLink.h"
+
+class FaserTrackHelper {
+public:
+  FaserTrackHelper(const G4Track* t);
+  bool IsPrimary() const ;
+  bool IsRegeneratedPrimary() const;
+  bool IsRegisteredSecondary() const ;
+  bool IsSecondary() const ;
+  int GetBarcode() const ;
+  FaserTrackInformation * GetTrackInformation() {return m_trackInfo;}
+  HepMcParticleLink GetParticleLink();
+private:
+  FaserTrackInformation *m_trackInfo;
+};
+
+#endif
diff --git a/Simulation/G4Sim/FaserMCTruth/FaserMCTruth/FaserTrackInformation.h b/Simulation/G4Sim/FaserMCTruth/FaserMCTruth/FaserTrackInformation.h
new file mode 100644
index 00000000..9c93b990
--- /dev/null
+++ b/Simulation/G4Sim/FaserMCTruth/FaserMCTruth/FaserTrackInformation.h
@@ -0,0 +1,34 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef FaserTrackInformation_H
+#define FaserTrackInformation_H
+
+#include "FaserVTrackInformation.h"
+
+namespace ISF {
+  class FaserISFParticle;
+}
+
+class FaserTrackInformation: public FaserVTrackInformation {
+public:
+	FaserTrackInformation();
+	FaserTrackInformation(const HepMC::GenParticle*,const ISF::FaserISFParticle* baseIsp=0);
+	const HepMC::GenParticle *GetHepMCParticle() const;
+	const ISF::FaserISFParticle *GetBaseISFParticle() const;
+	int GetParticleBarcode() const;
+	void SetParticle(const HepMC::GenParticle*);
+	void SetBaseISFParticle(const ISF::FaserISFParticle*);
+	void SetReturnedToISF(bool returned) {m_returnedToISF=returned;};
+	bool GetReturnedToISF() const {return m_returnedToISF;};
+	void SetRegenerationNr(int i) {m_regenerationNr=i;};
+	int GetRegenerationNr() const {return m_regenerationNr;};
+private:
+	int m_regenerationNr;
+	const HepMC::GenParticle *m_theParticle;
+	const ISF::FaserISFParticle *m_theBaseISFParticle;
+	bool m_returnedToISF;
+};
+
+#endif
diff --git a/Simulation/G4Sim/FaserMCTruth/FaserMCTruth/FaserTruthController.h b/Simulation/G4Sim/FaserMCTruth/FaserMCTruth/FaserTruthController.h
new file mode 100644
index 00000000..950f889c
--- /dev/null
+++ b/Simulation/G4Sim/FaserMCTruth/FaserMCTruth/FaserTruthController.h
@@ -0,0 +1,28 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef FaserTruthController_H
+#define FaserTruthController_H
+
+class TrackVisualizationHelper;
+
+class FaserTruthController {
+public:
+  static FaserTruthController *getTruthController();
+  void setVisualizationHelper(TrackVisualizationHelper *);
+  TrackVisualizationHelper* getVisualizationHelper() const
+  {
+    return m_theVisHelper;
+  }
+private:
+  // this is a singleton
+  static FaserTruthController *s_thePointer;
+  FaserTruthController();
+  FaserTruthController(const FaserTruthController&) {}
+  FaserTruthController& operator= (const FaserTruthController&);
+  ~FaserTruthController();
+  TrackVisualizationHelper *m_theVisHelper;
+};
+
+#endif
diff --git a/Simulation/G4Sim/FaserMCTruth/FaserMCTruth/FaserVTrackInformation.h b/Simulation/G4Sim/FaserMCTruth/FaserMCTruth/FaserVTrackInformation.h
new file mode 100644
index 00000000..6552652c
--- /dev/null
+++ b/Simulation/G4Sim/FaserMCTruth/FaserMCTruth/FaserVTrackInformation.h
@@ -0,0 +1,40 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef FaserVTrackInformation_H
+#define FaserVTrackInformation_H
+
+#include "G4VUserTrackInformation.hh"
+
+enum TrackClassification { Primary, RegeneratedPrimary, RegisteredSecondary, Secondary, BarcodeOnly } ;
+
+namespace HepMC {
+  class GenParticle;
+}
+
+namespace ISF {
+  class FaserISFParticle;
+}
+
+class FaserVTrackInformation: public G4VUserTrackInformation {
+public:
+	FaserVTrackInformation(TrackClassification tc=Primary);
+	const HepMC::GenParticle *GetPrimaryHepMCParticle() const;
+	void  SetPrimaryHepMCParticle(const HepMC::GenParticle*);
+	virtual const HepMC::GenParticle *GetHepMCParticle() const;
+	virtual const ISF::FaserISFParticle *GetBaseISFParticle() const;
+	virtual bool GetReturnedToISF() const;
+	virtual int  GetParticleBarcode() const =0;
+	virtual void SetParticle(const HepMC::GenParticle*);
+	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;}
+private:
+	TrackClassification m_classify;
+	const HepMC::GenParticle *m_thePrimaryParticle;
+};
+
+#endif
diff --git a/Simulation/G4Sim/FaserMCTruth/FaserMCTruth/TruthEvent.h b/Simulation/G4Sim/FaserMCTruth/FaserMCTruth/TruthEvent.h
new file mode 100644
index 00000000..30142b63
--- /dev/null
+++ b/Simulation/G4Sim/FaserMCTruth/FaserMCTruth/TruthEvent.h
@@ -0,0 +1,17 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TruthEvent_H
+#define TruthEvent_H
+
+#include "HepMC/GenEvent.h"
+#include "AthenaKernel/CLASS_DEF.h"
+
+typedef HepMC::GenEvent TruthEvent;
+typedef HepMC::GenVertex TruthVertex;
+typedef HepMC::GenParticle TruthParticle;
+
+CLASS_DEF( TruthEvent , 97924139 , 1 )
+
+#endif
diff --git a/Simulation/G4Sim/FaserMCTruth/src/FaserEventInformation.cxx b/Simulation/G4Sim/FaserMCTruth/src/FaserEventInformation.cxx
new file mode 100644
index 00000000..44bf462e
--- /dev/null
+++ b/Simulation/G4Sim/FaserMCTruth/src/FaserEventInformation.cxx
@@ -0,0 +1,38 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "FaserMCTruth/FaserEventInformation.h"
+
+HepMC::GenEvent* FaserEventInformation::GetHepMCEvent()
+{
+	return m_theEvent;
+}
+void FaserEventInformation::SetHepMCEvent(HepMC::GenEvent* ev)
+{
+        m_theEvent=ev;
+}
+int FaserEventInformation::GetNrOfPrimaryParticles() const
+{
+	return m_nrOfPrimaryParticles;
+}
+void FaserEventInformation::SetNrOfPrimaryParticles(int nr)
+{
+	m_nrOfPrimaryParticles=nr;
+}
+int FaserEventInformation::GetNrOfPrimaryVertices() const
+{
+	return m_nrOfPrimaryVertices;
+}
+void FaserEventInformation::SetNrOfPrimaryVertices(int nr)
+{
+	m_nrOfPrimaryVertices=nr;
+}
+void FaserEventInformation::SetVertexPosition(const G4ThreeVector vtx)
+{
+	m_vertexPosition=vtx;
+}
+const G4ThreeVector FaserEventInformation::GetVertexPosition() const
+{
+	return m_vertexPosition;
+}
diff --git a/Simulation/G4Sim/FaserMCTruth/src/FaserPrimaryParticleInformation.cxx b/Simulation/G4Sim/FaserMCTruth/src/FaserPrimaryParticleInformation.cxx
new file mode 100644
index 00000000..0314ea54
--- /dev/null
+++ b/Simulation/G4Sim/FaserMCTruth/src/FaserPrimaryParticleInformation.cxx
@@ -0,0 +1,48 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "FaserMCTruth/FaserPrimaryParticleInformation.h"
+
+FaserPrimaryParticleInformation::FaserPrimaryParticleInformation() 
+  : m_theParticle(0),m_theISFParticle(0),m_regenerationNr(0),m_barcode(-1)
+{
+}
+
+FaserPrimaryParticleInformation::FaserPrimaryParticleInformation(const HepMC::GenParticle *p, const ISF::FaserISFParticle* isp):m_theParticle(p),m_theISFParticle(isp),m_regenerationNr(0),m_barcode(-1)
+{
+}
+
+const HepMC::GenParticle* FaserPrimaryParticleInformation::GetHepMCParticle() const
+{
+	return m_theParticle;
+}
+
+const ISF::FaserISFParticle* FaserPrimaryParticleInformation::GetISFParticle() const
+{
+	return m_theISFParticle;
+}
+
+void FaserPrimaryParticleInformation::SuggestBarcode(int bc)
+{
+  m_barcode=bc;
+  if (m_theParticle) {
+    std::cout<<"ERROR: PrimaryParticleInformation::SuggestBarcode() should be only called if no HepMC::Particle is available"<<std::endl;
+    //theParticle->suggest_barcode(bc);
+  }
+}
+
+int FaserPrimaryParticleInformation::GetParticleBarcode() const
+{
+	return m_theParticle?m_theParticle->barcode():m_barcode;
+}
+
+void FaserPrimaryParticleInformation::SetParticle(const HepMC::GenParticle* p)
+{
+	m_theParticle=p;
+}
+
+void FaserPrimaryParticleInformation::SetISFParticle(const ISF::FaserISFParticle* p)
+{
+	m_theISFParticle=p;
+}
diff --git a/Simulation/G4Sim/FaserMCTruth/src/FaserTrackBarcodeInfo.cxx b/Simulation/G4Sim/FaserMCTruth/src/FaserTrackBarcodeInfo.cxx
new file mode 100644
index 00000000..78d64bed
--- /dev/null
+++ b/Simulation/G4Sim/FaserMCTruth/src/FaserTrackBarcodeInfo.cxx
@@ -0,0 +1,34 @@
+/*
+  Copyright (C) 2002-2017 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)
+{
+}
+
+int FaserTrackBarcodeInfo::GetParticleBarcode() const
+{
+  return m_barcode;
+}
+
+void FaserTrackBarcodeInfo::SetBaseISFParticle(const 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/FaserTrackHelper.cxx b/Simulation/G4Sim/FaserMCTruth/src/FaserTrackHelper.cxx
new file mode 100644
index 00000000..738c1779
--- /dev/null
+++ b/Simulation/G4Sim/FaserMCTruth/src/FaserTrackHelper.cxx
@@ -0,0 +1,48 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "FaserMCTruth/FaserTrackHelper.h"
+#include "FaserISF_Event/FaserISFParticle.h"
+
+FaserTrackHelper::FaserTrackHelper(const G4Track* t)
+{
+  m_trackInfo=static_cast<FaserTrackInformation *>(t->GetUserInformation());
+}
+bool FaserTrackHelper::IsPrimary() const
+{
+  if (m_trackInfo==0) return false;
+  return m_trackInfo->GetClassification()==Primary;
+}
+bool FaserTrackHelper::IsRegeneratedPrimary() const
+{
+  if (m_trackInfo==0) return false;
+  return m_trackInfo->GetClassification()==RegeneratedPrimary;
+}
+bool FaserTrackHelper::IsRegisteredSecondary() const
+{
+  if (m_trackInfo==0) return false;
+  return m_trackInfo->GetClassification()==RegisteredSecondary;
+}
+bool FaserTrackHelper::IsSecondary() const
+{
+  if (m_trackInfo==0) return true;
+  return m_trackInfo->GetClassification()==Secondary;
+}
+int FaserTrackHelper::GetBarcode() const
+{
+  if (m_trackInfo==0 || m_trackInfo->GetHepMCParticle()==0) return 0;
+  return m_trackInfo->GetParticleBarcode();
+}
+
+HepMcParticleLink FaserTrackHelper::GetParticleLink()
+{
+  int barcode = this->GetBarcode();
+  return HepMcParticleLink(barcode);
+  //HepMcParticleLink * originalParticleLink(nullptr);
+  //if (this->GetTrackInformation() && this->GetTrackInformation()->GetBaseISFParticle())
+  //  {
+  //    originalParticleLink = this->GetTrackInformation()->GetBaseISFParticle()->getParticleLink();
+  //  }
+  //return (originalParticleLink) ? HepMcParticleLink(barcode, originalParticleLink->eventIndex(), originalParticleLink->getEventCollection()) : HepMcParticleLink(barcode);
+}
diff --git a/Simulation/G4Sim/FaserMCTruth/src/FaserTrackInformation.cxx b/Simulation/G4Sim/FaserMCTruth/src/FaserTrackInformation.cxx
new file mode 100644
index 00000000..3bd0d982
--- /dev/null
+++ b/Simulation/G4Sim/FaserMCTruth/src/FaserTrackInformation.cxx
@@ -0,0 +1,43 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "FaserMCTruth/FaserTrackInformation.h"
+#include "HepMC/GenEvent.h"
+
+FaserTrackInformation::FaserTrackInformation():m_regenerationNr(0),m_theParticle(0),m_theBaseISFParticle(0),m_returnedToISF(false)
+{
+}
+
+FaserTrackInformation::FaserTrackInformation(const HepMC::GenParticle *p, const ISF::FaserISFParticle* baseIsp):
+    m_regenerationNr(0),
+    m_theParticle(p),
+    m_theBaseISFParticle(baseIsp),
+    m_returnedToISF(false)
+{
+}
+
+const HepMC::GenParticle* FaserTrackInformation::GetHepMCParticle() const
+{
+  return m_theParticle;
+}
+
+const ISF::FaserISFParticle* FaserTrackInformation::GetBaseISFParticle() const
+{
+  return m_theBaseISFParticle;
+}
+
+int FaserTrackInformation::GetParticleBarcode() const
+{
+  return ( m_theParticle ? m_theParticle->barcode() : 0 );
+}
+
+void FaserTrackInformation::SetParticle(const HepMC::GenParticle* p)
+{
+  m_theParticle=p;
+}
+
+void FaserTrackInformation::SetBaseISFParticle(const ISF::FaserISFParticle* p)
+{
+  m_theBaseISFParticle=p;
+}
diff --git a/Simulation/G4Sim/FaserMCTruth/src/FaserTruthController.cxx b/Simulation/G4Sim/FaserMCTruth/src/FaserTruthController.cxx
new file mode 100644
index 00000000..94e0889c
--- /dev/null
+++ b/Simulation/G4Sim/FaserMCTruth/src/FaserTruthController.cxx
@@ -0,0 +1,30 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "FaserMCTruth/FaserTruthController.h"
+#include "SimHelpers/TrackVisualizationHelper.h"
+
+FaserTruthController* FaserTruthController::s_thePointer=FaserTruthController::getTruthController() ;
+
+FaserTruthController* FaserTruthController::getTruthController()
+{
+  if (!s_thePointer) s_thePointer = new FaserTruthController;
+  return s_thePointer;
+}
+
+FaserTruthController::FaserTruthController()
+{
+  m_theVisHelper=new TrackVisualizationHelper;
+}
+
+FaserTruthController::~FaserTruthController()
+{
+  if (m_theVisHelper) delete m_theVisHelper;
+}
+void FaserTruthController::setVisualizationHelper(TrackVisualizationHelper *h)
+{
+  if (m_theVisHelper==h) return;
+  delete m_theVisHelper;
+  m_theVisHelper=h;
+}
diff --git a/Simulation/G4Sim/FaserMCTruth/src/FaserVTrackInformation.cxx b/Simulation/G4Sim/FaserMCTruth/src/FaserVTrackInformation.cxx
new file mode 100644
index 00000000..bc373eb4
--- /dev/null
+++ b/Simulation/G4Sim/FaserMCTruth/src/FaserVTrackInformation.cxx
@@ -0,0 +1,54 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "FaserMCTruth/FaserVTrackInformation.h"
+
+FaserVTrackInformation::FaserVTrackInformation(TrackClassification tc):m_classify(tc),m_thePrimaryParticle(0)
+{
+}
+
+const HepMC::GenParticle* FaserVTrackInformation::GetPrimaryHepMCParticle() const
+{
+  return m_thePrimaryParticle;
+}
+
+void FaserVTrackInformation::SetPrimaryHepMCParticle(const HepMC::GenParticle* p)
+{
+  m_thePrimaryParticle=p;
+}
+
+
+const HepMC::GenParticle* FaserVTrackInformation::GetHepMCParticle() const
+{
+  return 0;
+}
+
+const ISF::FaserISFParticle* FaserVTrackInformation::GetBaseISFParticle() const
+{
+  return 0;
+}
+
+bool FaserVTrackInformation::GetReturnedToISF() const
+{
+  return false;
+}
+
+void FaserVTrackInformation::SetParticle(const HepMC::GenParticle* /*p*/)
+{
+  // you should not call this, perhaps throw an exception?
+  std::cerr<<"ERROR  FaserVTrackInformation::SetParticle() not supported  "<<std::endl;
+ 
+}
+
+void FaserVTrackInformation::SetBaseISFParticle(const ISF::FaserISFParticle* /*p*/)
+{
+  // you should not call this, perhaps throw an exception?
+  std::cerr<<"ERROR  FaserVTrackInformation::SetBaseISFParticle() not supported  "<<std::endl;
+ 
+}
+
+void FaserVTrackInformation::SetReturnedToISF(bool)
+{
+  std::cerr<<"ERROR  FaserVTrackInformation::SetReturnedToISF() not supported  "<<std::endl;
+}
diff --git a/Simulation/G4Sim/FaserMCTruthBase/CMakeLists.txt b/Simulation/G4Sim/FaserMCTruthBase/CMakeLists.txt
new file mode 100644
index 00000000..6937f620
--- /dev/null
+++ b/Simulation/G4Sim/FaserMCTruthBase/CMakeLists.txt
@@ -0,0 +1,56 @@
+################################################################################
+# Package: FaserMCTruthBase
+################################################################################
+
+# Declare the package name:
+atlas_subdir( FaserMCTruthBase )
+
+# Declare the package's dependencies:
+atlas_depends_on_subdirs( PUBLIC
+                          Control/AthenaKernel
+                          GaudiKernel
+                          Simulation/G4Sim/SimHelpers
+                          Simulation/ISF/ISF_Core/ISF_Interfaces
+                          Simulation/ISF/ISF_Core/FaserISF_Interfaces
+                          PRIVATE
+                          Control/AthenaBaseComps
+                          Control/StoreGate
+                          Simulation/G4Atlas/G4AtlasInterfaces
+                          Simulation/G4Atlas/G4AtlasTools
+                          Simulation/G4Sim/FaserMCTruth
+                          Simulation/G4Sim/TrackRecord
+                          DetectorDescription/FaserDetDescr
+                          Simulation/ISF/ISF_Geant4/FaserISF_Geant4Event )
+
+# External dependencies:
+find_package( CLHEP )
+find_package( Geant4 )
+find_package( HepMC )
+find_package( XercesC )
+
+# Component(s) in the package:
+atlas_add_library( FaserMCTruthBaseLib
+                   src/*.cxx
+                   PUBLIC_HEADERS FaserMCTruthBase
+                   INCLUDE_DIRS ${GEANT4_INCLUDE_DIRS} ${XERCESC_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS} ${HEPMC_INCLUDE_DIRS}
+                   DEFINITIONS ${CLHEP_DEFINITIONS}
+                   LINK_LIBRARIES ${GEANT4_LIBRARIES} ${XERCESC_LIBRARIES} ${CLHEP_LIBRARIES} ${HEPMC_LIBRARIES} AthenaKernel GaudiKernel StoreGateLib SGtests G4AtlasToolsLib
+                   PRIVATE_LINK_LIBRARIES AthenaBaseComps
+                   G4AtlasInterfaces FaserMCTruth SimHelpers ISF_Interfaces FaserISF_Interfaces
+                   FaserDetDescr FaserISF_Geant4Event
+                 )
+
+#atlas_add_component( FaserMCTruthBase
+#                     src/components/*.cxx
+#                     INCLUDE_DIRS ${GEANT4_INCLUDE_DIRS} ${XERCESC_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS} ${HEPMC_INCLUDE_DIRS}
+#                     LINK_LIBRARIES ${GEANT4_LIBRARIES}
+#                     ${XERCESC_LIBRARIES} ${CLHEP_LIBRARIES}
+#                     ${HEPMC_LIBRARIES} AthenaKernel GaudiKernel
+#                     AthenaBaseComps StoreGateLib SGtests
+#                     G4AtlasInterfaces G4AtlasToolsLib FaserMCTruth
+#                     SimHelpers ISF_Interfaces FaserISF_Interfaces
+#                     FaserDetDescr FaserMCTruthBaseLib
+#                     FaserISF_Geant4Event )
+
+# Install files from the package:
+atlas_install_python_modules( python/*.py )
diff --git a/Simulation/G4Sim/FaserMCTruthBase/FaserMCTruthBase/FaserTrajectory.h b/Simulation/G4Sim/FaserMCTruthBase/FaserMCTruthBase/FaserTrajectory.h
new file mode 100644
index 00000000..c3d93d7c
--- /dev/null
+++ b/Simulation/G4Sim/FaserMCTruthBase/FaserMCTruthBase/FaserTrajectory.h
@@ -0,0 +1,40 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef FaserMCTruthBase_FaserTrajectory_H
+#define FaserMCTruthBase_FaserTrajectory_H
+
+#include "G4Trajectory.hh"
+
+/// @brief Class to store G4 trajectory information
+///
+/// NEEDS DOCUMENTATION
+///
+class FaserTrajectory : public G4Trajectory
+{
+
+public:
+
+  /// Constructor
+  FaserTrajectory(const G4Track* aTrack, int subDetVolLevel);
+
+  /// Overriden from G4 in order to do vertex analysis
+  void AppendStep(const G4Step* aStep);
+
+  /// Visualization stuff
+#if G4VERSION_NUMBER >= 1010
+  void DrawTrajectory() const override { DrawTrajectory(0); }
+#endif
+  void DrawTrajectory(G4int) const;
+
+private:
+
+  using G4Trajectory::DrawTrajectory;
+
+  /// The level in the G4 volume hierarchy at which can we find the sub-detector name
+  int m_subDetVolLevel;
+
+};
+
+#endif
diff --git a/Simulation/G4Sim/FaserMCTruthBase/FaserMCTruthBase/FaserTruthStrategyManager.h b/Simulation/G4Sim/FaserMCTruthBase/FaserMCTruthBase/FaserTruthStrategyManager.h
new file mode 100644
index 00000000..12bc2d23
--- /dev/null
+++ b/Simulation/G4Sim/FaserMCTruthBase/FaserMCTruthBase/FaserTruthStrategyManager.h
@@ -0,0 +1,41 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef FaserMCTruthBase_FaserTruthStrategyManager_H
+#define FaserMCTruthBase_FaserTruthStrategyManager_H
+
+// ISF include
+#include "FaserISF_Interfaces/IFaserTruthSvc.h"
+
+/// Forward declarations
+class G4Step;
+
+
+/// @brief Singleton class for creating truth incidents.
+/// This class is gradually being refactored out of existence.
+
+class FaserTruthStrategyManager
+{
+
+public:
+
+  /// Retrieve the singleton instance
+  static FaserTruthStrategyManager* GetStrategyManager();
+
+  /// Returns true if any of the truth strategies return true
+  bool CreateTruthIncident(const G4Step*, int subDetVolLevel) const;
+
+  /// Define which ISF TruthService to use
+  void SetISFTruthSvc(ISF::IFaserTruthSvc *truthSvc);
+
+private:
+  FaserTruthStrategyManager();
+  FaserTruthStrategyManager(const FaserTruthStrategyManager&) = delete;
+  FaserTruthStrategyManager& operator=(const FaserTruthStrategyManager&) = delete;
+
+  /// ISF Services the TruthStrategyManager talks to
+  ISF::IFaserTruthSvc* m_truthSvc;
+};
+
+#endif
diff --git a/Simulation/G4Sim/FaserMCTruthBase/src/FaserTrajectory.cxx b/Simulation/G4Sim/FaserMCTruthBase/src/FaserTrajectory.cxx
new file mode 100644
index 00000000..3ab8fabc
--- /dev/null
+++ b/Simulation/G4Sim/FaserMCTruthBase/src/FaserTrajectory.cxx
@@ -0,0 +1,160 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "FaserMCTruthBase/FaserTrajectory.h"
+#include "FaserMCTruthBase/FaserTruthStrategyManager.h"
+#include "FaserMCTruth/FaserTruthController.h"
+#include "FaserMCTruth/FaserTrackHelper.h"
+#include "SimHelpers/TrackVisualizationHelper.h"
+
+// Visualization stuff
+#include "G4VVisManager.hh"
+#include "G4Polyline.hh"
+#include "G4Polymarker.hh"
+#include "G4VisAttributes.hh"
+#include "G4Colour.hh"
+
+
+FaserTrajectory::FaserTrajectory(const G4Track* track, int subDetVolLevel)
+  : G4Trajectory(track), m_subDetVolLevel(subDetVolLevel)
+{}
+
+
+void FaserTrajectory::AppendStep(const G4Step* aStep)
+{
+  // only use truth service if there are new any secondaries
+  const int numSecondaries = aStep->GetSecondaryInCurrentStep()->size();
+  // This method not available until G4 10.2
+  //const int numSecondaries = aStep->GetNumberOfSecondariesInCurrentStep();
+  if (numSecondaries) {
+      // OK, there was an interation. look at the track, if it
+      // is not a secondary (i.e. we have a connected tree) we
+      // apply the MC truth machinery...
+      FaserTrackHelper tHelper(aStep->GetTrack());
+      if (!tHelper.IsSecondary())
+        {
+          FaserTruthStrategyManager* sManager =
+            FaserTruthStrategyManager::GetStrategyManager();
+          sManager->CreateTruthIncident(aStep, m_subDetVolLevel);
+        }
+    }
+
+  // Call the base class
+  G4Trajectory::AppendStep(aStep);
+}
+
+#if G4VERSION_NUMBER < 1010
+void FaserTrajectory::DrawTrajectory(G4int i_mode=0) const
+#else
+void FaserTrajectory::DrawTrajectory(G4int i_mode) const
+#endif
+{
+  // If i_mode>=0, draws a trajectory as a polyline (blue for
+  // positive, red for negative, green for neutral) and, if i_mode!=0,
+  // adds markers - yellow circles for step points and magenta squares
+  // for auxiliary points, if any - whose screen size in pixels is
+  // given by abs(i_mode)/1000.  E.g: i_mode = 5000 gives easily
+  // visible markers.
+
+  G4VVisManager* pVVisManager = G4VVisManager::GetConcreteInstance();
+  if (!pVVisManager) return;
+
+  const G4double markerSize = abs(i_mode)*0.001;
+  G4bool lineRequired (i_mode >= 0);
+  G4bool markersRequired (markerSize > 0.);
+
+  G4Polyline trajectoryLine;
+  G4Polymarker stepPoints;
+  G4Polymarker auxiliaryPoints;
+
+  for (G4int i = 0; i < GetPointEntries() ; i++)
+    {
+      G4VTrajectoryPoint* aTrajectoryPoint = GetPoint(i);
+      const std::vector<G4ThreeVector>* auxiliaries
+        = aTrajectoryPoint->GetAuxiliaryPoints();
+      if (auxiliaries)
+        {
+          for (size_t iAux = 0; iAux < auxiliaries->size(); ++iAux)
+            {
+              const G4ThreeVector pos((*auxiliaries)[iAux]);
+              if (lineRequired)
+                {
+                  trajectoryLine.push_back(pos);
+                }
+              if (markersRequired)
+                {
+                  auxiliaryPoints.push_back(pos);
+                }
+            }
+        }
+      const G4ThreeVector pos(aTrajectoryPoint->GetPosition());
+      if (lineRequired)
+        {
+          trajectoryLine.push_back(pos);
+        }
+      if (markersRequired)
+        {
+          stepPoints.push_back(pos);
+        }
+    }
+
+  if (lineRequired)
+    {
+      int visScheme=FaserTruthController::getTruthController()->
+        getVisualizationHelper()->trackVisualizationScheme();
+      G4Colour colour;
+      const G4double charge = GetCharge();
+      if (visScheme==1)
+        {
+          // Geant3-like color code - neutrals are dashed
+          const G4String pname=GetParticleName();
+          if (pname=="e+" || pname=="e-") colour = G4Colour(1.,1.,0.);
+          else if (pname=="mu+" || pname=="mu-") colour = G4Colour(0.,1.,0.);
+          else if (pname=="gamma") colour = G4Colour(0.,0.,1.);
+          else if (pname=="neutron") colour = G4Colour(0.,0.,0.);
+          else if (charge) colour = G4Colour(1.,0.,0.);
+        }
+      else if (visScheme==2)
+        {
+          if(charge>0.)      colour = G4Colour(0.,0.,1.); // Blue = positive.
+          else if(charge<0.) colour = G4Colour(1.,0.,0.); // Red = negative.
+          else               colour = G4Colour(0.,1.,0.); // Green = neutral.
+        }
+      else if (visScheme==3)
+        {
+          const G4String pname=GetParticleName();
+          if (pname=="e+" || pname=="e-") colour = G4Colour(1.,1.,0.);
+          else if (pname=="mu+" || pname=="mu-") colour = G4Colour(0.,0.,1.);
+          else if (pname=="gamma") colour = G4Colour(60./256.,79./256.,113./256.);
+          else if (pname=="neutron") colour = G4Colour(1.,1.,1.);
+          else if (pname=="pi-"|| pname=="pi+")
+            colour = G4Colour(250/256.,128/256.,114/256.);
+          else colour = G4Colour(176/256.,48/256.,96/256.);
+        }
+      G4VisAttributes trajectoryLineAttribs(colour);
+      if(visScheme==1 && charge==0)
+        {
+          G4VisAttributes::LineStyle style=G4VisAttributes::dotted;
+          trajectoryLineAttribs.SetLineStyle(style);
+        }
+      trajectoryLine.SetVisAttributes(&trajectoryLineAttribs);
+      pVVisManager->Draw(trajectoryLine);
+    }
+  if (markersRequired)
+    {
+      auxiliaryPoints.SetMarkerType(G4Polymarker::squares);
+      auxiliaryPoints.SetScreenSize(markerSize);
+      auxiliaryPoints.SetFillStyle(G4VMarker::filled);
+      G4VisAttributes auxiliaryPointsAttribs(G4Colour(0.,1.,1.));  // Magenta
+      auxiliaryPoints.SetVisAttributes(&auxiliaryPointsAttribs);
+      pVVisManager->Draw(auxiliaryPoints);
+
+      stepPoints.SetMarkerType(G4Polymarker::circles);
+      stepPoints.SetScreenSize(markerSize);
+      stepPoints.SetFillStyle(G4VMarker::filled);
+      G4VisAttributes stepPointsAttribs(G4Colour(1.,1.,0.));  // Yellow.
+      stepPoints.SetVisAttributes(&stepPointsAttribs);
+      pVVisManager->Draw(stepPoints);
+    }
+}
diff --git a/Simulation/G4Sim/FaserMCTruthBase/src/FaserTruthStrategyManager.cxx b/Simulation/G4Sim/FaserMCTruthBase/src/FaserTruthStrategyManager.cxx
new file mode 100644
index 00000000..d81de897
--- /dev/null
+++ b/Simulation/G4Sim/FaserMCTruthBase/src/FaserTruthStrategyManager.cxx
@@ -0,0 +1,60 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// class header
+#include "FaserMCTruthBase/FaserTruthStrategyManager.h"
+
+// Framework includes
+#include "AthenaBaseComps/AthMsgStreamMacros.h"
+
+// Geant4 Includes
+#include "G4Event.hh"
+#include "G4EventManager.hh"
+#include "G4PhysicalVolumeStore.hh"
+#include "G4Step.hh"
+#include "G4TransportationManager.hh"
+#include "G4VPhysicalVolume.hh"
+#include "G4VSolid.hh"
+
+// Truth-related includes
+#include "FaserMCTruth/FaserEventInformation.h"
+// #include "FaserMCTruth/FaserTrackHelper.h"
+
+// ISF includes
+#include "FaserISF_Interfaces/IFaserTruthSvc.h"
+#include "FaserISF_Event/FaserISFParticle.h"
+
+// DetectorDescription
+#include "FaserDetDescr/FaserRegionHelper.h"
+#include "FaserISF_Geant4Event/FaserGeant4TruthIncident.h"
+#include "FaserISF_Geant4Event/FaserISFG4GeoHelper.h"
+
+FaserTruthStrategyManager::FaserTruthStrategyManager()
+  : m_truthSvc(nullptr)
+{
+}
+
+FaserTruthStrategyManager* FaserTruthStrategyManager::GetStrategyManager()
+{
+  static FaserTruthStrategyManager theMgr;
+  return &theMgr;
+}
+
+void FaserTruthStrategyManager::SetISFTruthSvc(ISF::IFaserTruthSvc *truthSvc)
+{
+  m_truthSvc = truthSvc;
+}
+
+bool FaserTruthStrategyManager::CreateTruthIncident(const G4Step* aStep, int subDetVolLevel) const
+{
+  FaserDetDescr::FaserRegion geoID = iGeant4::FaserISFG4GeoHelper::nextGeoId(aStep, subDetVolLevel);
+
+  auto* eventInfo = static_cast<FaserEventInformation*> (G4EventManager::GetEventManager()->GetConstCurrentEvent()->GetUserInformation());
+
+  iGeant4::FaserGeant4TruthIncident truth(aStep, geoID, eventInfo);
+
+  m_truthSvc->registerTruthIncident(truth);
+  return false;
+}
+
diff --git a/Simulation/G4Utilities/G4UserActions/CMakeLists.txt b/Simulation/G4Utilities/G4UserActions/CMakeLists.txt
new file mode 100644
index 00000000..5315f2a3
--- /dev/null
+++ b/Simulation/G4Utilities/G4UserActions/CMakeLists.txt
@@ -0,0 +1,46 @@
+################################################################################
+# Package: G4UserActions
+################################################################################
+
+# Declare the package name:
+atlas_subdir( G4UserActions )
+
+# Declare the package's dependencies:
+atlas_depends_on_subdirs( PUBLIC
+                          PRIVATE
+                          Control/AthenaBaseComps
+                          Control/AthenaKernel
+                          Control/StoreGate
+                          GaudiKernel
+                          Simulation/G4Atlas/G4AtlasInterfaces
+                          Simulation/G4Atlas/G4AtlasTools
+                          Simulation/G4Sim/TrackRecord
+                          Event/EventInfo
+                          Tracker/TrackerSimEvent
+                          Scintillator/ScintSimEvent
+                          Simulation/G4Sim/FaserMCTruth
+                          Simulation/G4Sim/FaserMCTruthBase
+                          Simulation/G4Sim/SimHelpers
+                          Simulation/G4Utilities/TrackWriteFastSim
+                          Simulation/G4Utilities/G4DebuggingTools
+                          Tools/PathResolver )
+
+# External dependencies:
+find_package( CLHEP )
+find_package( Geant4 )
+find_package( ROOT COMPONENTS Core Tree MathCore Hist RIO pthread )
+find_package( TBB )
+find_package( XercesC )
+
+# Component(s) in the package:
+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)
+
+
+# Install files from the package:
+atlas_install_python_modules( python/*.py )
+atlas_install_joboptions( share/*.py )
+atlas_install_runtime( share/*.dat )
diff --git a/Simulation/G4Utilities/G4UserActions/python/G4UserActionsConfDb.py b/Simulation/G4Utilities/G4UserActions/python/G4UserActionsConfDb.py
new file mode 100644
index 00000000..de656087
--- /dev/null
+++ b/Simulation/G4Utilities/G4UserActions/python/G4UserActionsConfDb.py
@@ -0,0 +1,32 @@
+# Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+
+from AthenaCommon.CfgGetter import addTool
+
+# New tools for multi-threading
+addTool("G4UserActions.G4UserActionsConfig.getAthenaTrackingActionTool", "G4UA::AthenaTrackingActionTool")
+addTool("G4UserActions.G4UserActionsConfig.getAthenaStackingActionTool", "G4UA::AthenaStackingActionTool")
+
+# addTool("G4UserActions.G4UserActionsConf.G4UA__G4SimTimerTool", "G4UA::G4SimTimerTool")
+# addTool("G4UserActions.G4UserActionsConf.G4UA__CosmicPerigeeActionTool", "G4UA::CosmicPerigeeActionTool")
+# addTool("G4UserActions.G4UserActionsConf.G4UA__G4TrackCounterTool", "G4UA::G4TrackCounterTool")
+# addTool("G4UserActions.G4UserActionsConf.G4UA__LengthIntegratorTool", "G4UA::LengthIntegratorTool")
+# addTool("G4UserActions.G4UserActionsConf.G4UA__PhotonKillerTool", "G4UA::PhotonKillerTool")
+
+# addTool("G4UserActions.G4UserActionsConfig.getFastIDKillerTool", "G4UA::FastIDKillerTool")
+# addTool("G4UserActions.G4UserActionsConfig.getFastMBKillerTool", "G4UA::FastMBKillerTool")
+# addTool("G4UserActions.G4UserActionsConfig.getHitWrapperTool", "G4UA::HitWrapperTool")
+# addTool("G4UserActions.G4UserActionsConfig.getHIPKillerTool", "G4UA::HIPKillerTool")
+# addTool("G4UserActions.G4UserActionsConfig.getHIPLArVolumeAcceptTool", "G4UA::HIPLArVolumeAcceptTool")
+addTool("G4UserActions.G4UserActionsConfig.getLooperKillerTool", "G4UA::LooperKillerTool")
+# addTool("G4UserActions.G4UserActionsConfig.getMonopoleLooperKillerTool", "G4UA::MonopoleLooperKillerTool")
+# addTool("G4UserActions.G4UserActionsConfig.getLooperKillerEventOverlayTool", "G4UA::LooperKillerEventOverlayTool")
+# addTool("G4UserActions.G4UserActionsConfig.getMomentumConservationTool", "G4UA::MomentumConservationTool")
+# addTool("G4UserActions.G4UserActionsConfig.getScoringVolumeTrackKillerTool", "G4UA::ScoringVolumeTrackKillerTool")
+
+# addTool("G4UserActions.G4UserActionsConfig.getFluxRecorderTool", "G4UA::FluxRecorderTool")
+# addTool("G4UserActions.G4UserActionsConfig.getScoringPlaneTool", "G4UA::ScoringPlaneTool")
+# addTool("G4UserActions.G4UserActionsConfig.getRadiationMapsMakerTool", "G4UA::RadiationMapsMakerTool")
+# addTool("G4UserActions.G4UserActionsConfig.getStoppedParticleActionTool", "G4UA::StoppedParticleActionTool")
+# addTool("G4UserActions.G4UserActionsConfig.getRadLengthActionTool", "G4UA::RadLengthActionTool")
+# addTool("G4UserActions.G4UserActionsConfig.getLooperThresholdSetTool", "G4UA::LooperThresholdSetTool")
+# addTool("G4UserActions.G4UserActionsConfig.getVolumeDumperTool", "G4UA::VolumeDumperTool")
diff --git a/Simulation/G4Utilities/G4UserActions/python/G4UserActionsConfigNew.py b/Simulation/G4Utilities/G4UserActions/python/G4UserActionsConfigNew.py
new file mode 100644
index 00000000..bd282bbd
--- /dev/null
+++ b/Simulation/G4Utilities/G4UserActions/python/G4UserActionsConfigNew.py
@@ -0,0 +1,53 @@
+# Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+
+from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator
+from G4UserActions.G4UserActionsConf import G4UA__AthenaStackingActionTool, G4UA__AthenaTrackingActionTool
+
+# this is a bit cumbersome, but it seems ike it is a lot easier to separate
+# the getter functionality from all the rest (i.e. adding the action).
+# This way, e.g., after the getter is called the tool is automatically added
+# to the ToolSvc and can be assigned to a ToolHandle by the add function.
+# Also, passing arguments to the getter (like "this is a system action") is not straightforward
+
+def AthenaStackingActionToolCfg(ConfigFlags, name='G4UA::AthenaStackingActionTool', **kwargs):
+
+    result = ComponentAccumulator()
+    ## Killing neutrinos
+    if "FASER" in ConfigFlags.Sim.Layout:
+        kwargs.setdefault('KillAllNeutrinos',  True)
+    ## Neutron Russian Roulette
+    #need to check if it exists?
+    #if ConfigFlags.hasFlag('Sim.NRRThreshold') and ConfigFlags.hasFlag('Sim.NRRWeight'):
+    # if ConfigFlags.Sim.NRRThreshold and ConfigFlags.Sim.NRRWeight:
+    #     if ConfigFlags.Sim.CalibrationRun:
+    #         raise NotImplementedError("Neutron Russian Roulette should not be used in Calibration Runs.")
+    #     kwargs.setdefault('NRRThreshold',  ConfigFlags.Sim.NRRThreshold)
+    #     kwargs.setdefault('NRRWeight',  ConfigFlags.Sim.NRRWeight)
+    # ## Photon Russian Roulette
+    # if ConfigFlags.Sim.PRRThreshold and ConfigFlags.Sim.PRRWeight:
+    #     if ConfigFlags.Sim.CalibrationRun:
+    #         raise NotImplementedError("Photon Russian Roulette should not be used in Calibration Runs.")
+    #     kwargs.setdefault('PRRThreshold',  ConfigFlags.Sim.PRRThreshold)
+    #     kwargs.setdefault('PRRWeight',  ConfigFlags.Sim.PRRWeight)
+    kwargs.setdefault('IsISFJob', ConfigFlags.Sim.ISFRun)
+
+    result.setPrivateTools( G4UA__AthenaStackingActionTool(name,**kwargs) )
+    return result
+
+
+def AthenaTrackingActionToolCfg(ConfigFlags, name='G4UA::AthenaTrackingActionTool', **kwargs):
+    result = ComponentAccumulator()
+    kwargs.setdefault('SecondarySavingLevel', 2)
+    
+    #
+    # subDetLevel will need to be increased to 2 if the cavern infrastructure is simulated
+    # (adding another layer of volumes between Faser and subdetectors)
+    #
+    subDetLevel=1
+    # if "ATLAS" in ConfigFlags.Sim.Layout and \
+    # (ConfigFlags.Beam.Type == 'cosmics' or ConfigFlags.Sim.CavernBG != 'Signal' ):
+    #     subDetLevel=2
+
+    kwargs.setdefault('SubDetVolumeLevel', subDetLevel)
+    result.setPrivateTools( G4UA__AthenaTrackingActionTool(name,**kwargs) )
+    return result
diff --git a/Simulation/G4Utilities/G4UserActions/src/AthenaDebugStackingAction.cxx b/Simulation/G4Utilities/G4UserActions/src/AthenaDebugStackingAction.cxx
new file mode 100644
index 00000000..237e6208
--- /dev/null
+++ b/Simulation/G4Utilities/G4UserActions/src/AthenaDebugStackingAction.cxx
@@ -0,0 +1,146 @@
+/*
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+*/
+
+// System includes
+#include <iostream>
+#include <memory>
+#include <string>
+
+// Local includes
+#include "AthenaDebugStackingAction.h"
+
+// Truth includes
+#include "FaserMCTruth/FaserPrimaryParticleInformation.h"
+#include "FaserMCTruth/FaserTrackInformation.h"
+#include "FaserMCTruth/FaserTrackBarcodeInfo.h"
+#include "FaserMCTruth/FaserEventInformation.h"
+
+// Geant4 includes
+#include "G4Track.hh"
+#include "G4Event.hh"
+#include "G4EventManager.hh"
+
+
+namespace G4UA
+{
+
+  //---------------------------------------------------------------------------
+  // Constructor
+  //---------------------------------------------------------------------------
+  AthenaDebugStackingAction::AthenaDebugStackingAction(const Config& config):
+    AthenaStackingAction(config) {}
+
+  //---------------------------------------------------------------------------
+  // Classify a new track
+  //---------------------------------------------------------------------------
+  G4ClassificationOfNewTrack
+  AthenaDebugStackingAction::ClassifyNewTrack(const G4Track* track)
+  {
+    // Kill neutrinos if enabled
+    if(m_config.killAllNeutrinos && isNeutrino(track)) {
+      return fKill;
+    }
+
+    // Kill super-low-E photons
+    const double safeCut = 0.00005;
+    double totalE = track->GetTotalEnergy();
+    if(isGamma(track) && totalE < safeCut) {
+      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());
+
+    // Was track subject to a RR?
+    // bool rouletted = false;
+
+    // // Neutron Russian Roulette
+    // if (m_config.russianRouletteNeutronThreshold > 0 && isNeutron(track) &&
+    //     track->GetWeight() < m_config.russianRouletteNeutronWeight && // do not re-Roulette particles
+    //     track->GetKineticEnergy() < m_config.russianRouletteNeutronThreshold) {
+    //   // shoot random number
+    //   if ( CLHEP::RandFlat::shoot() > m_oneOverWeightNeutron ) {
+    //     if (m_config.applyNRR) {
+    //       // Kill (w-1)/w neutrons
+    //       return fKill;
+    //     } else {
+    //       // process them at the end of the stack
+    //       return fWaiting;
+    //     }
+    //   }
+    //   rouletted = true;
+    //   // Weight the rest 1/w neutrons with a weight of w
+    //   if (m_config.applyNRR) {
+    //     mutableTrack->SetWeight(m_config.russianRouletteNeutronWeight);
+    //   }
+    // }
+
+    // // Photon Russian Roulette
+    // if (m_config.russianRoulettePhotonThreshold > 0 && isGamma(track) && track->GetOriginTouchable() &&
+    //     track->GetOriginTouchable()->GetVolume()->GetName().substr(0, 3) == "LAr" && // only for photons created in LAr
+    //     track->GetWeight() < m_config.russianRoulettePhotonWeight && // do not re-Roulette particles
+    //     track->GetKineticEnergy() < m_config.russianRoulettePhotonThreshold) {
+    //   // shoot random number
+    //   if ( CLHEP::RandFlat::shoot() > m_oneOverWeightPhoton ) {
+    //     if (m_config.applyPRR) {
+    //       // Kill (w-1)/w photons
+    //       return fKill;
+    //     } else {
+    //       // process them at the end of the stack
+    //       return fWaiting;
+    //     }
+    //   }
+    //   rouletted = true;
+    //   // Weight the rest 1/w neutrons with a weight of w
+    //   if (m_config.applyPRR) {
+    //     mutableTrack->SetWeight(m_config.russianRoulettePhotonWeight);
+    //   }
+    // }
+
+    // Handle primary particles
+    if(track->GetParentID() == 0) { // Condition for Primaries
+      // Extract the PrimaryParticleInformation
+      FaserPrimaryParticleInformation* ppi = this->getPrimaryParticleInformation(track);
+      // Fill some information for this track
+      if(ppi) {
+        if (!m_config.isISFJob) {
+          // don't do anything
+          const HepMC::GenParticle* 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
+          }
+          // What does this condition mean?
+          else if(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
+          }
+        } // no ISFParticle attached
+      } // has PrimaryParticleInformation
+    }
+    // Secondary track; decide whether to save or kill
+    else if( isGamma(track) &&
+             m_config.photonEnergyCut > 0 &&
+             totalE < m_config.photonEnergyCut )
+      {
+        return fKill;
+      }
+    // Put rouletted tracks at the end of the stack
+    // if (rouletted)
+    //   return fWaiting;
+    // else
+      return fUrgent;
+  }
+
+} // namespace G4UA
diff --git a/Simulation/G4Utilities/G4UserActions/src/AthenaDebugStackingAction.h b/Simulation/G4Utilities/G4UserActions/src/AthenaDebugStackingAction.h
new file mode 100644
index 00000000..ad6f2928
--- /dev/null
+++ b/Simulation/G4Utilities/G4UserActions/src/AthenaDebugStackingAction.h
@@ -0,0 +1,41 @@
+/*
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef G4ATLASALG_ATHENADEBUGSTACKINGACTION_H
+#define G4ATLASALG_ATHENADEBUGSTACKINGACTION_H
+
+// Base class
+#include "AthenaStackingAction.h"
+
+
+namespace G4UA
+{
+
+  /// @class AthenaDebugStackingAction
+  /// @brief Debug version of the AthenaStackingAction
+  /// used for validation of Russian Roulette algorimts.
+  /// It can ensure that there is no randomization in
+  /// simulation caused by turning the Russian Roulette
+  /// on or off.
+  ///
+  /// @author Miha Muskinja <Miha.Muskinja@cern.ch>
+  ///
+  class AthenaDebugStackingAction : public AthenaStackingAction
+  {
+
+    public:
+
+      /// Constructor with configuration
+      AthenaDebugStackingAction(const Config& config);
+
+      /// @brief Classify a new track.
+      /// Result can be fUrgent, fWaiting, fPostpone, or fKill.
+      virtual G4ClassificationOfNewTrack
+      ClassifyNewTrack(const G4Track* track) override final;
+
+  }; // class AthenaDebugStackingAction
+
+} // namespace G4UA
+
+#endif
diff --git a/Simulation/G4Utilities/G4UserActions/src/AthenaStackingAction.cxx b/Simulation/G4Utilities/G4UserActions/src/AthenaStackingAction.cxx
new file mode 100644
index 00000000..92cc340d
--- /dev/null
+++ b/Simulation/G4Utilities/G4UserActions/src/AthenaStackingAction.cxx
@@ -0,0 +1,183 @@
+/*
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+*/
+
+// System includes
+#include <iostream>
+#include <memory>
+#include <string>
+
+// Local includes
+#include "AthenaStackingAction.h"
+
+// Truth includes
+#include "FaserMCTruth/FaserPrimaryParticleInformation.h"
+#include "FaserMCTruth/FaserTrackInformation.h"
+#include "FaserMCTruth/FaserTrackBarcodeInfo.h"
+#include "FaserMCTruth/FaserEventInformation.h"
+
+// Geant4 includes
+#include "G4Track.hh"
+#include "G4Event.hh"
+#include "G4EventManager.hh"
+#include "G4NeutrinoE.hh"
+#include "G4NeutrinoMu.hh"
+#include "G4NeutrinoTau.hh"
+#include "G4AntiNeutrinoE.hh"
+#include "G4AntiNeutrinoMu.hh"
+#include "G4AntiNeutrinoTau.hh"
+#include "G4Gamma.hh"
+#include "G4Neutron.hh"
+
+
+namespace G4UA
+{
+
+  //---------------------------------------------------------------------------
+  // Constructor
+  //---------------------------------------------------------------------------
+  AthenaStackingAction::AthenaStackingAction(const Config& config):
+    m_config(config) //,
+    // m_oneOverWeightNeutron(0),
+    // m_oneOverWeightPhoton(0)
+  {
+    // calculate this division only once
+    // if (m_config.applyNRR)
+    //   m_oneOverWeightNeutron = 1./m_config.russianRouletteNeutronWeight;
+
+    // // calculate this division only once
+    // if (m_config.applyPRR)
+    //   m_oneOverWeightPhoton = 1./m_config.russianRoulettePhotonWeight;
+  }
+
+  //---------------------------------------------------------------------------
+  // Classify a new track
+  //---------------------------------------------------------------------------
+  G4ClassificationOfNewTrack
+  AthenaStackingAction::ClassifyNewTrack(const G4Track* track)
+  {
+    // Kill neutrinos if enabled
+    if(m_config.killAllNeutrinos && isNeutrino(track)) {
+      return fKill;
+    }
+
+    // Kill super-low-E photons
+    const double safeCut = 0.00005;
+    double totalE = track->GetTotalEnergy();
+    if(isGamma(track) && totalE < safeCut) {
+      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());
+
+    // Neutron Russian Roulette
+    // if (m_config.applyNRR && isNeutron(track) &&
+    //     track->GetWeight() < m_config.russianRouletteNeutronWeight && // do not re-Roulette particles
+    //     track->GetKineticEnergy() < m_config.russianRouletteNeutronThreshold) {
+    //   // shoot random number
+    //   if ( CLHEP::RandFlat::shoot() > m_oneOverWeightNeutron ) {
+    //     // Kill (w-1)/w neutrons
+    //     return fKill;
+    //   }
+    //   // Weight the rest 1/w neutrons with a weight of w
+    //   mutableTrack->SetWeight(m_config.russianRouletteNeutronWeight);
+    // }
+
+    // // Photon Russian Roulette
+    // if (m_config.applyPRR && isGamma(track) && track->GetOriginTouchable() &&
+    //     track->GetOriginTouchable()->GetVolume()->GetName().substr(0, 3) == "LAr" && // only for photons created in LAr
+    //     track->GetWeight() < m_config.russianRoulettePhotonWeight && // do not re-Roulette particles
+    //     track->GetKineticEnergy() < m_config.russianRoulettePhotonThreshold) {
+    //   // shoot random number
+    //   if ( CLHEP::RandFlat::shoot() > m_oneOverWeightPhoton ) {
+    //     // Kill (w-1)/w photons
+    //     return fKill;
+    //   }
+    //   // Weight the rest 1/w neutrons with a weight of w
+    //   mutableTrack->SetWeight(m_config.russianRoulettePhotonWeight);
+    // }
+
+    // Handle primary particles
+    if(track->GetParentID() == 0) { // Condition for Primaries
+      // Extract the PrimaryParticleInformation
+      FaserPrimaryParticleInformation* ppi = this->getPrimaryParticleInformation(track);
+      // Fill some information for this track
+      if(ppi) {
+        if (!m_config.isISFJob) {
+          // don't do anything
+          const HepMC::GenParticle* 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
+          }
+          // What does this condition mean?
+          else if(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
+          }
+        } // no ISFParticle attached
+      } // has PrimaryParticleInformation
+    }
+    // Secondary track; decide whether to save or kill
+    else if( isGamma(track) &&
+             m_config.photonEnergyCut > 0 &&
+             totalE < m_config.photonEnergyCut )
+      {
+        return fKill;
+      }
+    return fUrgent;
+  }
+
+  FaserPrimaryParticleInformation* AthenaStackingAction::getPrimaryParticleInformation(const G4Track *track) const
+  {
+    const G4DynamicParticle* dp = track->GetDynamicParticle();
+    if(dp) {
+      const G4PrimaryParticle* pp = nullptr;
+      pp = dp->GetPrimaryParticle();
+      if(pp) {
+        // Extract the PrimaryParticleInformation
+        return dynamic_cast<FaserPrimaryParticleInformation*>
+          ( pp->GetUserInformation() );
+      }
+    }
+    return nullptr;
+  }
+
+  //---------------------------------------------------------------------------
+  // Identify track definition
+  //---------------------------------------------------------------------------
+  bool AthenaStackingAction::isNeutrino(const G4Track* track) const
+  {
+    auto particleDef = track->GetParticleDefinition();
+    return (particleDef == G4NeutrinoE::NeutrinoEDefinition()           ||
+            particleDef == G4AntiNeutrinoE::AntiNeutrinoEDefinition()   ||
+            particleDef == G4NeutrinoMu::NeutrinoMuDefinition()         ||
+            particleDef == G4AntiNeutrinoMu::AntiNeutrinoMuDefinition() ||
+            particleDef == G4NeutrinoTau::NeutrinoTauDefinition()       ||
+            particleDef == G4AntiNeutrinoTau::AntiNeutrinoTauDefinition());
+  }
+
+  //---------------------------------------------------------------------------
+  bool AthenaStackingAction::isGamma(const G4Track* track) const
+  {
+    return track->GetParticleDefinition() == G4Gamma::Gamma();
+  }
+
+  //---------------------------------------------------------------------------
+  bool AthenaStackingAction::isNeutron(const G4Track* track) const
+  {
+    return track->GetParticleDefinition() == G4Neutron::Neutron();
+  }
+
+} // namespace G4UA
diff --git a/Simulation/G4Utilities/G4UserActions/src/AthenaStackingAction.h b/Simulation/G4Utilities/G4UserActions/src/AthenaStackingAction.h
new file mode 100644
index 00000000..1ebf19dd
--- /dev/null
+++ b/Simulation/G4Utilities/G4UserActions/src/AthenaStackingAction.h
@@ -0,0 +1,87 @@
+/*
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef G4ATLASALG_ATHENASTACKINGACTION_H
+#define G4ATLASALG_ATHENASTACKINGACTION_H
+
+#include "G4UserStackingAction.hh"
+
+class FaserPrimaryParticleInformation;
+
+namespace G4UA
+{
+
+  /// @class AthenaStackingAction
+  /// @brief Standard ATLAS stacking action functionality.
+  /// Mostly taken from the old AthenaStackingAction implementation, but
+  /// adapted for the new user action design for multi-threading.
+  ///
+  /// @author Steve Farrell <Steven.Farrell@cern.ch>
+  ///
+  class AthenaStackingAction : public G4UserStackingAction
+  {
+
+    public:
+
+      /// Configuration option struct for AthenaStackingAction.
+      struct Config
+      {
+        /// Flag to toggle killing neutrinos at tracking stage
+        bool killAllNeutrinos;
+        /// Photon energy cut
+        double photonEnergyCut;
+        /// Apply the Neutron Russian Roulette
+        // bool applyNRR;
+        // /// Energy threshold for the Neutron Russian Roulette
+        // double russianRouletteNeutronThreshold;
+        // /// Weight for the Neutron Russian Roulette
+        // double russianRouletteNeutronWeight;
+        // /// Apply the Photon Russian Roulette
+        // bool applyPRR;
+        // /// Energy threshold for the Photon Russian Roulette
+        // double russianRoulettePhotonThreshold;
+        // /// Weight for the Photon Russian Roulette
+        // double russianRoulettePhotonWeight;
+        /// Is this an ISF job
+        bool isISFJob;
+      };
+      
+      /// Constructor with configuration
+      AthenaStackingAction(const Config& config);
+
+      /// @brief Classify a new track.
+      /// Result can be fUrgent, fWaiting, fPostpone, or fKill.
+      virtual G4ClassificationOfNewTrack
+      ClassifyNewTrack(const G4Track* track) override;
+
+    protected:
+
+      /// @brief Configuration options
+      Config m_config;
+
+      /// @brief Identify track as a neutrino.
+      /// It might be useful to move this kind of functionality
+      /// into some standalong helper function(s).
+      bool isNeutrino(const G4Track*) const;
+
+      /// @brief Identify track as a photon.
+      bool isGamma(const G4Track*) const;
+
+      /// @brief Identify track as a neutron.
+      bool isNeutron(const G4Track*) const;
+
+      /// @brief obtain the PrimaryParticleInformation from the current G4Track
+      FaserPrimaryParticleInformation* getPrimaryParticleInformation(const G4Track *track) const;
+
+    //   // one over m_config.russianRouletteNeutronWeight
+    //   double m_oneOverWeightNeutron;
+      
+    //   // one over m_config.russianRoulettePhotonWeight
+    //   double m_oneOverWeightPhoton;
+
+  }; // class AthenaStackingAction
+
+} // namespace G4UA
+
+#endif
diff --git a/Simulation/G4Utilities/G4UserActions/src/AthenaStackingActionTool.cxx b/Simulation/G4Utilities/G4UserActions/src/AthenaStackingActionTool.cxx
new file mode 100644
index 00000000..c480699c
--- /dev/null
+++ b/Simulation/G4Utilities/G4UserActions/src/AthenaStackingActionTool.cxx
@@ -0,0 +1,83 @@
+/*
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "AthenaDebugStackingAction.h"
+#include "AthenaStackingActionTool.h"
+
+namespace G4UA
+{
+
+  //---------------------------------------------------------------------------
+  // Constructor
+  //---------------------------------------------------------------------------
+  AthenaStackingActionTool::
+  AthenaStackingActionTool(const std::string& type, const std::string& name,
+                           const IInterface* parent)
+    : UserActionToolBase<AthenaStackingAction>(type, name, parent),
+      m_config { /*killAllNeutrinos*/ false,
+                 /*photonEnergyCut*/ -1.,
+                //  /*applyNRR*/                      false,
+                //  /*russianRouletteNeutronThreshold*/ -1.,
+                //  /*russianRouletteNeutronWeight*/    -1.,
+                //  /*applyPRR*/                      false,
+                //  /*russianRoulettePhotonThreshold*/  -1.,
+                //  /*russianRoulettePhotonWeight*/     -1.,
+                 /*isISFJob*/ false
+      },
+      m_useDebugAction(false)
+  {
+    declareProperty("KillAllNeutrinos", m_config.killAllNeutrinos,
+                    "Toggle killing of all neutrinos");
+    declareProperty("PhotonEnergyCut", m_config.photonEnergyCut,
+                    "Energy threshold for tracking photons");
+    // declareProperty("ApplyNRR", m_config.applyNRR,
+    //                 "Apply the Neutron Russian Roulette");
+    // declareProperty("NRRThreshold", m_config.russianRouletteNeutronThreshold,
+    //                 "Energy threshold for the Neutron Russian Roulette");
+    // declareProperty("NRRWeight", m_config.russianRouletteNeutronWeight,
+    //                 "Weight for the Neutron Russian Roulette");
+    // declareProperty("ApplyPRR", m_config.applyPRR,
+    //                 "Apply the Photon Russian Roulette");
+    // declareProperty("PRRThreshold", m_config.russianRoulettePhotonThreshold,
+    //                 "Energy threshold for the Photon Russian Roulette");
+    // declareProperty("PRRWeight", m_config.russianRoulettePhotonWeight,
+    //                 "Weight for the Photon Russian Roulette");
+    declareProperty("IsISFJob", m_config.isISFJob, "");
+    declareProperty("UseDebugAction", m_useDebugAction);
+  }
+
+  //---------------------------------------------------------------------------
+  // Initialize
+  //---------------------------------------------------------------------------
+  StatusCode AthenaStackingActionTool::initialize()
+  {
+    ATH_MSG_DEBUG( "Initializing " << name() );
+    ATH_MSG_DEBUG( "KillAllNeutrinos: " << m_config.killAllNeutrinos );
+    ATH_MSG_DEBUG( "PhotonEnergyCut: " << m_config.photonEnergyCut );
+    // ATH_MSG_DEBUG( "RussianRouletteNeutronThreshold: " << m_config.russianRouletteNeutronThreshold );
+    // ATH_MSG_DEBUG( "RussianRouletteNeutronWeight: " << m_config.russianRouletteNeutronWeight );
+    // ATH_MSG_DEBUG( "RussianRoulettePhotonThreshold: " << m_config.russianRoulettePhotonThreshold );
+    // ATH_MSG_DEBUG( "RussianRoulettePhotonWeight: " << m_config.russianRoulettePhotonWeight );
+    return StatusCode::SUCCESS;
+  }
+
+  //---------------------------------------------------------------------------
+  // Create the action on request
+  //---------------------------------------------------------------------------
+  std::unique_ptr<AthenaStackingAction>
+  AthenaStackingActionTool::makeAndFillAction(G4AtlasUserActions& actionLists)
+  {
+    ATH_MSG_DEBUG("Creating an AthenaStackingAction");
+    // Create and configure the action plugin.
+    std::unique_ptr<AthenaStackingAction> action{nullptr};
+    if (m_useDebugAction) {
+      action = std::make_unique<AthenaDebugStackingAction>(m_config);
+    } else {
+      action = std::make_unique<AthenaStackingAction>(m_config);
+    }
+    actionLists.stackingActions.push_back( action.get() );
+    return action;
+  }
+
+}
diff --git a/Simulation/G4Utilities/G4UserActions/src/AthenaStackingActionTool.h b/Simulation/G4Utilities/G4UserActions/src/AthenaStackingActionTool.h
new file mode 100644
index 00000000..24a401e8
--- /dev/null
+++ b/Simulation/G4Utilities/G4UserActions/src/AthenaStackingActionTool.h
@@ -0,0 +1,57 @@
+/*
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef G4ATLASALG_ATLASSTACKINGACTIONTOOL_H
+#define G4ATLASALG_ATLASSTACKINGACTIONTOOL_H
+
+// STL includes
+#include <string>
+
+// G4Atlas includes
+#include "G4AtlasInterfaces/IUserActionTool.h"
+#include "G4AtlasTools/UserActionToolBase.h"
+
+// Local includes
+#include "AthenaStackingAction.h"
+
+
+namespace G4UA
+{
+
+  /// @class AthenaStackingActionTool
+  /// @brief Tool which manages the AthenaStackingAction
+  ///
+  /// @author Steve Farrell <Steven.Farrell@cern.ch>
+  ///
+  class AthenaStackingActionTool : public UserActionToolBase<AthenaStackingAction>
+  {
+
+    public:
+
+      /// Standard constructor
+      AthenaStackingActionTool(const std::string& type, const std::string& name,
+                               const IInterface* parent);
+
+      /// Initialize the tool
+      virtual StatusCode initialize() override final;
+
+    protected:
+
+      // Setup the user action for current thread
+      virtual std::unique_ptr<AthenaStackingAction>
+      makeAndFillAction(G4AtlasUserActions& actionLists) override final;
+
+    private:
+
+      /// Configuration parameters
+      AthenaStackingAction::Config m_config;
+
+      /// Use the debug version of the stacking action
+      bool m_useDebugAction;
+
+  }; // class AthenaStackingActionTool
+
+} // namespace G4UA
+
+#endif
diff --git a/Simulation/G4Utilities/G4UserActions/src/AthenaTrackingAction.cxx b/Simulation/G4Utilities/G4UserActions/src/AthenaTrackingAction.cxx
new file mode 100644
index 00000000..41e5f280
--- /dev/null
+++ b/Simulation/G4Utilities/G4UserActions/src/AthenaTrackingAction.cxx
@@ -0,0 +1,92 @@
+/*
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "AthenaTrackingAction.h"
+
+#include <iostream>
+
+#include "G4Event.hh"
+#include "G4EventManager.hh"
+
+#include "FaserMCTruth/FaserEventInformation.h"
+#include "FaserMCTruth/FaserPrimaryParticleInformation.h"
+#include "FaserMCTruth/FaserTrackHelper.h"
+#include "FaserMCTruth/FaserTrackInformation.h"
+#include "FaserMCTruthBase/FaserTrajectory.h"
+#include "AthenaBaseComps/AthMsgStreamMacros.h"
+
+namespace G4UA
+{
+
+  //---------------------------------------------------------------------------
+  // Constructor
+  //---------------------------------------------------------------------------
+  AthenaTrackingAction::AthenaTrackingAction(MSG::Level lvl,
+                                             int secondarySavingLevel, int subDetVolLevel)
+    : m_msg("AthenaTrackingAction")
+    , m_secondarySavingLevel(secondarySavingLevel)
+    , m_subDetVolLevel(subDetVolLevel)
+  {
+    m_msg.get().setLevel(lvl);
+  }
+
+  //---------------------------------------------------------------------------
+  // Pre-tracking action.
+  //---------------------------------------------------------------------------
+  void AthenaTrackingAction::PreUserTrackingAction(const G4Track* track)
+  {
+    ATH_MSG_DEBUG("Starting to track a new particle");
+
+    // Use the TrackHelper code to identify the kind of particle.
+    FaserTrackHelper trackHelper(track);
+
+    // Condition for storing the GenParticle in the EventInformation for later.
+    if (trackHelper.IsPrimary() || trackHelper.IsRegisteredSecondary())
+    {
+      // Why a const_cast???
+      // This is an ugly way to communicate the GenParticle...
+      HepMC::GenParticle* part =
+        const_cast<HepMC::GenParticle*>( trackHelper.GetTrackInformation()->
+                                         GetHepMCParticle() );
+
+      // Assign the GenParticle to the EventInformation.
+      FaserEventInformation* eventInfo = static_cast<FaserEventInformation*>
+        (G4EventManager::GetEventManager()->GetConstCurrentEvent()->GetUserInformation());
+      if (trackHelper.IsPrimary()) eventInfo->SetCurrentPrimary(part);
+      eventInfo->SetCurrentlyTraced(part);
+    }
+
+    // Condition for creating a trajectory object to store truth.
+    if (trackHelper.IsPrimary() ||
+        (trackHelper.IsRegisteredSecondary() && m_secondarySavingLevel>1) ||
+        (trackHelper.IsSecondary() && m_secondarySavingLevel>2))
+    {
+      ATH_MSG_DEBUG("Preparing a FaserTrajectory for saving truth");
+
+      // Create a new AtlasTrajectory for this particle
+      FaserTrajectory* trajectory = new FaserTrajectory(track, m_subDetVolLevel);
+
+      // Assign the trajectory to the tracking manager.
+      // TODO: consider caching the tracking manager once to reduce overhead.
+      auto trkMgr = G4EventManager::GetEventManager()->GetTrackingManager();
+      //trajectory->setTrackingManager(trkMgr);
+      trkMgr->SetStoreTrajectory(true);
+      trkMgr->SetTrajectory(trajectory);
+    }
+  }
+
+  //---------------------------------------------------------------------------
+  // Post-tracking action.
+  //---------------------------------------------------------------------------
+  void AthenaTrackingAction::PostUserTrackingAction(const G4Track* /*track*/)
+  {
+    ATH_MSG_DEBUG("Finished tracking a particle");
+
+    // We are done tracking this particle, so reset the trajectory.
+    // TODO: consider caching the tracking manager once to reduce overhead.
+    G4EventManager::GetEventManager()->GetTrackingManager()->
+      SetStoreTrajectory(false);
+  }
+
+} // namespace G4UA
diff --git a/Simulation/G4Utilities/G4UserActions/src/AthenaTrackingAction.h b/Simulation/G4Utilities/G4UserActions/src/AthenaTrackingAction.h
new file mode 100644
index 00000000..625ca7b3
--- /dev/null
+++ b/Simulation/G4Utilities/G4UserActions/src/AthenaTrackingAction.h
@@ -0,0 +1,54 @@
+/*
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef G4AtlasAlg_AthenaTrackingAction_H
+#define G4AtlasAlg_AthenaTrackingAction_H
+
+#include "AthenaKernel/MsgStreamMember.h"
+
+#include "G4UserTrackingAction.hh"
+
+namespace G4UA
+{
+
+  /// @class AthenaTrackingAction
+  /// @brief User action for pre/post tracking truth handling.
+  ///
+  class AthenaTrackingAction : public G4UserTrackingAction
+  {
+
+    public:
+
+      /// Constructor
+      AthenaTrackingAction(MSG::Level lvl, int secondarySavingLevel, int subDetVolLevel);
+
+      /// @brief Called before tracking a new particle.
+      ///
+      /// If the track meets certain conditions, we save it in the
+      /// EventInformation and possibly construct a new AtlasTrajectory
+      /// which will be used for writing out truth particles later.
+      virtual void PreUserTrackingAction(const G4Track*) override final;
+
+      /// @brief Called after tracking a particle.
+      ///
+      /// Here we reset the AtlasTrajectory if it was created.
+      virtual void PostUserTrackingAction(const G4Track*) override final;
+
+    private:
+
+      /// Log a message using the Athena controlled logging system
+      MsgStream& msg( MSG::Level lvl ) const { return m_msg << lvl; }
+      bool msgLvl( MSG::Level lvl ) const { return m_msg.get().level() <= lvl; }
+      mutable Athena::MsgStreamMember m_msg;
+
+      /// The saving level for secondaries.
+      int m_secondarySavingLevel;
+      /// The level in the G4 volume hierarchy at which can we find the sub-detector name
+      int m_subDetVolLevel;
+
+  }; // class AthenaTrackingAction
+
+} // namespace G4UA
+
+#endif
diff --git a/Simulation/G4Utilities/G4UserActions/src/AthenaTrackingActionTool.cxx b/Simulation/G4Utilities/G4UserActions/src/AthenaTrackingActionTool.cxx
new file mode 100644
index 00000000..5b180590
--- /dev/null
+++ b/Simulation/G4Utilities/G4UserActions/src/AthenaTrackingActionTool.cxx
@@ -0,0 +1,49 @@
+/*
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "AthenaTrackingActionTool.h"
+
+namespace G4UA
+{
+
+  //---------------------------------------------------------------------------
+  // Constructor
+  //---------------------------------------------------------------------------
+  AthenaTrackingActionTool::
+  AthenaTrackingActionTool(const std::string& type, const std::string& name,
+                           const IInterface* parent)
+    : UserActionToolBase<AthenaTrackingAction>(type, name, parent)
+    , m_secondarySavingLevel(2)
+    , m_subDetVolLevel(1)
+  {
+    declareProperty("SecondarySavingLevel", m_secondarySavingLevel,
+      "Three valid options: 1 - Primaries; 2 - StoredSecondaries(default); 3 - All");
+    declareProperty("SubDetVolumeLevel", m_subDetVolLevel,
+      "The level in the G4 volume hierarchy at which can we find the sub-detector name");
+  }
+
+  //---------------------------------------------------------------------------
+  // Initialize - temporarily here for debugging
+  //---------------------------------------------------------------------------
+  StatusCode AthenaTrackingActionTool::initialize()
+  {
+    ATH_MSG_DEBUG( "Initializing " << name() );
+    return StatusCode::SUCCESS;
+  }
+
+  //---------------------------------------------------------------------------
+  // Create the action on request
+  //---------------------------------------------------------------------------
+  std::unique_ptr<AthenaTrackingAction>
+  AthenaTrackingActionTool::makeAndFillAction(G4AtlasUserActions& actionLists)
+  {
+    ATH_MSG_DEBUG("Constructing an AthenaTrackingAction");
+    // Create and configure the action plugin.
+    auto action = std::make_unique<AthenaTrackingAction>(
+        msg().level(), m_secondarySavingLevel, m_subDetVolLevel );
+    actionLists.trackingActions.push_back( action.get() );
+    return action;
+  }
+
+}
diff --git a/Simulation/G4Utilities/G4UserActions/src/AthenaTrackingActionTool.h b/Simulation/G4Utilities/G4UserActions/src/AthenaTrackingActionTool.h
new file mode 100644
index 00000000..7e1c98fc
--- /dev/null
+++ b/Simulation/G4Utilities/G4UserActions/src/AthenaTrackingActionTool.h
@@ -0,0 +1,52 @@
+/*
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef G4AtlasAlg_AthenaTrackingActionTool_H
+#define G4AtlasAlg_AthenaTrackingActionTool_H
+
+// G4Atlas includes
+#include "G4AtlasInterfaces/IUserActionTool.h"
+#include "G4AtlasTools/UserActionToolBase.h"
+
+// Local includes
+#include "AthenaTrackingAction.h"
+
+namespace G4UA
+{
+
+  /// @class AthenaTrackingActionTool
+  /// @brief Tool which manages the AthenaTrackingAction
+  ///
+  /// @author Steve Farrell <Steven.Farrell@cern.ch>
+  ///
+  class AthenaTrackingActionTool : public UserActionToolBase<AthenaTrackingAction>
+  {
+
+    public:
+
+      /// Standard constructor
+      AthenaTrackingActionTool(const std::string& type, const std::string& name,
+                               const IInterface* parent);
+
+      /// Initialize the tool (just for debugging printout)
+      virtual StatusCode initialize() override;
+
+    protected:
+
+      /// Setup the user action for current thread
+      virtual std::unique_ptr<AthenaTrackingAction>
+      makeAndFillAction(G4AtlasUserActions& actionLists) override final;
+
+    private:
+
+      /// The saving level for secondaries.
+      int m_secondarySavingLevel;
+      /// The level in the G4 volume hierarchy at which can we find the sub-detector name
+      int m_subDetVolLevel;
+
+  }; // class AthenaTrackingActionTool
+
+} // namespace G4UA
+
+#endif
diff --git a/Simulation/G4Utilities/G4UserActions/src/LooperKiller.cxx b/Simulation/G4Utilities/G4UserActions/src/LooperKiller.cxx
new file mode 100644
index 00000000..c9bd4a54
--- /dev/null
+++ b/Simulation/G4Utilities/G4UserActions/src/LooperKiller.cxx
@@ -0,0 +1,101 @@
+/*
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "LooperKiller.h"
+#include <iostream>
+#include "G4RunManagerKernel.hh"
+#include "G4TransportationManager.hh"
+#include "G4Navigator.hh"
+#include "G4PropagatorInField.hh"
+#include "G4TrackingManager.hh"
+#include "G4SteppingManager.hh"
+#include "G4StackManager.hh"
+#include "G4EventManager.hh"
+#include "G4Event.hh"
+#include "StoreGate/WriteHandle.h"
+#include "StoreGate/StoreGateSvc.h"
+
+// For setting an error state in event info
+#include "EventInfo/EventInfo.h"
+
+#include "GaudiKernel/Bootstrap.h"
+#include "GaudiKernel/ISvcLocator.h"
+#include "GaudiKernel/IMessageSvc.h"
+
+namespace G4UA
+{
+
+  //---------------------------------------------------------------------------
+  LooperKiller::LooperKiller(const Config& config)
+    : AthMessaging(Gaudi::svcLocator()->service<IMessageSvc>("MessageSvc"),
+                   "LooperKiller"),
+      m_evtStore("StoreGateSvc/StoreGateSvc", "LooperKiller"),
+      m_detStore("StoreGateSvc/DetectorStore", "LooperKiller"),
+      m_config(config), m_report(), m_count_steps(0)
+  {
+  }
+
+  //---------------------------------------------------------------------------
+  void LooperKiller::UserSteppingAction(const G4Step* aStep)
+  {
+
+    if (aStep->GetTrack()->GetCurrentStepNumber() < m_config.MaxSteps) {
+      if (m_count_steps==0) return;
+      // Track recovered...
+      ATH_MSG_WARNING("Track finished on its own.  Congrats.  Moving on with the event.");
+      m_count_steps = 0;
+      G4TransportationManager *tm = G4TransportationManager::GetTransportationManager();
+      tm->GetNavigatorForTracking()->SetVerboseLevel(0);
+      tm->GetPropagatorInField()->SetVerboseLevel(0);
+      G4RunManagerKernel *rmk = G4RunManagerKernel::GetRunManagerKernel();
+      rmk->GetTrackingManager()->SetVerboseLevel(0);
+      rmk->GetTrackingManager()->GetSteppingManager()->SetVerboseLevel(0);
+      rmk->GetStackManager()->SetVerboseLevel(0);
+      return;
+    } else if (aStep->GetTrack()->GetCurrentStepNumber() == m_config.MaxSteps) {
+      ATH_MSG_WARNING("LooperKiller triggered!! Hold on to your hats!!!!!!!!" );
+    }
+
+    G4TransportationManager *tm = G4TransportationManager::GetTransportationManager();
+    tm->GetNavigatorForTracking()->SetVerboseLevel(m_config.VerboseLevel);
+    tm->GetPropagatorInField()->SetVerboseLevel(m_config.VerboseLevel);
+
+    G4RunManagerKernel *rmk = G4RunManagerKernel::GetRunManagerKernel();
+    rmk->GetTrackingManager()->SetVerboseLevel(m_config.VerboseLevel);
+    rmk->GetTrackingManager()->GetSteppingManager()->SetVerboseLevel(m_config.VerboseLevel);
+    rmk->GetStackManager()->SetVerboseLevel(m_config.VerboseLevel);
+
+    m_count_steps++;
+
+    if (m_count_steps>m_config.PrintSteps) {
+      m_count_steps = 0;
+      m_report.killed_tracks++;
+      aStep->GetTrack()->SetTrackStatus(fStopAndKill);
+      tm->GetNavigatorForTracking()->SetVerboseLevel(0);
+      tm->GetPropagatorInField()->SetVerboseLevel(0);
+      rmk->GetTrackingManager()->SetVerboseLevel(0);
+      rmk->GetTrackingManager()->GetSteppingManager()->SetVerboseLevel(0);
+      rmk->GetStackManager()->SetVerboseLevel(0);
+
+      // Bail out...
+      if (m_config.AbortEvent){
+	rmk->GetEventManager()->AbortCurrentEvent();
+	rmk->GetEventManager()->GetNonconstCurrentEvent()->SetEventAborted();
+      }
+      if (m_config.SetError){
+	
+	// Set error state in eventInfo
+	SG::WriteHandle<EventInfo> eic("McEventInfo");
+	if (! eic.isValid()){
+	  ATH_MSG_WARNING( "Failed to retrieve EventInfo" );
+	} else {
+	  eic->setErrorState(EventInfo::Core,EventInfo::Error);
+	  ATH_MSG_WARNING( "Set error state in event info!" );
+	}
+	
+      } // End of set error
+    } // End of handling end of error time
+  }
+
+} // namespace G4UA
diff --git a/Simulation/G4Utilities/G4UserActions/src/LooperKiller.h b/Simulation/G4Utilities/G4UserActions/src/LooperKiller.h
new file mode 100644
index 00000000..6463cf8b
--- /dev/null
+++ b/Simulation/G4Utilities/G4UserActions/src/LooperKiller.h
@@ -0,0 +1,69 @@
+/*
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef G4USERACTIONS_G4UA_LOOPERKILLER_H
+#define G4USERACTIONS_G4UA_LOOPERKILLER_H
+
+#include "GaudiKernel/ServiceHandle.h"
+
+// Infrastructure includes
+#include "AthenaKernel/MsgStreamMember.h"
+#include "G4UserSteppingAction.hh"
+#include "AthenaBaseComps/AthMessaging.h"
+
+class StoreGateSvc;
+
+namespace G4UA
+{
+
+  /// @class LooperKiller
+  /// @brief A user action to kill looping tracks.
+  ///
+  class LooperKiller final : public G4UserSteppingAction, public AthMessaging
+  {
+
+    public:
+
+      struct Config
+      {
+        int MaxSteps=1000000;
+        int PrintSteps=100;
+        int VerboseLevel=1;
+        bool AbortEvent=true;
+        bool SetError=false;
+      };
+
+      struct Report
+      {
+        long killed_tracks=0;
+        void merge(const Report& rep){
+          killed_tracks+=rep.killed_tracks;
+        }
+      };
+
+      LooperKiller(const Config& config);
+
+      virtual void UserSteppingAction(const G4Step*) override;
+      /// Retrieve  results
+      const Report& getReport() const
+      { return m_report; }
+
+    private:
+
+      typedef ServiceHandle<StoreGateSvc> StoreGateSvc_t;
+      /// Pointer to StoreGate (event store by default)
+      mutable StoreGateSvc_t m_evtStore;
+      /// Pointer to StoreGate (detector store by default)
+      mutable StoreGateSvc_t m_detStore;
+
+      /// My configuration options
+      Config m_config;
+      Report m_report;
+      int m_count_steps;
+
+  }; // class LooperKiller
+
+}
+
+#endif
diff --git a/Simulation/G4Utilities/G4UserActions/src/LooperKillerTool.cxx b/Simulation/G4Utilities/G4UserActions/src/LooperKillerTool.cxx
new file mode 100644
index 00000000..09c58339
--- /dev/null
+++ b/Simulation/G4Utilities/G4UserActions/src/LooperKillerTool.cxx
@@ -0,0 +1,65 @@
+/*
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "LooperKillerTool.h"
+
+namespace G4UA
+{
+
+  //---------------------------------------------------------------------------
+  // Constructor
+  //---------------------------------------------------------------------------
+  LooperKillerTool::LooperKillerTool(const std::string& type, const std::string& name,
+                                 const IInterface* parent)
+    : UserActionToolBase<LooperKiller>(type, name, parent)
+  {
+    declareProperty("MaxSteps", m_config.MaxSteps);
+    declareProperty("PrintSteps",m_config.PrintSteps);
+    declareProperty("VerboseLevel", m_config.VerboseLevel);
+    declareProperty("AbortEvent", m_config.AbortEvent);
+    declareProperty("SetError", m_config.SetError);
+  }
+
+  //---------------------------------------------------------------------------
+  // Initialize - temporarily here for debugging
+  //---------------------------------------------------------------------------
+  StatusCode LooperKillerTool::initialize()
+  {
+    ATH_MSG_DEBUG("initialize");
+    return StatusCode::SUCCESS;
+  }
+
+  StatusCode LooperKillerTool::finalize()
+  {
+    ATH_MSG_DEBUG("finalize");
+
+    // Accumulate the results across threads
+    LooperKiller::Report report;
+    m_actions.accumulate(report, &LooperKiller::getReport,
+                         &LooperKiller::Report::merge);
+
+    ATH_MSG_INFO( "******* Report from "<< name()<< " *******");
+    ATH_MSG_INFO(" Set to kill tracks over " << m_config.MaxSteps << " steps");
+    ATH_MSG_INFO(" and give " << m_config.PrintSteps << " steps of verbose output");
+    ATH_MSG_INFO(" We killed " << report.killed_tracks << " tracks this run.");
+    ATH_MSG_INFO(" Was set to " << (m_config.AbortEvent?"":"not ") << "abort events and ");
+    ATH_MSG_INFO( (m_config.SetError?"":"not ") << "set an error state." );
+
+    return StatusCode::SUCCESS;
+  }
+
+
+  //---------------------------------------------------------------------------
+  // Create the action on request
+  //---------------------------------------------------------------------------
+  std::unique_ptr<LooperKiller>
+  LooperKillerTool::makeAndFillAction(G4AtlasUserActions& actionList)
+  {
+    ATH_MSG_DEBUG("Making a LooperKiller action");
+    auto action =  std::make_unique<LooperKiller>(m_config);
+    actionList.steppingActions.push_back( action.get() );
+    return action;
+  }
+
+}
diff --git a/Simulation/G4Utilities/G4UserActions/src/LooperKillerTool.h b/Simulation/G4Utilities/G4UserActions/src/LooperKillerTool.h
new file mode 100644
index 00000000..450ce181
--- /dev/null
+++ b/Simulation/G4Utilities/G4UserActions/src/LooperKillerTool.h
@@ -0,0 +1,54 @@
+/*
+  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef G4USERACTIONS_G4UA_LOOPERKILLERTOOL_H
+#define G4USERACTIONS_G4UA_LOOPERKILLERTOOL_H
+
+// System includes
+#include <string>
+
+// Infrastructure includes
+#include "G4AtlasTools/UserActionToolBase.h"
+
+// Local includes
+#include "LooperKiller.h"
+
+namespace G4UA
+{
+
+  /// @class LooperKillerTool
+  /// @brief Tool which manages the LooperKiller action.
+  ///
+  /// Create the LooperKiller for each worker thread
+  ///
+  /// @author Andrea Di Simone
+  ///
+  class LooperKillerTool : public UserActionToolBase<LooperKiller>
+  {
+
+    public:
+
+      /// Standard constructor
+      LooperKillerTool(const std::string& type, const std::string& name,
+		       const IInterface* parent);
+
+      virtual StatusCode initialize() override;
+      virtual StatusCode finalize() override;
+
+    protected:
+
+      /// Create action for this thread
+      virtual std::unique_ptr<LooperKiller>
+      makeAndFillAction(G4AtlasUserActions&) override final;
+
+    private:
+
+      /// Configuration parameters
+      G4UA::LooperKiller::Config m_config;
+
+  }; // class LooperKillerTool
+
+} // namespace G4UA
+
+#endif
diff --git a/Simulation/G4Utilities/G4UserActions/src/components/G4UserActions_entries.cxx b/Simulation/G4Utilities/G4UserActions/src/components/G4UserActions_entries.cxx
new file mode 100644
index 00000000..7e08650c
--- /dev/null
+++ b/Simulation/G4Utilities/G4UserActions/src/components/G4UserActions_entries.cxx
@@ -0,0 +1,7 @@
+#include "../LooperKillerTool.h"
+#include "../AthenaStackingActionTool.h"
+#include "../AthenaTrackingActionTool.h"
+
+DECLARE_COMPONENT( G4UA::LooperKillerTool )
+DECLARE_COMPONENT( G4UA::AthenaStackingActionTool )
+DECLARE_COMPONENT( G4UA::AthenaTrackingActionTool )
diff --git a/Simulation/ISF/ISF_Core/FaserISF_Event/CMakeLists.txt b/Simulation/ISF/ISF_Core/FaserISF_Event/CMakeLists.txt
new file mode 100644
index 00000000..91864e66
--- /dev/null
+++ b/Simulation/ISF/ISF_Core/FaserISF_Event/CMakeLists.txt
@@ -0,0 +1,37 @@
+################################################################################
+# Package: FaserISF_Event
+################################################################################
+
+# Declare the package name:
+atlas_subdir( FaserISF_Event )
+
+# Declare the package's dependencies:
+atlas_depends_on_subdirs( PUBLIC
+                          AtlasTest/TestTools
+                          Control/AthenaBaseComps
+                          DetectorDescription/FaserDetDescr
+                          DetectorDescription/GeoPrimitives
+                          Generators/GeneratorObjects
+                          GaudiKernel
+                          Simulation/Barcode/BarcodeEvent
+                          Simulation/ISF/ISF_Core/ISF_Event )
+
+# External dependencies:
+find_package( CLHEP )
+find_package( Eigen )
+find_package( HepMC )
+
+# Component(s) in the package:
+atlas_add_library( FaserISF_Event
+                   src/*.cxx
+                   PUBLIC_HEADERS FaserISF_Event
+                   INCLUDE_DIRS ${CLHEP_INCLUDE_DIRS} ${HEPMC_INCLUDE_DIRS} ${EIGEN_INCLUDE_DIRS}
+                   DEFINITIONS ${CLHEP_DEFINITIONS}
+                   LINK_LIBRARIES ${CLHEP_LIBRARIES} ${HEPMC_LIBRARIES} ${EIGEN_LIBRARIES} ISF_Event TestTools AthenaBaseComps FaserDetDescr GeoPrimitives GeneratorObjects GaudiKernel )
+
+#atlas_add_test( FaserISFParticle_test
+#                SOURCES
+#                test/ISFParticle_test.cxx
+#                INCLUDE_DIRS ${CLHEP_INCLUDE_DIRS} ${HEPMC_INCLUDE_DIRS} ${EIGEN_INCLUDE_DIRS}
+#                LINK_LIBRARIES ${CLHEP_LIBRARIES} ${HEPMC_LIBRARIES} ${EIGEN_LIBRARIES} ISF_Event TestTools AthenaBaseComps FaserDetDescr GeoPrimitives GeneratorObjects GaudiKernel FaserISF_Event 
+#                WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
diff --git a/Simulation/ISF/ISF_Core/FaserISF_Event/FaserISF_Event/FaserISFParticle.h b/Simulation/ISF/ISF_Core/FaserISF_Event/FaserISF_Event/FaserISFParticle.h
new file mode 100644
index 00000000..d06138eb
--- /dev/null
+++ b/Simulation/ISF/ISF_Core/FaserISF_Event/FaserISF_Event/FaserISFParticle.h
@@ -0,0 +1,215 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// FaserISFParticle.h, (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#ifndef FASERISF_EVENT_FASERISFPARTICLE_H
+#define FASERISF_EVENT_FASERISFPARTICLE_H
+
+// Gaudi Kernel
+#include "GaudiKernel/MsgStream.h"
+// Barcode includes
+#include "BarcodeEvent/Barcode.h"
+// ISF include
+#include "ISF_Event/TruthBinding.h"
+#include "ISF_Event/SimSvcID.h"
+#include "ISF_Event/ParticleOrder.h"
+#include "ISF_Event/ParticleUserInformation.h"
+// DetectorDescription
+#include "FaserDetDescr/FaserRegion.h"
+// Amg classes
+#include "GeoPrimitives/GeoPrimitives.h"
+// CHLEP classes
+#include "CLHEP/Geometry/Point3D.h"
+#include "CLHEP/Geometry/Vector3D.h"
+// Common classes
+#include "GeneratorObjects/HepMcParticleLink.h"
+
+namespace ISF {
+
+  /** the datatype to be used to store each individual particle hop */
+  typedef std::pair< FaserDetDescr::FaserRegion, ISF::SimSvcID >   FaserDetRegionSvcIDPair;
+  /** the container type to be used for the particle hops */
+  typedef std::vector< FaserDetRegionSvcIDPair >                   FaserParticleHistory;
+
+  /**
+     @class FaserISFParticle
+
+     The generic ISF particle definition,
+
+     @author Andreas.Salzburger -at- cern.ch , Elmar.Ritsch -at- cern.ch
+  */
+
+  class FaserISFParticle {
+
+  public:
+    /** disallow default constructor */
+    FaserISFParticle() = delete;
+
+    /** use this constructor whenever possible */
+    FaserISFParticle(const Amg::Vector3D& pos,
+                const Amg::Vector3D& mom,
+                double mass,
+                double charge,
+                int pdgCode,
+                double time,
+                const FaserISFParticle &parent,
+                Barcode::ParticleBarcode barcode = Barcode::fUndefinedBarcode,
+                TruthBinding* truth = nullptr,
+                const HepMcParticleLink * partLink = nullptr );
+
+    /** CLHEP-compatible constructor */
+    FaserISFParticle(const HepGeom::Point3D<double>& pos,
+                const HepGeom::Vector3D<double>& mom,
+                double mass,
+                double charge,
+                int pdgCode,
+                double time,
+                const FaserISFParticle &parent,
+                Barcode::ParticleBarcode barcode = Barcode::fUndefinedBarcode,
+                TruthBinding* truth = nullptr,
+                const HepMcParticleLink * partLink = nullptr );
+
+    /** this constructor should only be used for event read-in */
+    FaserISFParticle(const Amg::Vector3D& pos,
+                const Amg::Vector3D& mom,
+                double mass,
+                double charge,
+                int pdgCode,
+                double time,
+                const FaserDetRegionSvcIDPair &origin,
+                int bcid,
+                Barcode::ParticleBarcode barcode = Barcode::fUndefinedBarcode,
+                TruthBinding* truth = nullptr,
+                const HepMcParticleLink * partLink = nullptr );
+
+    /** Copy constructor */
+    FaserISFParticle(const FaserISFParticle& isfp);
+
+    /** Move copy constructor */
+    FaserISFParticle(FaserISFParticle&& isfp);
+
+    /** Destructor */
+    ~FaserISFParticle();
+
+    /** Assignment operator */
+    FaserISFParticle& operator=(const FaserISFParticle& rhs);
+
+    /** Move assignment operator */
+    FaserISFParticle& operator=(FaserISFParticle&& rhs);
+
+    /** Comparisons */
+    bool operator==(const FaserISFParticle& rhs) const;
+    bool isEqual(const FaserISFParticle& rhs) const;
+    bool isIdent(const FaserISFParticle& rhs) const;
+
+    /** The current momentum vector of the ISFParticle */
+    const Amg::Vector3D& momentum() const;
+
+    /** The current position of the ISFParticle */
+    const Amg::Vector3D& position() const;
+
+    /** Update the position of the ISFParticle */
+    void updatePosition(const Amg::Vector3D& position);
+
+    /** Update the momentum of the ISFParticle */
+    void updateMomentum(const Amg::Vector3D& momentum);
+
+    /** mass of the particle */
+    double mass() const;
+
+    /** charge of the particle */
+    double charge() const;
+
+    /** Timestamp of the ISFParticle */
+    double timeStamp() const;
+
+    /** PDG value */
+    int pdgCode() const;
+
+    /** Kinetic energy */
+    double ekin() const;
+
+    /** the particle's full history */
+    const FaserParticleHistory& history() const;
+    /** the sub-detector ID the particle's originates from */
+    FaserDetDescr::FaserRegion  originGeoID() const;
+    /** the simulation service the particle originates from */
+    SimSvcID                    originSimID() const;
+    /** previous geoID that the particle was simulated in */
+    FaserDetDescr::FaserRegion  prevGeoID() const;
+    /** the simulation service that previously treated this particle */
+    SimSvcID                    prevSimID() const;
+    /** next geoID the particle will be simulated in */
+    FaserDetDescr::FaserRegion  nextGeoID() const;
+    /** the next simulation service the particle will be sent to */
+    SimSvcID                    nextSimID() const;
+    /** register the next FaserDetDescr::FaserRegion */
+    void                        setNextGeoID(FaserDetDescr::FaserRegion geoID);
+    /** register the next SimSvcID */
+    void                        setNextSimID(SimSvcID simID);
+
+    /** the barcode */
+    Barcode::ParticleBarcode barcode() const;
+
+    /** set a new barcode */
+    void setBarcode(Barcode::ParticleBarcode bc);
+    /** set a new barcode and update the HepMcParticleLink  */
+    void setBarcodeAndUpdateHepMcParticleLink(Barcode::ParticleBarcode bc);
+
+    /** bunch-crossing identifier */
+    int getBCID() const;
+
+    /** set bunch-crossing identifier */
+    void setBCID(int bcid);
+
+    /** pointer to the simulation truth - optional, can be 0 */
+    TruthBinding* getTruthBinding() const;
+    void          setTruthBinding(TruthBinding *truth);
+
+    /** HepMcParticleLink accessors */
+    inline const HepMcParticleLink* getParticleLink() const {return  m_partLink;};
+    inline void setParticleLink(const HepMcParticleLink* partLink) {m_partLink=partLink;};
+
+    /** return the particle order (eg used to assure ID->Calo->MS simulation order) */
+    ParticleOrder  getOrder() const;
+    void           setOrder(ParticleOrder order);
+
+    /** get/set ParticleUserInformation */
+    ParticleUserInformation *getUserInformation() const;
+    void                     setUserInformation(ParticleUserInformation *userInfo);
+
+    /** Dump methods to be used by the overloaded stream operator (inheritance!) */
+    MsgStream&    dump(MsgStream& out) const;
+    std::ostream& dump(std::ostream& out) const;
+
+  private :
+    Amg::Vector3D                m_position;
+    Amg::Vector3D                m_momentum;
+    double                       m_mass;
+    double                       m_charge;
+    int                          m_pdgCode;
+    double                       m_tstamp;
+    FaserParticleHistory         m_history;
+    Barcode::ParticleBarcode     m_barcode;
+    int                          m_bcid;                  //!< bunch-crossing identifier
+    TruthBinding*                m_truth;
+    ParticleOrder                m_order;                 //!< particle simulation order
+    mutable ParticleUserInformation *m_userInfo;          //!< user information stored with the ISFParticle
+    const HepMcParticleLink*     m_partLink;
+  };
+
+  // Overload of << operator for MsgStream for debug output
+  //
+  inline MsgStream&    operator << ( MsgStream& sl,    const ISF::FaserISFParticle& isfp) { isfp.dump(sl); return sl; }
+  inline std::ostream& operator << ( std::ostream& sl, const ISF::FaserISFParticle& isfp) { isfp.dump(sl); return sl; }
+
+} // end of namespace
+
+/* implementation for inlined methods */
+#include <FaserISF_Event/FaserISFParticle.icc>
+
+#endif // FASERISF_EVENT_FASERISFPARTICLE_H
diff --git a/Simulation/ISF/ISF_Core/FaserISF_Event/FaserISF_Event/FaserISFParticle.icc b/Simulation/ISF/ISF_Core/FaserISF_Event/FaserISF_Event/FaserISFParticle.icc
new file mode 100644
index 00000000..0d98c59b
--- /dev/null
+++ b/Simulation/ISF/ISF_Core/FaserISF_Event/FaserISF_Event/FaserISFParticle.icc
@@ -0,0 +1,93 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// this file contains all ISFParticle inline methods
+
+namespace ISF {
+
+  // inline methods, nomen est omen
+  //
+  inline const Amg::Vector3D& FaserISFParticle::position() const { return m_position; }
+  inline const Amg::Vector3D& FaserISFParticle::momentum() const { return m_momentum; }
+  inline void FaserISFParticle::updatePosition(const Amg::Vector3D& position) { m_position=position; }
+  inline void FaserISFParticle::updateMomentum(const Amg::Vector3D& momentum) { m_momentum=momentum; }
+
+  inline double          FaserISFParticle::mass() const      { return m_mass; }
+  inline double          FaserISFParticle::charge() const    { return m_charge; }
+  inline double          FaserISFParticle::timeStamp() const { return m_tstamp; }
+  inline int             FaserISFParticle::pdgCode() const   { return m_pdgCode; }
+
+  inline double          FaserISFParticle::ekin() const      { return sqrt( m_momentum.mag2() + m_mass*m_mass ) - m_mass; }
+
+  // history methods
+  //
+  inline const FaserParticleHistory& FaserISFParticle::history()     const { return m_history;                    }
+  inline FaserDetDescr::FaserRegion  FaserISFParticle::originGeoID() const { return m_history.front().first;      }
+  inline SimSvcID                    FaserISFParticle::originSimID() const { return m_history.front().second;     }
+  inline FaserDetDescr::FaserRegion  FaserISFParticle::prevGeoID()   const { return (m_history.end()-1)->first;   }
+  inline SimSvcID                    FaserISFParticle::prevSimID()   const { return (m_history.end()-1)->second;  }
+  inline FaserDetDescr::FaserRegion  FaserISFParticle::nextGeoID()   const { return m_history.back().first;       }
+  inline SimSvcID                    FaserISFParticle::nextSimID()   const { return m_history.back().second;      }
+  inline void                        FaserISFParticle::setNextGeoID( FaserDetDescr::FaserRegion geoID) { m_history.back().first = geoID; }
+  inline void                        FaserISFParticle::setNextSimID( SimSvcID simID)                   { m_history.back().second = simID;}
+
+  // barcode methods
+  //
+  inline Barcode::ParticleBarcode FaserISFParticle::barcode() const { return m_barcode; }
+  inline void            FaserISFParticle::setBarcode(Barcode::ParticleBarcode bc) { m_barcode = bc; }
+
+  // truth methods
+  //
+  inline TruthBinding* FaserISFParticle::getTruthBinding() const              { return m_truth; }
+  inline void          FaserISFParticle::setTruthBinding(TruthBinding *truth) { m_truth = truth; }
+
+  // particle order methods
+  //
+  inline int  FaserISFParticle::getOrder() const { return m_order; }
+  inline void FaserISFParticle::setOrder( ParticleOrder order ) { m_order = order; }
+
+  // set ParticleUserInformation
+  inline ParticleUserInformation *FaserISFParticle::getUserInformation() const                            { return m_userInfo;    }
+  inline void                     FaserISFParticle::setUserInformation(ParticleUserInformation *userInfo)
+  {
+    if ( m_userInfo==0 ) { m_userInfo = userInfo; }
+    else {
+      m_userInfo->setGeneration( userInfo->generation() );
+      m_userInfo->setProcess( userInfo->process() );
+      // don't overwrite barcode
+    }
+  }
+
+  // bunch-crossing identifier
+  inline int FaserISFParticle::getBCID() const {
+    return m_bcid;
+  }
+  inline void FaserISFParticle::setBCID(int bcid) {
+    m_bcid = bcid;
+  }
+
+  // printout methods
+  inline MsgStream& FaserISFParticle::dump( MsgStream& out ) const
+  { out << "ISFP pdg=" << m_pdgCode << " p=" << m_momentum.mag()
+        << " xyz=(" << m_position.x() << "," <<  m_position.y() << "," <<  m_position.z() << ")"
+        << " r=" << m_position.perp() << " eta=" << m_position.eta() << " phi=" << m_position.phi()
+        << " barcode=" << m_barcode << " mass=" << m_mass << " order=" << m_order << " bcid=" << m_bcid;
+    if (m_partLink)
+      out << " (" << *m_partLink << ")";
+    else
+      out << " (No assoc. HMPL)";
+    return out;}
+
+  inline std::ostream& FaserISFParticle::dump( std::ostream& out ) const
+  { out << "ISFP pdg=" << m_pdgCode << " p=" << m_momentum.mag()
+        << " xyz=(" << m_position.x() << "," <<  m_position.y() << "," <<  m_position.z() << ")"
+        << " r=" << m_position.perp() << " eta=" << m_position.eta() << " phi=" << m_position.phi()
+        << " barcode=" << m_barcode << " mass=" << m_mass << " order=" << m_order << " bcid=" << m_bcid;
+    if (m_partLink)
+      out << " (" << *m_partLink << ")";
+    else
+      out << " (No assoc. HMPL)";
+    return out;}
+
+} // end ISF namespace
diff --git a/Simulation/ISF/ISF_Core/FaserISF_Event/FaserISF_Event/FaserISFParticleContainer.h b/Simulation/ISF/ISF_Core/FaserISF_Event/FaserISF_Event/FaserISFParticleContainer.h
new file mode 100644
index 00000000..c7ebf070
--- /dev/null
+++ b/Simulation/ISF/ISF_Core/FaserISF_Event/FaserISF_Event/FaserISFParticleContainer.h
@@ -0,0 +1,27 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// FaserISFParticleContainer.h, (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+//
+#ifndef FASERISF_EVENT_FASERISFPARTICLECONTAINER_H
+#define FASERISF_EVENT_FASERISFPARTICLECONTAINER_H
+
+// STL includes
+#include <list>
+
+// forward declarations
+namespace ISF {
+  class FaserISFParticle;
+}
+
+namespace ISF {
+  /** generic ISFParticle container (not necessarily a std::list!) */
+  typedef std::list<ISF::FaserISFParticle*>                FaserISFParticleContainer;
+  typedef std::list<const ISF::FaserISFParticle*>          ConstFaserISFParticleContainer;
+}
+
+#endif // FASERISF_EVENT_FASERISFPARTICLECONTAINER_H
+
diff --git a/Simulation/ISF/ISF_Core/FaserISF_Event/FaserISF_Event/FaserISFParticleVector.h b/Simulation/ISF/ISF_Core/FaserISF_Event/FaserISF_Event/FaserISFParticleVector.h
new file mode 100644
index 00000000..ad15f993
--- /dev/null
+++ b/Simulation/ISF/ISF_Core/FaserISF_Event/FaserISF_Event/FaserISFParticleVector.h
@@ -0,0 +1,27 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// FaserISFParticleVector.h, (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+//
+#ifndef FASERISF_EVENT_FASERISFPARTICLEVECTOR_H
+#define FASERISF_EVENT_FASERISFPARTICLEVECTOR_H
+
+// STL includes
+#include <vector>
+
+// forward declarations
+namespace ISF {
+  class FaserISFParticle;
+}
+
+namespace ISF {
+  /** ISFParticle vector */
+  typedef std::vector<ISF::FaserISFParticle *>             FaserISFParticleVector;
+  typedef std::vector<const ISF::FaserISFParticle *>       ConstFaserISFParticleVector;
+}
+
+#endif // FASERISF_EVENT_FASERISFPARTICLEVECTOR_H
+
diff --git a/Simulation/ISF/ISF_Core/FaserISF_Event/FaserISF_Event/FaserParticleHelper.h b/Simulation/ISF/ISF_Core/FaserISF_Event/FaserISF_Event/FaserParticleHelper.h
new file mode 100644
index 00000000..dcaec8f4
--- /dev/null
+++ b/Simulation/ISF/ISF_Core/FaserISF_Event/FaserISF_Event/FaserParticleHelper.h
@@ -0,0 +1,51 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// FaserParticleHelper.h, (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#ifndef FASERISF_EVENT_FASERPARTICLEHELPER_H
+#define FASERISF_EVENT_FASERPARTICLEHELPER_H 1
+
+// forward declarations
+namespace HepMC {
+  class GenParticle;
+}
+
+namespace ISF {
+
+  class FaserISFParticle;
+
+  /**
+   @class FaserParticleHelper
+
+   A simple helper class to perform commonly used, basic functions, like
+     * converting FaserISFParticles into a differnt particle representation format
+
+   @author Elmar.Ritsch -at- cern.ch
+   */
+
+  class FaserParticleHelper {
+
+    public:
+        /** empty constructor */
+        FaserParticleHelper() {} ;
+
+        /** empty destructor */
+        ~FaserParticleHelper() {} ;
+
+        /** convert the given particle to HepMC format */
+        static HepMC::GenParticle *convert( const ISF::FaserISFParticle &p);
+        
+    private :
+  };
+
+} // end of namespace
+
+/* implementation for inlined methods (none existing at the moment) */
+//#include <FaserISF_Event/FaserParticleHelper.icc>
+
+#endif // FASERISF_EVENT_FASERPARTICLEHELPER_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
new file mode 100644
index 00000000..86f6a900
--- /dev/null
+++ b/Simulation/ISF/ISF_Core/FaserISF_Event/FaserISF_Event/IFaserTruthIncident.h
@@ -0,0 +1,206 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// IFaserTruthIncident.h, (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+#ifndef FASERISF_EVENT_IFASERTRUTHINCIDENT_H
+#define FASERISF_EVENT_IFASERTRUTHINCIDENT_H 1
+
+// DetectorDescription
+#include "FaserDetDescr/FaserRegion.h"
+
+// Barcode includes
+#include "BarcodeEvent/Barcode.h"
+#include "BarcodeEvent/PhysicsProcessCode.h"
+
+// forward declarations
+namespace HepMC {
+  class FourVector;
+  class GenParticle;
+}
+
+namespace ISF {
+
+  /**  The interaction classifications are described as follows:
+       STD_VTX: interaction of a particle without a pre-defined decay;
+       QS_SURV_VTX: a particle with a pre-defined decay under-going a
+       non-destructive interaction;
+       QS_DEST_VTX: a particle with a pre-defined decay under-going a
+       destructive interaction other than its pre-defined decay;
+       QS_PREDEF_VTX: a particle under-going its pre-defined decay */
+  typedef enum InteractionClass_t {
+    STD_VTX = 0,
+    QS_SURV_VTX = 1,
+    QS_DEST_VTX = 2,
+    QS_PREDEF_VTX = 3,
+    UNKNOWN_VTX
+  } InteractionClass_t;
+
+  /** @class IFaserTruthIncident
+
+      ISF interface class for TruthIncidents. Information regarding
+      interactions that occur inside simulators are wrapped into
+      dedicated TruthIncident implemenations. The IFaserTruthIncident
+      interface offers a layer of abstraction to the ISF framework,
+      in order to build a MC truth record of the simulated event.
+
+      @author Elmar.Ritsch -at- cern.ch
+  */
+  class IFaserTruthIncident {
+  public:
+    IFaserTruthIncident(FaserDetDescr::FaserRegion geoID, unsigned short numChildren): m_geoID(geoID),
+                                                                                  m_numChildren(numChildren),
+                                                                                  m_passWholeVertex(true),
+                                                                                  m_childPassedFilters(numChildren,false) { };
+
+    /** Return the SimGeoID corresponding to the vertex of the truth incident */
+    FaserDetDescr::FaserRegion geoID() { return m_geoID; };
+
+    /** Return HepMC position of the truth vertex */
+    virtual const HepMC::FourVector&  position() const = 0;
+
+    /** Return category of the physics process represented by the truth incident (eg hadronic, em, ..) */
+    virtual int                       physicsProcessCategory() const = 0;
+    /** Return specific physics process code of the truth incident (eg ionisation, bremsstrahlung, ..)*/
+    virtual Barcode::PhysicsProcessCode physicsProcessCode() const = 0;
+
+    /** Return p^2 of the parent particle */
+    virtual double                    parentP2() const = 0;
+    /** Return pT^2 of the parent particle */
+    virtual double                    parentPt2() const = 0;
+    /** Return Ekin of the parent particle */
+    virtual double                    parentEkin() const = 0;
+    /** Return the PDG Code of the parent particle */
+    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::GenParticle*       parentParticle() const = 0;
+    /** Return the barcode of the parent particle */
+    virtual Barcode::ParticleBarcode  parentBarcode() const = 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
+        a new barcode to it) */
+    virtual HepMC::GenParticle*       parentParticleAfterIncident(Barcode::ParticleBarcode newBC) = 0;
+
+    /** Return total number of child particles */
+    inline unsigned short             numberOfChildren() const;
+    /** Return p^2 of the i-th child particle */
+    virtual double                    childP2(unsigned short index) const = 0;
+    /** Return pT^2 of the i-th child particle */
+    virtual double                    childPt2(unsigned short index) const = 0;
+    /** Return Ekin of the i-th child particle */
+    virtual double                    childEkin(unsigned short index) const = 0;
+    /** Return the PDG Code of the i-th child particle */
+    virtual int                       childPdgCode(unsigned short index) const = 0;
+    /** Return true if at least one child particle passes the given p^2 cut
+        (= at least one child with p^2 >= pt2cut) */
+    inline bool                       childrenP2Pass(double p2cut);
+    /** Return true if at least one child particle passes the given pT^2 cut
+        (= at least one child with pT^2 >= pt2cut) */
+    inline bool                       childrenPt2Pass(double pt2cut);
+    /** Return true if at least one child particle passes the given Ekin cut
+        (= at least one child with Ekin >= ekincut) */
+    inline bool                       childrenEkinPass(double ekincut);
+    /** Return the i-th child as a HepMC particle type and assign the given
+        Barcode to the simulator particle (only called for particles that will
+        enter the HepMC truth event) */
+    virtual HepMC::GenParticle*       childParticle(unsigned short index,
+                                                    Barcode::ParticleBarcode bc = Barcode::fUndefinedBarcode) const = 0;
+    /** 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). */
+    virtual HepMC::GenParticle*       updateChildParticle(unsigned short index,
+                                                          HepMC::GenParticle *existingChild) const = 0;
+    /** Set the the barcode of all child particles to the given bc */
+    virtual void                      setAllChildrenBarcodes(Barcode::ParticleBarcode bc) = 0;
+
+    /** Record that a particular child passed a check */
+    inline void                       setChildPassedFilters(unsigned short index);
+    /** Should a particular child be written out to the GenEvent */
+    inline bool                       childPassedFilters(unsigned short index) const;
+    /** Set whether this TruthIncident should pass the vertex as a whole or individual children */
+    inline void                       setPassWholeVertices(bool passWholeVertex);
+
+    /**  The interaction classifications are described as follows:
+         STD_VTX: interaction of a particle without a pre-defined decay;
+         QS_SURV_VTX: a particle with a pre-defined decay under-going a
+         non-destructive interaction;
+         QS_DEST_VTX: a particle with a pre-defined decay under-going a
+         destructive interaction other than its pre-defined decay;
+         QS_PREDEF_VTX: a particle under-going its pre-defined decay */
+    virtual ISF::InteractionClass_t interactionClassification() const {return ISF::STD_VTX;};
+  private:
+    FaserDetDescr::FaserRegion        m_geoID; //!< region that the TruthIncident is located in
+  protected:
+    int                               m_numChildren;
+    bool                              m_passWholeVertex;
+    std::vector<bool>                 m_childPassedFilters;
+
+  };
+
+  //
+  // inline methods :
+  //
+
+  unsigned short ISF::IFaserTruthIncident::numberOfChildren() const {
+    return m_numChildren;
+  }
+
+  // default loops to check a given cut for all child particles
+
+  // loop over children to find out whether the momentum cut is passed or not
+  bool ISF::IFaserTruthIncident::childrenP2Pass(double p2cut) {
+    bool pass = false; // true if cut passed
+    // as soon as at a particle passes the cut -> end loop and return true
+    for ( unsigned short i=0; !(pass && m_passWholeVertex) && (i<m_numChildren); ++i) {
+      bool thispassed = (childP2(i) >= p2cut);
+      if(thispassed) { setChildPassedFilters(i); }
+      pass |= thispassed;
+    }
+    return pass;
+  }
+
+  // loop over children to find out whether the transverse momentum cut is passed or not
+  bool ISF::IFaserTruthIncident::childrenPt2Pass(double pt2cut) {
+    bool pass = false; // true if cut passed
+    // as soon as at a particle passes the cut -> end loop and return true
+    for ( unsigned short i=0; !(pass && m_passWholeVertex) && (i<m_numChildren); ++i) {
+      bool thispassed = (childPt2(i) >= pt2cut);
+      if(thispassed) { setChildPassedFilters(i); }
+      pass |= thispassed;
+    }
+    return pass;
+  }
+
+  // loop over children to find out whether the transverse momentum cut is passed or not
+  bool ISF::IFaserTruthIncident::childrenEkinPass(double ekincut) {
+    bool pass = false; // true if cut passed
+    // as soon as at a particle passes the cut -> end loop and return true
+    for ( unsigned short i=0; !(pass && m_passWholeVertex) && (i<m_numChildren); ++i) {
+      bool thispassed = (childEkin(i) >= ekincut);
+      if(thispassed) { setChildPassedFilters(i); }
+      pass |= thispassed;
+    }
+    return pass;
+  }
+
+  void ISF::IFaserTruthIncident::setChildPassedFilters(unsigned short index) {
+    m_childPassedFilters[index] = true;
+    return;
+  }
+
+  bool ISF::IFaserTruthIncident::childPassedFilters(unsigned short index) const {
+    return m_childPassedFilters[index];
+  }
+
+  void ISF::IFaserTruthIncident::setPassWholeVertices(bool passWholeVertex) {
+    m_passWholeVertex=passWholeVertex;
+  }
+
+}
+
+#endif //> !FASERISF_EVENT_IFASERTRUTHINCIDENT_H
diff --git a/Simulation/ISF/ISF_Core/FaserISF_Event/src/FaserISFParticle.cxx b/Simulation/ISF/ISF_Core/FaserISF_Event/src/FaserISFParticle.cxx
new file mode 100644
index 00000000..b3c4f22d
--- /dev/null
+++ b/Simulation/ISF/ISF_Core/FaserISF_Event/src/FaserISFParticle.cxx
@@ -0,0 +1,273 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// ISFParticle.cxx, (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#include "FaserISF_Event/FaserISFParticle.h"
+
+#include <cmath> // fabs
+
+ISF::FaserISFParticle::FaserISFParticle(
+                              const Amg::Vector3D& pos,
+                              const Amg::Vector3D& mom,
+                              double mass,
+                              double charge,
+                              int pdgCode,
+                              double time,
+                              const FaserISFParticle &parent,
+                              Barcode::ParticleBarcode barcode,
+                              TruthBinding* truth,
+                              const HepMcParticleLink* partLink):
+  m_position(pos),
+  m_momentum(mom),
+  m_mass(mass),
+  m_charge(charge),
+  m_pdgCode(pdgCode),
+  m_tstamp(time),
+  m_history(parent.history()),
+  m_barcode(barcode),
+  m_bcid(parent.getBCID()),
+  m_truth(truth),
+  m_order(ISF::DefaultParticleOrder),
+  m_userInfo(nullptr),
+  m_partLink(partLink)
+{
+
+}
+
+ISF::FaserISFParticle::FaserISFParticle(
+                              const HepGeom::Point3D<double>& pos,
+                              const HepGeom::Vector3D<double>& mom,
+                              double mass,
+                              double charge,
+                              int pdgCode,
+                              double time,
+                              const FaserISFParticle &parent,
+                              Barcode::ParticleBarcode barcode,
+                              TruthBinding* truth,
+                              const HepMcParticleLink* partLink):
+  m_position( pos.x(), pos.y(), pos.z()),
+  m_momentum( mom.x(), mom.y(), mom.z()),
+  m_mass(mass),
+  m_charge(charge),
+  m_pdgCode(pdgCode),
+  m_tstamp(time),
+  m_history(parent.history()),
+  m_barcode(barcode),
+  m_bcid(parent.getBCID()),
+  m_truth(truth),
+  m_order(ISF::DefaultParticleOrder),
+  m_userInfo(nullptr),
+  m_partLink(partLink)
+{
+
+}
+
+ISF::FaserISFParticle::FaserISFParticle(
+                              const Amg::Vector3D& pos,
+                              const Amg::Vector3D& mom,
+                              double mass,
+                              double charge,
+                              int pdgCode,
+                              double time,
+                              const FaserDetRegionSvcIDPair &origin,
+                              int bcid,
+                              Barcode::ParticleBarcode barcode,
+                              TruthBinding* truth,
+                              const HepMcParticleLink* partLink):
+  m_position(pos),
+  m_momentum(mom),
+  m_mass(mass),
+  m_charge(charge),
+  m_pdgCode(pdgCode),
+  m_tstamp(time),
+  m_history(1, origin),
+  m_barcode(barcode),
+  m_bcid(bcid),
+  m_truth(truth),
+  m_order(ISF::DefaultParticleOrder),
+  m_userInfo(nullptr),
+  m_partLink(partLink)
+{
+
+}
+
+ISF::FaserISFParticle::FaserISFParticle(const FaserISFParticle& isfp):
+  m_position(isfp.position()),
+  m_momentum(isfp.momentum()),
+  m_mass(isfp.mass()),
+  m_charge(isfp.charge()),
+  m_pdgCode(isfp.pdgCode()),
+  m_tstamp(isfp.timeStamp()),
+  m_history(isfp.history()),
+  m_barcode(isfp.barcode()),
+  m_bcid(isfp.getBCID()),
+  m_truth(nullptr),
+  m_order(ISF::DefaultParticleOrder),
+  m_userInfo(nullptr)
+{
+  TruthBinding *truth = isfp.getTruthBinding();
+  if (truth) {
+    m_truth = new TruthBinding(*truth);
+  }
+  m_partLink = ((isfp.getParticleLink()) ? new HepMcParticleLink(*isfp.getParticleLink()) : nullptr);
+}
+
+ISF::FaserISFParticle::FaserISFParticle(FaserISFParticle&& isfp):
+  m_position(isfp.position()),
+  m_momentum(isfp.momentum()),
+  m_mass(isfp.mass()),
+  m_charge(isfp.charge()),
+  m_pdgCode(isfp.pdgCode()),
+  m_tstamp(isfp.timeStamp()),
+  m_history(isfp.history()),
+  m_barcode(isfp.barcode()),
+  m_bcid(isfp.getBCID()),
+  m_truth(isfp.getTruthBinding()),
+  m_order(isfp.getOrder()),
+  m_userInfo(isfp.getUserInformation()),
+  m_partLink(isfp.getParticleLink())
+{
+}
+
+ISF::FaserISFParticle::~FaserISFParticle() {
+  delete m_truth;
+  delete m_userInfo;
+  if (m_partLink) delete m_partLink;
+}
+
+ISF::FaserISFParticle& ISF::FaserISFParticle::operator=(const ISF::FaserISFParticle& rhs)
+{
+
+  if (this != &rhs) {
+    m_position     = rhs.position();
+    m_momentum     = rhs.momentum();
+    m_mass         = rhs.mass();
+    m_charge       = rhs.charge();
+    m_pdgCode      = rhs.pdgCode();
+    m_tstamp       = rhs.timeStamp();
+    m_history      = rhs.history();
+    m_barcode      = rhs.barcode();
+    m_bcid         = rhs.getBCID();
+
+    delete m_truth;
+    m_truth = nullptr;
+
+    TruthBinding *rhsTruth = rhs.getTruthBinding();
+    if (rhsTruth) {
+      m_truth = new TruthBinding(*rhsTruth);
+    }
+    m_partLink = ((rhs.getParticleLink()) ? new HepMcParticleLink(*rhs.getParticleLink()): nullptr);
+
+    delete m_userInfo;
+    m_userInfo = nullptr;
+  }
+
+  return *this;
+}
+
+ISF::FaserISFParticle& ISF::FaserISFParticle::operator=(ISF::FaserISFParticle&& rhs)
+{
+  m_position     = rhs.position();
+  m_momentum     = rhs.momentum();
+  m_mass         = rhs.mass();
+  m_charge       = rhs.charge();
+  m_pdgCode      = rhs.pdgCode();
+  m_tstamp       = rhs.timeStamp();
+  m_history      = rhs.history();
+  m_barcode      = rhs.barcode();
+  m_bcid         = rhs.getBCID();
+  delete m_truth;
+  m_truth        = rhs.getTruthBinding();
+  delete m_userInfo;
+  m_userInfo     = rhs.getUserInformation();
+  if (m_partLink) delete m_partLink;
+  m_partLink     = rhs.getParticleLink();
+
+  return *this;
+}
+
+bool ISF::FaserISFParticle::operator==(const ISF::FaserISFParticle& rhs) const
+{
+  return isEqual(rhs);
+}
+
+bool ISF::FaserISFParticle::isEqual(const ISF::FaserISFParticle& rhs) const
+{
+  double epsilon = 1e-6;
+
+  bool pass = true;
+  pass &= m_position == rhs.position();
+  pass &= m_momentum == rhs.momentum();
+  pass &= std::fabs(m_mass-rhs.mass()) < epsilon;
+  pass &= std::fabs(m_charge-rhs.charge()) < epsilon;
+  pass &= m_pdgCode == rhs.pdgCode();
+  pass &= std::fabs(m_tstamp-rhs.timeStamp()) < epsilon;
+  pass &= m_history == rhs.history();
+  pass &= m_barcode == rhs.barcode();
+  pass &= m_bcid == rhs.getBCID();
+
+  {
+    const auto rhsTruthPtr = rhs.getTruthBinding();
+    if (m_truth && rhsTruthPtr) {
+      pass &= *m_truth == *rhsTruthPtr;
+    } else {
+      pass &= m_truth == rhsTruthPtr; // must be both nullptr to pass
+    }
+  }
+
+  {
+    const auto rhsUserInfoPtr = rhs.getUserInformation();
+    if (m_userInfo && rhsUserInfoPtr) {
+      pass &= *m_userInfo == *rhsUserInfoPtr;
+    } else {
+      pass &= m_userInfo == rhsUserInfoPtr; // must be both nullptr to pass
+    }
+  }
+
+  {
+    const auto rhsPartLinkPtr = rhs.getParticleLink();
+    if(m_partLink && rhsPartLinkPtr) {
+      pass &= *m_partLink == *rhsPartLinkPtr;
+    } else {
+      pass &= m_partLink == rhsPartLinkPtr; // must be both nullptr to pass
+    }
+  }
+  return pass;
+}
+
+bool ISF::FaserISFParticle::isIdent(const ISF::FaserISFParticle& rhs) const
+{
+  bool pass = true;
+  pass &= m_position == rhs.position();
+  pass &= m_momentum == rhs.momentum();
+  pass &= m_mass == rhs.mass();
+  pass &= m_charge == rhs.charge();
+  pass &= m_pdgCode == rhs.pdgCode();
+  pass &= m_tstamp == rhs.timeStamp();
+  pass &= m_history == rhs.history();
+  pass &= m_barcode == rhs.barcode();
+  pass &= m_bcid == rhs.getBCID();
+  pass &= m_truth && rhs.getTruthBinding();
+  pass &= m_userInfo == rhs.getUserInformation();
+  pass &= m_partLink == rhs.getParticleLink();
+  return pass;
+}
+
+void ISF::FaserISFParticle::setBarcodeAndUpdateHepMcParticleLink( Barcode::ParticleBarcode bc) {
+  // set a new barcode
+  setBarcode(bc);
+
+  //creating/changing the ISFParticle's HepMcParticleLink
+  HepMcParticleLink* newHMPL = nullptr;
+  if (m_partLink) {
+    newHMPL = new HepMcParticleLink(bc, m_partLink->eventIndex(), m_partLink->getEventCollection());
+    delete m_partLink;
+  } else {
+    newHMPL = new HepMcParticleLink(bc);
+  }
+  m_partLink = newHMPL;
+}
diff --git a/Simulation/ISF/ISF_Core/FaserISF_Event/src/FaserParticleHelper.cxx b/Simulation/ISF/ISF_Core/FaserISF_Event/src/FaserParticleHelper.cxx
new file mode 100644
index 00000000..a255fb0e
--- /dev/null
+++ b/Simulation/ISF/ISF_Core/FaserISF_Event/src/FaserParticleHelper.cxx
@@ -0,0 +1,34 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// FaserParticleHelper.cxx, (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+// class include
+#include "FaserISF_Event/FaserParticleHelper.h"
+
+// HepMC includes
+#include "HepMC/GenParticle.h"
+#include "HepMC/Flow.h"
+#include "HepMC/SimpleVector.h" // HepMC::FourVector
+
+// ISF includes
+#include "FaserISF_Event/FaserISFParticle.h"
+
+HepMC::GenParticle* ISF::FaserParticleHelper::convert( const ISF::FaserISFParticle &particle) {
+
+  const Amg::Vector3D &mom = particle.momentum();
+  double mass = particle.mass();
+  double energy = sqrt( mom.mag2() + mass*mass);
+  HepMC::FourVector fourMomentum( mom.x(), mom.y(), mom.z(), energy);
+  int status = 1; // stable particle not decayed by EventGenerator
+
+  auto* hepParticle = new HepMC::GenParticle( fourMomentum, particle.pdgCode(), status );
+  hepParticle->suggest_barcode( particle.barcode() );
+
+  // return a newly created GenParticle
+  return hepParticle;
+}
+
diff --git a/Simulation/ISF/ISF_Core/FaserISF_Interfaces/CMakeLists.txt b/Simulation/ISF/ISF_Core/FaserISF_Interfaces/CMakeLists.txt
new file mode 100644
index 00000000..901c6a10
--- /dev/null
+++ b/Simulation/ISF/ISF_Core/FaserISF_Interfaces/CMakeLists.txt
@@ -0,0 +1,34 @@
+################################################################################
+# Package: FaserISF_Interfaces
+################################################################################
+
+# Declare the package name:
+atlas_subdir( FaserISF_Interfaces )
+
+# Declare the package's dependencies:
+atlas_depends_on_subdirs( PUBLIC
+                          Control/AthenaBaseComps
+                          Control/AthenaKernel
+                          Control/StoreGate
+                          DetectorDescription/FaserDetDescr
+                          DetectorDescription/GeoPrimitives
+                          Generators/GeneratorObjects
+                          GaudiKernel
+                          Generators/GeneratorObjects
+                          Simulation/Barcode/BarcodeEvent
+                          Simulation/G4Sim/TrackRecord
+                          Simulation/ISF/ISF_Core/FaserISF_Event
+                          Simulation/ISF/ISF_Core/ISF_Event )
+
+# External dependencies:
+find_package( CLHEP )
+find_package( Eigen )
+
+# Component(s) in the package:
+atlas_add_library( FaserISF_Interfaces
+                   src/*.cxx
+                   PUBLIC_HEADERS FaserISF_Interfaces
+                   INCLUDE_DIRS ${CLHEP_INCLUDE_DIRS} ${EIGEN_INCLUDE_DIRS}
+                   DEFINITIONS ${CLHEP_DEFINITIONS}
+                   LINK_LIBRARIES ${CLHEP_LIBRARIES} ${EIGEN_LIBRARIES} AthenaBaseComps AthenaKernel FaserDetDescr GeoPrimitives GaudiKernel GeneratorObjects FaserISF_Event ISF_Event StoreGateLib SGtests )
+
diff --git a/Simulation/ISF/ISF_Core/FaserISF_Interfaces/FaserISF_Interfaces/IFaserGeoIDSvc.h b/Simulation/ISF/ISF_Core/FaserISF_Interfaces/FaserISF_Interfaces/IFaserGeoIDSvc.h
new file mode 100644
index 00000000..21075945
--- /dev/null
+++ b/Simulation/ISF/ISF_Core/FaserISF_Interfaces/FaserISF_Interfaces/IFaserGeoIDSvc.h
@@ -0,0 +1,122 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// IFaserGeoIDSvc.h, (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#ifndef ISF_INTERFACES_IFASERGEOIDSVC_H
+#define ISF_INTERFACES_IFASERGEOIDSVC_H 1
+
+// Gaudi
+#include "GaudiKernel/IInterface.h"
+
+// Amg
+#include "GeoPrimitives/GeoPrimitives.h"
+
+// DetectorDescription
+#include "FaserDetDescr/FaserRegion.h"
+
+// ISF Simulation includes
+#include "FaserISF_Event/FaserISFParticle.h" 
+ 
+namespace ISF {
+
+  enum InsideType {
+    fOutside        = 0,
+    fSurface        = 1,
+    fInside         = 2,
+   // to be used to allocate arrays
+    fNumInsideTypes = 3
+  };
+
+  /**
+   @class IFaserGeoIDSvc
+
+   The interface to chose between the sub geometry services,
+   realized as an AlgTool since it does not have to be dynamically created
+   
+   The IFaserGeoIDSvc registers the nextGeoSvcID to the ISFParticle.
+       
+   @author Andreas.Salzburger -at- cern.ch , Elmar.Ritsch -at- cern.ch
+   */
+     
+  class IFaserGeoIDSvc : virtual public IInterface {
+     public:
+     
+       /** Virtual destructor */
+       virtual ~IFaserGeoIDSvc(){}
+
+       /// Creates the InterfaceID and interfaceID() method
+       DeclareInterfaceID(IFaserGeoIDSvc, 1, 0);
+
+       /** Athena algtool's Hooks */
+       virtual StatusCode  initialize() = 0;
+       virtual StatusCode  finalize() = 0;
+
+       /** Checks if the given position (ISFParticle) is inside/outside/onsurface a given FaserRegion */
+       virtual ISF::InsideType inside(const Amg::Vector3D &pos, FaserDetDescr::FaserRegion geoID) const = 0;
+       inline  ISF::InsideType inside(const FaserISFParticle& sp, FaserDetDescr::FaserRegion geoID) const;
+       inline  ISF::InsideType inside(double x, double y, double z, FaserDetDescr::FaserRegion geoID) const;
+
+       /** A static filter that returns the FaserRegion of the given ISFParticle (position)
+            -> returns ISF::fUndefinedGeoID if particle is on surface */
+       virtual FaserDetDescr::FaserRegion identifyGeoID(const Amg::Vector3D &pos) const = 0;
+       inline  FaserDetDescr::FaserRegion identifyGeoID(const FaserISFParticle& sp) const;
+       inline  FaserDetDescr::FaserRegion identifyGeoID(double x, double y, double z) const;
+
+       /** Find the FaserRegion that the particle will enter with its next infinitesimal step
+           along the given direction */
+       virtual FaserDetDescr::FaserRegion identifyNextGeoID(const Amg::Vector3D &pos, const Amg::Vector3D &dir) const = 0;
+       inline  FaserDetDescr::FaserRegion identifyNextGeoID(const FaserISFParticle& sp) const;
+       inline  FaserDetDescr::FaserRegion identifyNextGeoID(double x, double y, double z,
+                                               double dx, double dy, double dz) const;
+
+       /** Find the FaserRegion that the particle will enter with its next infinitesimal step
+           along the given direction, and register this geoID to the particle */
+       inline  FaserDetDescr::FaserRegion identifyAndRegNextGeoID(FaserISFParticle& sp) const;
+  };
+
+
+  // inline methods (basically wrapper for ISFParticle/coord. -> HepGeom::Point3D<double>)
+  //
+  // inside() wrappers
+  inline ISF::InsideType IFaserGeoIDSvc::inside(const FaserISFParticle& sp, FaserDetDescr::FaserRegion geoID) const {
+    return inside( sp.position(), geoID);
+  }
+  inline ISF::InsideType IFaserGeoIDSvc::inside(double x, double y, double z, FaserDetDescr::FaserRegion geoID) const {
+    const Amg::Vector3D pos(x, y, z);
+    return inside( pos, geoID);
+  }
+
+  // identifyGeoID() wrappers
+  inline FaserDetDescr::FaserRegion IFaserGeoIDSvc::identifyGeoID(const FaserISFParticle &sp) const { 
+    return identifyGeoID( sp.position());
+  }
+  inline FaserDetDescr::FaserRegion IFaserGeoIDSvc::identifyGeoID(double x, double y, double z) const { 
+    const Amg::Vector3D pos(x, y, z);
+    return identifyGeoID( pos);
+  }
+
+  // identifyNextGeoID() wrappers
+  inline FaserDetDescr::FaserRegion IFaserGeoIDSvc::identifyNextGeoID(const FaserISFParticle& sp) const {
+    return identifyNextGeoID( sp.position(), sp.momentum());
+  }
+  inline FaserDetDescr::FaserRegion IFaserGeoIDSvc::identifyNextGeoID(double x, double y, double z,
+                                                    double dx, double dy, double dz) const {
+    const Amg::Vector3D pos(x, y, z);
+    const Amg::Vector3D dir(dx, dy, dz);
+    return identifyNextGeoID( pos, dir);
+  }
+
+  // identifyAndRegNextGeoID() wrapper
+  inline  FaserDetDescr::FaserRegion IFaserGeoIDSvc::identifyAndRegNextGeoID( FaserISFParticle& part) const {
+    FaserDetDescr::FaserRegion geoID = identifyNextGeoID( part.position(), part.momentum());
+    part.setNextGeoID(geoID);
+    return geoID;
+  }
+
+} // end of namespace
+
+#endif // ISF_INTERFACES_IFASERGEOIDSVC_H 
diff --git a/Simulation/ISF/ISF_Core/FaserISF_Interfaces/FaserISF_Interfaces/IFaserInputConverter.h b/Simulation/ISF/ISF_Core/FaserISF_Interfaces/FaserISF_Interfaces/IFaserInputConverter.h
new file mode 100644
index 00000000..927a77a2
--- /dev/null
+++ b/Simulation/ISF/ISF_Core/FaserISF_Interfaces/FaserISF_Interfaces/IFaserInputConverter.h
@@ -0,0 +1,73 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// IFaserInputConverter.h, (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#ifndef FASERISF_INTERFACES_IFASERINPUTCONVERTER_H
+#define FASERISF_INTERFACES_IFASERINPUTCONVERTER_H 1
+
+// Gaudi
+#include "GaudiKernel/IInterface.h"
+
+//GeneratorObjects
+#include "GeneratorObjects/HepMcParticleLink.h"
+
+// StoreGate
+#include "StoreGate/ReadHandle.h"
+#include "StoreGate/WriteHandle.h"
+
+// Simulation includes
+#include "FaserISF_Event/FaserISFParticleContainer.h"
+
+// forward declarations
+class McEventCollection;
+class G4Event;
+namespace HepMC {
+  class GenEvent;
+}
+
+namespace ISF {
+
+  class FaserISFParticle;
+
+  /**
+     @class IFaserInputConverter
+
+     Interface to Athena service that converts an input McEventCollection
+     into a container of FaserISFParticles.
+
+     @author Elmar.Ritsch -at- cern.ch
+  */
+
+  class IFaserInputConverter : virtual public IInterface {
+  public:
+
+    /** Virtual destructor */
+    virtual ~IFaserInputConverter(){}
+
+    /** Tell Gaudi which InterfaceID we have */
+    DeclareInterfaceID( ISF::IFaserInputConverter, 1, 0 );
+
+    /** Convert selected particles from the given McEventCollection into ISFParticles
+        and push them into the given ISFParticleContainer */
+    virtual StatusCode convert(const McEventCollection& inputGenEvents,
+                               FaserISFParticleContainer& simParticles,
+                               EBC_EVCOLL kindOfCollection=EBC_MAINEVCOLL) const = 0;
+
+    /** Convert selected particles from the given McEventCollection into G4PrimaryParticles
+        and push them into the given G4Event */
+    virtual StatusCode convertHepMCToG4Event(McEventCollection& inputGenEvents,
+                                             G4Event*& outputG4Event,
+                                             EBC_EVCOLL kindOfCollection=EBC_MAINEVCOLL) const = 0;
+
+    /** Converts vector of ISF::ISFParticles to G4Event */
+    virtual G4Event* ISF_to_G4Event(const std::vector<const ISF::FaserISFParticle*>& isp, HepMC::GenEvent *genEvent) const = 0;
+
+  };
+
+} // end of ISF namespace
+
+#endif // FASERISF_INTERFACES_IFASERINPUTCONVERTER_H
diff --git a/Simulation/ISF/ISF_Core/FaserISF_Interfaces/FaserISF_Interfaces/IFaserTruthSvc.h b/Simulation/ISF/ISF_Core/FaserISF_Interfaces/FaserISF_Interfaces/IFaserTruthSvc.h
new file mode 100644
index 00000000..ff19fca0
--- /dev/null
+++ b/Simulation/ISF/ISF_Core/FaserISF_Interfaces/FaserISF_Interfaces/IFaserTruthSvc.h
@@ -0,0 +1,53 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// IFaserTruthSvc.h, (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+#ifndef FASERISF_INTERFACES_IFASERTRUTHSVC_H
+#define FASERISF_INTERFACES_IFASERTRUTHSVC_H 1
+
+// framework includes
+#include "GaudiKernel/IInterface.h"
+#include "GaudiKernel/StatusCode.h"
+
+// DetectorDescription
+#include "FaserDetDescr/FaserRegion.h"
+
+// forward declarations
+class G4Step;
+
+namespace ISF {
+
+  class IFaserTruthIncident;
+    
+  /** @ class IFaserTruthSvc
+  
+      Interface for the central truth record service to be used by
+      the different simulation services.
+  
+      @ author Andreas.Salzburger -at- cern.ch , Elmar.Ritsch -at- cern.ch
+     */
+    class IFaserTruthSvc : virtual public IInterface { 
+
+      public: 
+        /// Creates the InterfaceID and interfaceID() method
+        DeclareInterfaceID(IFaserTruthSvc, 1, 0);
+      
+        /** virtual desctructor */
+        virtual ~IFaserTruthSvc() { }
+
+        /** Register a truth incident */
+        virtual void registerTruthIncident( IFaserTruthIncident& truthincident) const = 0;
+        
+        /** Initialize the Truth Svc at the beginning of each event */
+        virtual StatusCode initializeTruthCollection() = 0;
+        
+        /** Finalize the Truth Svc at the end of each event*/
+        virtual StatusCode releaseEvent() = 0;
+  }; 
+}
+
+#endif //> !FASERISF_INTERFACES_IFASERTRUTHSVC_H
+
diff --git a/Simulation/ISF/ISF_Core/FaserISF_Services/CMakeLists.txt b/Simulation/ISF/ISF_Core/FaserISF_Services/CMakeLists.txt
new file mode 100644
index 00000000..67cdc047
--- /dev/null
+++ b/Simulation/ISF/ISF_Core/FaserISF_Services/CMakeLists.txt
@@ -0,0 +1,102 @@
+################################################################################
+# Package: FaserISF_Services
+################################################################################
+
+# Declare the package name:
+atlas_subdir( FaserISF_Services )
+
+# Declare the package's dependencies:
+atlas_depends_on_subdirs( PUBLIC
+                          GaudiKernel
+                          PRIVATE
+                          AtlasGeometryCommon/SubDetectorEnvelopes
+                          Control/AthenaBaseComps
+                          Control/StoreGate
+                          DetectorDescription/FaserDetDescr
+                          Generators/GeneratorObjects
+                          Generators/TruthUtils
+                          Tracker/TrackerSimEvent
+                          Scintillator/ScintSimEvent
+                          Simulation/Barcode/BarcodeEvent
+                          Simulation/Barcode/BarcodeInterfaces
+                          Simulation/G4Atlas/G4AtlasInterfaces
+                          Simulation/G4Sim/FaserMCTruth
+                          Simulation/G4Sim/SimHelpers
+                          Simulation/G4Sim/TrackRecord
+                          Simulation/ISF/ISF_Core/ISF_Event
+                          Simulation/ISF/FaserISF_Core/FaserISF_Event
+                          Simulation/ISF/ISF_Core/ISF_Interfaces
+                          Simulation/ISF/ISF_Core/FaserISF_Interfaces
+                          Simulation/ISF/ISF_HepMC/FaserISF_HepMC_Interfaces
+                          Simulation/ISF/ISF_HepMC/ISF_HepMC_Interfaces
+                          Tools/PmbCxxUtils )
+
+# External dependencies:
+find_package( CLHEP )
+find_package( Eigen )
+find_package( Geant4 )
+find_package( HepMC )
+find_package( HepPDT )
+#find_package( GTest )
+#find_package( GMock )
+find_package( ROOT COMPONENTS Core Tree MathCore Hist RIO pthread )
+#find_package( GTest )
+#find_package( GMock )
+
+# Component(s) in the package:
+atlas_add_component( FaserISF_Services
+                     src/*.cxx
+                     src/components/*.cxx
+                     INCLUDE_DIRS ${ROOT_INCLUDE_DIRS} ${GEANT4_INCLUDE_DIRS} ${HEPMC_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS} ${HEPPDT_INCLUDE_DIRS}
+                     LINK_LIBRARIES ${ROOT_LIBRARIES} ${GEANT4_LIBRARIES} ${HEPMC_LIBRARIES} ${CLHEP_LIBRARIES} ${HEPPDT_LIBRARIES} GaudiKernel ScintSimEvent AthenaBaseComps StoreGateLib SGtests FaserDetDescr GeneratorObjects TrackerSimEvent G4AtlasInterfaces FaserMCTruth SimHelpers FaserISF_Event ISF_Event FaserISF_Interfaces ISF_Interfaces PmbCxxUtils TruthUtils )
+
+#atlas_add_test( FaserTruthSvc_test
+#                SOURCES
+#                  test/FaserTruthSvc_test.cxx src/FaserTruthSvc.cxx
+#                INCLUDE_DIRS
+#                  ${GTEST_INCLUDE_DIRS}
+#                  ${GMOCK_INCLUDE_DIRS}
+#                  ${ROOT_INCLUDE_DIRS}
+#                  ${GEANT4_INCLUDE_DIRS}
+#                  ${HEPMC_INCLUDE_DIRS}
+#                  ${CLHEP_INCLUDE_DIRS}
+#                  ${HEPPDT_INCLUDE_DIRS}
+#                LINK_LIBRARIES
+#                  ${GTEST_LIBRARIES}
+#                  ${GMOCK_LIBRARIES}
+#                  ${ROOT_LIBRARIES}
+#                  ${GEANT4_LIBRARIES}
+#                  ${HEPMC_LIBRARIES}
+#                  ${CLHEP_LIBRARIES}
+#                  ${HEPPDT_LIBRARIES}
+#                  GaudiKernel
+#                  ScintSimEvent
+#                  AthenaBaseComps
+#                  StoreGateLib
+#                  TrackerSimEvent
+#                  FaserISF_Event
+#                  ISF_Event
+#                  FaserISF_Interfaces
+#                  ISF_Interfaces
+#                  PmbCxxUtils
+#                  FaserMCTruth
+#                  TruthUtils
+#                ENVIRONMENT
+#                  "JOBOPTSEARCHPATH=${CMAKE_CURRENT_SOURCE_DIR}/test"
+#                )
+
+#test FaserISF_ServicesConfigNew
+#atlas_add_test( FaserISF_ServicesConfigNew_test
+#                SCRIPT test/FaserISF_ServicesConfigNew_test.py
+#                WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
+#                PROPERTIES TIMEOUT 300 )
+
+
+
+# Needed for the plugin service to see the test components
+# defined in the test binary.
+#set_target_properties( FaserISF_Services_FaserTruthSvc_test PROPERTIES ENABLE_EXPORTS True )
+
+# Install files from the package:
+atlas_install_python_modules( python/*.py )
+
diff --git a/Simulation/ISF/ISF_Core/FaserISF_Services/python/FaserISF_ServicesConfigNew.py b/Simulation/ISF/ISF_Core/FaserISF_Services/python/FaserISF_ServicesConfigNew.py
new file mode 100644
index 00000000..0a839b88
--- /dev/null
+++ b/Simulation/ISF/ISF_Core/FaserISF_Services/python/FaserISF_ServicesConfigNew.py
@@ -0,0 +1,142 @@
+# Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+
+"""
+Service configurations for ISF
+KG Tan, 17/06/2012
+"""
+
+from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator
+from AthenaConfiguration.ComponentFactory import CompFactory
+
+from BarcodeServices.BarcodeServicesConfigNew import MC15aPlusBarcodeSvcCfg
+from ISF_HepMC_Tools.ISF_HepMC_ToolsConfigNew import ParticleFinalStateFilterCfg, GenParticleInteractingFilterCfg
+#from FaserISF_HepMC_Tools.FaserISF_HepMC_ToolsConfigNew import FaserParticlePositionFilterCfg, FaserParticleGenericFilterCfg
+from FaserISF_HepMC_Tools.FaserISF_HepMC_ToolsConfigNew import FaserTruthStrategyCfg
+
+# from ISF_HepMC_Tools.ISF_HepMC_ToolsConfigNew import TruthStrategyGroupID_MC15Cfg, TruthStrategyGroupCaloMuBremCfg, TruthStrategyGroupCaloDecay_MC15Cfg, TruthStrategyGroupIDHadInt_MC15Cfg, ParticleFinalStateFilterCfg, ParticlePositionFilterDynamicCfg, EtaPhiFilterCfg, GenParticleInteractingFilterCfg
+# from SubDetectorEnvelopes.SubDetectorEnvelopesConfigNew import EnvelopeDefSvcCfg
+
+
+ISF__FaserTruthSvc, ISF__FaserGeoIDSvc, ISF__FaserInputConverter = CompFactory.getComps("ISF__FaserTruthSvc","ISF__FaserGeoIDSvc","ISF__FaserInputConverter")
+
+#Functions yet to be migrated:
+#getParticleBrokerSvcNoOrdering, getParticleBrokerSvc, getAFIIParticleBrokerSvc, getAFIIEnvelopeDefSvc, getAFIIGeoIDSvc
+#getLongLivedInputConverter, getValidationTruthService, getMC12BeamPipeTruthStrategies, getMC12IDTruthStrategies
+#getMC12CaloTruthStrategies, getMC12MSTruthStrategies, getMC12TruthService, getTruthService, getMC12LLPTruthService, getMC12PlusTruthService,  getMC15IDTruthStrategies
+#getMC15CaloTruthStrategies
+
+def FaserGeoIDSvcCfg(ConfigFlags, name="ISF_FaserGeoIDSvc", **kwargs):
+    result = ComponentAccumulator()
+
+    result.addService(ISF__FaserGeoIDSvc(name, **kwargs))
+
+    return result
+
+def GenParticleFiltersToolCfg(ConfigFlags):
+    result = ComponentAccumulator()
+
+    #acc1 = ParticlePositionFilterDynamicCfg(ConfigFlags)
+    genParticleFilterList = []
+
+    acc1 = ParticleFinalStateFilterCfg(ConfigFlags)
+    genParticleFilterList += [result.popToolsAndMerge(acc1)]
+
+    # acc2 = ParticlePositionFilterDynamicCfg(ConfigFlags)
+    # genParticleFilterList += [result.popToolsAndMerge(acc2)]
+
+    # acc3 = EtaPhiFilterCfg(ConfigFlags)
+    # genParticleFilterList += [result.popToolsAndMerge(acc3)]
+
+    acc4 = GenParticleInteractingFilterCfg(ConfigFlags)
+    genParticleFilterList += [result.popToolsAndMerge(acc4)]
+
+    result.setPrivateTools(genParticleFilterList)
+    return result
+
+
+def FaserInputConverterCfg(ConfigFlags, name="ISF_FaserInputConverter", **kwargs):
+    result = ComponentAccumulator()
+
+    #just use this barcodeSvc for now. TODO - make configurable
+    #from G4AtlasApps.SimFlags import simFlags
+    #kwargs.setdefault('BarcodeSvc', simFlags.TruthStrategy.BarcodeServiceName())
+    result = MC15aPlusBarcodeSvcCfg(ConfigFlags)
+    kwargs.setdefault('BarcodeSvc', result.getService("Barcode_MC15aPlusBarcodeSvc") )
+
+    kwargs.setdefault("UseGeneratedParticleMass", False)
+
+    acc_GenParticleFiltersList = GenParticleFiltersToolCfg(ConfigFlags)
+    kwargs.setdefault("GenParticleFilters", result.popToolsAndMerge(acc_GenParticleFiltersList) )
+
+    result.addService(ISF__FaserInputConverter(name, **kwargs))
+    return result
+
+#
+# Generic Truth Service Configurations
+#
+def FaserTruthServiceCfg(ConfigFlags, name="FaserISF_TruthService", **kwargs):
+    result = MC15aPlusBarcodeSvcCfg(ConfigFlags)
+    kwargs.setdefault('BarcodeSvc', result.getService("Barcode_MC15aPlusBarcodeSvc") )
+    
+    acc = FaserTruthStrategyCfg(ConfigFlags)
+    kwargs.setdefault('TruthStrategies',[result.popToolsAndMerge(acc)])
+
+    kwargs.setdefault('SkipIfNoChildren', True)
+    kwargs.setdefault('SkipIfNoParentBarcode', True)
+
+    import ROOT, cppyy
+    cppyy.loadDictionary('FaserDetDescrDict')
+    FaserRegion = ROOT.FaserDetDescr
+
+    kwargs.setdefault('ForceEndVtxInRegions', [FaserRegion.fFaserNeutrino,
+                                               FaserRegion.fFaserScintillator,
+                                               FaserRegion.fFaserTracker,
+                                               FaserRegion.fFaserDipole,
+                                               FaserRegion.fFaserCalorimeter,
+                                               FaserRegion.fFaserCavern])
+                                               
+    #long_lived_simulators = ['LongLived', 'longLived', 'QS']
+    #from ISF_Config.ISF_jobProperties import ISF_Flags
+    #is_long_lived_simulation = any(x in ISF_Flags.Simulator() for x in long_lived_simulators) #FIXME this should be set in a nicer way.
+    is_long_lived_simulation = True
+    if is_long_lived_simulation:
+        kwargs.setdefault('QuasiStableParticlesIncluded', True)
+
+    result.addService(ISF__FaserTruthSvc(name, **kwargs))
+    return result
+
+
+# def MC15TruthServiceCfg(ConfigFlags, name="ISF_MC15TruthService", **kwargs):
+#     result = ComponentAccumulator()
+#     # importing Reflex dictionary to access AtlasDetDescr::AtlasRegion enum
+#     import ROOT, cppyy
+#     cppyy.loadDictionary('AtlasDetDescrDict')
+#     AtlasRegion = ROOT.AtlasDetDescr
+
+#     acc1 = TruthStrategyGroupID_MC15Cfg(ConfigFlags)
+#     acc2 = TruthStrategyGroupIDHadInt_MC15Cfg(ConfigFlags)
+#     acc3 = TruthStrategyGroupCaloMuBremCfg(ConfigFlags)
+#     acc4 = TruthStrategyGroupCaloDecay_MC15Cfg(ConfigFlags)
+
+#     kwargs.setdefault('TruthStrategies', [result.popToolsAndMerge(acc1),
+#                                           result.popToolsAndMerge(acc2),
+#                                           result.popToolsAndMerge(acc3), #FIXME this should be ISF_MCTruthStrategyGroupCaloMuBrem_MC15!!
+#                                           result.popToolsAndMerge(acc4)])
+
+
+#     kwargs.setdefault('IgnoreUndefinedBarcodes', False)
+#     kwargs.setdefault('PassWholeVertices', False) # new for MC15 - can write out partial vertices.
+#     kwargs.setdefault('ForceEndVtxInRegions', [AtlasRegion.fAtlasID])
+#     accTruthService = GenericTruthServiceCfg(ConfigFlags, name, **kwargs)
+#     result.merge(accTruthService)
+#     return result
+
+
+# def MC15aPlusTruthServiceCfg(ConfigFlags, name="ISF_MC15aPlusTruthService", **kwargs):
+#     # importing Reflex dictionary to access AtlasDetDescr::AtlasRegion enum
+#     import ROOT, cppyy
+#     cppyy.loadDictionary('AtlasDetDescrDict')
+#     AtlasRegion = ROOT.AtlasDetDescr
+#     kwargs.setdefault('ForceEndVtxInRegions', [AtlasRegion.fAtlasID])
+#     result = MC15TruthServiceCfg(ConfigFlags, name, **kwargs)
+#     return result
diff --git a/Simulation/ISF/ISF_Core/FaserISF_Services/src/FaserGeoIDSvc.cxx b/Simulation/ISF/ISF_Core/FaserISF_Services/src/FaserGeoIDSvc.cxx
new file mode 100644
index 00000000..ed4a3370
--- /dev/null
+++ b/Simulation/ISF/ISF_Core/FaserISF_Services/src/FaserGeoIDSvc.cxx
@@ -0,0 +1,147 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// GeoIDSvc.cxx, (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+// class header include
+#include "FaserGeoIDSvc.h"
+
+// framework includes
+#include "GaudiKernel/Bootstrap.h"
+#include "GaudiKernel/ISvcLocator.h"
+
+// DetectorDescription
+#include "FaserDetDescr/FaserRegionHelper.h"
+
+// Geant4
+#include "G4Navigator.hh"
+#include "G4TransportationManager.hh"
+#include "G4VPhysicalVolume.hh"
+#include "G4TouchableHistoryHandle.hh"
+
+// STL includes
+#include <algorithm>
+
+/** Constructor **/
+ISF::FaserGeoIDSvc::FaserGeoIDSvc(const std::string& name,ISvcLocator* svc) :
+  base_class(name,svc), m_navigator { nullptr }
+{ }
+
+
+/** Destructor **/
+ISF::FaserGeoIDSvc::~FaserGeoIDSvc()
+{ 
+  if (m_navigator != nullptr)
+  {
+    delete m_navigator;
+    m_navigator = nullptr;
+  }
+}
+
+
+// Athena algtool's Hooks
+StatusCode  ISF::FaserGeoIDSvc::initialize()
+{
+  ATH_MSG_INFO("initialize() ...");
+
+  G4VPhysicalVolume* world = G4TransportationManager::GetTransportationManager()->GetNavigatorForTracking()->GetWorldVolume();
+  if (world == nullptr)
+  {
+    ATH_MSG_FATAL("Unable to retrieve Geant4 world volume.");
+    return StatusCode::FAILURE;
+  }
+
+  m_navigator = new G4Navigator();
+  if (m_navigator == nullptr)
+  {
+    ATH_MSG_FATAL("Unable to create private navigator");
+    return StatusCode::FAILURE;
+  }
+  m_navigator->SetWorldVolume(world);
+
+  //  ATH_MSG_INFO("initialize() successful");
+  return StatusCode::SUCCESS;
+}
+
+
+StatusCode  ISF::FaserGeoIDSvc::finalize() {
+  ATH_MSG_INFO("finalize() ...");
+
+  // ATH_MSG_INFO("finalize() successful");
+  return StatusCode::SUCCESS;
+}
+
+
+ISF::InsideType ISF::FaserGeoIDSvc::inside(const Amg::Vector3D& pos, FaserDetDescr::FaserRegion geoID) const 
+{
+
+  // an arbitrary unitary direction with +1 in x,y,z
+  // (following this direction will cross any FaserRegion boundary if position is close to it in the first place)
+  const Amg::Vector3D dir(1., 1., 1.);
+  const Amg::Vector3D dirUnit( dir.unit() );
+
+  // create particle positions which are a bit forward and a bit aft of the current position
+  const Amg::Vector3D posFwd( pos + dirUnit*m_tolerance );
+  const Amg::Vector3D posAft( pos - dirUnit*m_tolerance );
+
+  FaserDetDescr::FaserRegion geoIDFwd = identifyGeoID(posFwd);
+  FaserDetDescr::FaserRegion geoIDAft = identifyGeoID(posAft);
+
+  // default case: particle is outside given geoID
+  ISF::InsideType where = ISF::fOutside;
+
+  // only if either the fwd or the aft step is inside the given geoID,
+  // inside/surface cases need to be resolved
+  if ( (geoID == geoIDFwd) || (geoID == geoIDAft) ) {
+    // 1. inside
+    if ( geoIDFwd == geoIDAft ) {
+      where = ISF::fInside;
+      // 2. surface
+    } else if ( geoIDFwd != geoIDAft ) {
+      where = ISF::fSurface;
+    }
+  }
+
+  return where;
+}
+
+FaserDetDescr::FaserRegion ISF::FaserGeoIDSvc::identifyGeoID(const Amg::Vector3D& pos) const 
+{
+  m_navigator->LocateGlobalPointAndSetup(G4ThreeVector(pos.x(), pos.y(), pos.z()));
+  G4TouchableHistoryHandle pHistory = m_navigator->CreateTouchableHistoryHandle();
+  if (pHistory->GetHistoryDepth() <= 0) return FaserDetDescr::fFaserCavern;
+
+  // Search upward through volume hierarchy until we find something intelligible
+  for (G4int level = 0; level <= pHistory->GetHistoryDepth(); level++)
+  {
+    G4String lvName = pHistory->GetVolume(level)->GetLogicalVolume()->GetName();
+
+    if (lvName == "SCT::SCT" || lvName == "SCT::Station") return FaserDetDescr::fFaserTracker;
+
+    if (lvName == "Veto::Veto"           || lvName == "Veto::VetoStationA"          ||
+        lvName == "Trigger::Trigger"     || lvName == "Trigger::TriggerStationA"    ||
+        lvName == "Preshower::Preshower" || lvName == "Preshower::PreshowerStationA") return FaserDetDescr::fFaserScintillator;
+    
+    if (lvName == "Ecal::Ecal") return FaserDetDescr::fFaserCalorimeter;
+
+    if (lvName == "Emulsion::Emulsion" || lvName == "Emulsion::EmulsionStationA" ) return FaserDetDescr::fFaserNeutrino;
+
+    if (lvName == "Dipole::Dipole") return FaserDetDescr::fFaserDipole;
+  }
+
+  // If all else fails
+  return FaserDetDescr::fFaserCavern;
+}
+
+
+FaserDetDescr::FaserRegion ISF::FaserGeoIDSvc::identifyNextGeoID(const Amg::Vector3D& pos,
+                                                            const Amg::Vector3D& dir) const 
+{
+  FaserDetDescr::FaserRegion geoID = identifyGeoID( pos + dir.unit()*m_tolerance );
+
+  return geoID;
+}
+
diff --git a/Simulation/G4Faser/G4FaserServices/src/FaserGeoIDSvc.h b/Simulation/ISF/ISF_Core/FaserISF_Services/src/FaserGeoIDSvc.h
similarity index 61%
rename from Simulation/G4Faser/G4FaserServices/src/FaserGeoIDSvc.h
rename to Simulation/ISF/ISF_Core/FaserISF_Services/src/FaserGeoIDSvc.h
index 5faf5ff6..34933fcd 100644
--- a/Simulation/G4Faser/G4FaserServices/src/FaserGeoIDSvc.h
+++ b/Simulation/ISF/ISF_Core/FaserISF_Services/src/FaserGeoIDSvc.h
@@ -6,8 +6,8 @@
 // FaserGeoIDSvc.h, (c) ATLAS Detector software
 ///////////////////////////////////////////////////////////////////
 
-#ifndef G4FASERSERVICES_FASERGEOIDSVC_H
-#define G4FASERSERVICES_FASERGEOIDSVC_H 1
+#ifndef ISF_FASERSERVICES_FASERGEOIDSVC_H
+#define ISF_FASERSERVICES_FASERGEOIDSVC_H 1
 
 // framework includes
 #include "GaudiKernel/ServiceHandle.h"
@@ -19,23 +19,25 @@
 #include <set>
 
 // DetectorDescription
-#include "AtlasDetDescr/AtlasRegion.h"
+#include "FaserDetDescr/FaserRegion.h"
 
 // ISF includes
-#include "ISF_Interfaces/IGeoIDSvc.h"
+#include "FaserISF_Interfaces/IFaserGeoIDSvc.h"
+
+// Geant4
+class G4Navigator;
 
 namespace ISF {
 
   /** @class GeoIDSvc
   
-      A fast Athena service identifying the AtlasRegion a given position/particle is in.
+      A fast Athena service identifying the FaserRegion a given position/particle is in.
 
       @author Elmar.Ritsch -at- cern.ch
 
-      This dummy version for FASER says that everything is in the "undefined" ATLAS region
   
      */
-  class FaserGeoIDSvc : public extends<AthService, ISF::IGeoIDSvc> {
+  class FaserGeoIDSvc : public extends<AthService, ISF::IFaserGeoIDSvc> {
     public: 
      /** Constructor with parameters */
      FaserGeoIDSvc(const std::string& name,ISvcLocator* svc);
@@ -48,19 +50,20 @@ namespace ISF {
      StatusCode  finalize();
 
      /** A static filter that returns the SimGeoID of the given position */
-     AtlasDetDescr::AtlasRegion    identifyGeoID(const Amg::Vector3D &pos) const;
+     FaserDetDescr::FaserRegion  identifyGeoID(const Amg::Vector3D &pos) const;
 
      /** Checks if the given position (or ISFParticle) is inside a given SimGeoID */
-     ISF::InsideType inside(const Amg::Vector3D &pos, AtlasDetDescr::AtlasRegion geoID) const;
+     ISF::InsideType inside(const Amg::Vector3D &pos, FaserDetDescr::FaserRegion geoID) const;
 
      /** Find the SimGeoID that the particle will enter with its next infinitesimal step
          along the given direction */
-     AtlasDetDescr::AtlasRegion identifyNextGeoID(const Amg::Vector3D &pos, const Amg::Vector3D &dir) const;
+     FaserDetDescr::FaserRegion identifyNextGeoID(const Amg::Vector3D &pos, const Amg::Vector3D &dir) const;
 
     private:
-
+      Gaudi::Property<double>     m_tolerance { this, "Tolerance", 1.0e-5, "Tolerance for being on surface" };
+      G4Navigator*                m_navigator;
    }; 
   
 } // ISF namespace
 
-#endif //> !FASERSERVICES_FASERGEOIDSVC_H
+#endif //> !ISF_FASERSERVICES_FASERGEOIDSVC_H
diff --git a/Simulation/ISF/ISF_Core/FaserISF_Services/src/FaserInputConverter.cxx b/Simulation/ISF/ISF_Core/FaserISF_Services/src/FaserInputConverter.cxx
new file mode 100644
index 00000000..da6cfd0f
--- /dev/null
+++ b/Simulation/ISF/ISF_Core/FaserISF_Services/src/FaserInputConverter.cxx
@@ -0,0 +1,618 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// InputConverter.cxx, (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+// class header include
+#include "FaserInputConverter.h"
+
+#include <memory>
+
+// framework
+#include "GaudiKernel/IPartPropSvc.h"
+#include "GaudiKernel/PhysicalConstants.h"
+
+// ISF_HepMC include
+#include "ISF_Event/TruthBinding.h"
+#include "ISF_HepMC_Interfaces/IGenParticleFilter.h"
+// barcode event and interfaces for bc creation
+#include "BarcodeEvent/Barcode.h"
+#include "BarcodeInterfaces/IBarcodeSvc.h"
+// ISF_Event include
+#include "FaserISF_Event/FaserISFParticle.h"
+#include "FaserISF_Event/FaserISFParticleContainer.h"
+#include "FaserISF_Event/FaserISFParticleVector.h"
+#include "ISF_Event/ParticleUserInformation.h"
+// MCTruth includes
+#include "FaserMCTruth/FaserPrimaryParticleInformation.h"
+#include "FaserMCTruth/FaserEventInformation.h"
+// McEventCollection
+#include "GeneratorObjects/McEventCollection.h"
+// Geant4 includes
+#include "G4PrimaryParticle.hh"
+#include "G4Event.hh"
+#include "G4Geantino.hh"
+#include "G4ChargedGeantino.hh"
+#include "G4ParticleTable.hh"
+#include "G4LorentzVector.hh"
+#include "G4TransportationManager.hh"
+// HepMC includes
+#include "HepMC/GenParticle.h"
+#include "HepMC/GenEvent.h"
+// CLHEP includes
+#include "CLHEP/Geometry/Point3D.h"
+#include "CLHEP/Geometry/Vector3D.h"
+// HepPDT
+#include "HepPDT/ParticleID.hh"
+#include "HepPDT/DecayData.hh"
+#include "HepPDT/ParticleDataTable.hh"
+
+
+/** Constructor **/
+ISF::FaserInputConverter::FaserInputConverter(const std::string& name, ISvcLocator* svc)
+    : base_class(name, svc)
+    , m_particlePropSvc("PartPropSvc",name)
+    , m_particleDataTable(nullptr)
+    , m_useGeneratedParticleMass(false)
+    , m_genParticleFilters(this)
+    , m_quasiStableParticlesIncluded(false)
+    , m_barcodeSvc("", name)
+    , m_barcodeGenerationIncrement(Barcode::fUndefinedBarcode)
+{
+  // particle mass from particle data table?
+  declareProperty("UseGeneratedParticleMass",
+                  m_useGeneratedParticleMass,
+                  "Use particle mass assigned to GenParticle.");
+  // particle filters
+  declareProperty("GenParticleFilters",
+                  m_genParticleFilters,
+                  "Tools for filtering out GenParticles.");
+  // the particle property service
+  declareProperty("ParticlePropertyService",
+                  m_particlePropSvc,
+                  "ParticlePropertyService to retrieve the PDT.");
+  // the barcode service (used to compute Vertex Barcodes)
+  declareProperty("BarcodeSvc",                 m_barcodeSvc           );
+  declareProperty("QuasiStableParticlesIncluded", m_quasiStableParticlesIncluded);
+}
+
+
+/** Destructor **/
+ISF::FaserInputConverter::~FaserInputConverter()
+{
+}
+
+
+// Athena algtool's Hooks
+StatusCode
+ISF::FaserInputConverter::initialize()
+{
+  ATH_MSG_VERBOSE("initialize() begin");
+
+  // retrieve BarcodeSvc
+  ATH_CHECK(m_barcodeSvc.retrieve());
+  m_barcodeGenerationIncrement = m_barcodeSvc->particleGenerationIncrement();
+  if (m_barcodeGenerationIncrement == Barcode::fUndefinedBarcode) {
+    ATH_MSG_FATAL( "'Barcode::fUndefinedBarcode' returned as 'BarcodeGenerationIncrement' by BarcodeService. Abort." );
+    return StatusCode::FAILURE;
+  }
+
+  // setup PDT if requested (to get particle masses later on)
+  if (!m_useGeneratedParticleMass) {
+    ATH_CHECK(m_particlePropSvc.retrieve());
+    m_particleDataTable = m_particlePropSvc->PDT();
+    if (!m_particleDataTable) {
+      ATH_MSG_FATAL( "Could not get ParticleDataTable from " << m_particlePropSvc << ". Abort" );
+      return StatusCode::FAILURE;
+    }
+  }
+
+  if (!m_genParticleFilters.empty()) {
+    ATH_CHECK(m_genParticleFilters.retrieve());
+  }
+
+  ATH_MSG_VERBOSE("initialize() successful");
+  return StatusCode::SUCCESS;
+}
+
+
+/** Athena algtool Hook */
+StatusCode
+ISF::FaserInputConverter::finalize()
+{
+  ATH_MSG_DEBUG("Finalizing ...");
+  return StatusCode::SUCCESS;
+}
+
+
+/** Convert selected particles from the given McEventCollection into ISFParticles
+    and push them into the given ISFParticleContainer */
+StatusCode
+ISF::FaserInputConverter::convert(const McEventCollection& inputGenEvents,
+                                  ISF::FaserISFParticleContainer& simParticles,
+                                  EBC_EVCOLL kindOfCollection) const
+{
+  for ( const auto& eventPtr : inputGenEvents ) {
+    // skip empty events
+    if (eventPtr == nullptr) { continue; }
+
+    ATH_MSG_DEBUG("Starting conversion of GenEvent with"
+                  " signal_process_id=" << eventPtr->signal_process_id() <<
+                  " and event_number=" << eventPtr->event_number() );
+
+    // new collection containing all gen particles that passed filters
+    bool legacyOrdering = true; // FIXME: this is only to keep the same order of particles
+                                //        as the prior 'StackFiller' implementation
+                                // TODO:  remove this functionality from the
+                                //        getSelectedParticles function once
+                                //        happy with the results
+    const auto passedGenParticles = getSelectedParticles(*eventPtr, legacyOrdering);
+
+    for ( auto& genPartPtr : passedGenParticles ) {
+      ATH_MSG_VERBOSE("Picking up following GenParticle for conversion to ISFParticle: " <<  *genPartPtr);
+      auto simParticlePtr = convertParticle(genPartPtr, kindOfCollection);
+      if (!simParticlePtr) {
+        ATH_MSG_ERROR("Error while trying to convert input generator particles. Aborting.");
+        return StatusCode::FAILURE;
+      }
+      // add to collection that will be returned
+      simParticles.push_back(simParticlePtr);
+
+    } // loop over passed gen particles
+
+  } // loop over gen events
+
+  ATH_MSG_DEBUG( "Created initial simulation particle collection with size " << simParticles.size() );
+
+  return StatusCode::SUCCESS;
+}
+
+StatusCode ISF::FaserInputConverter::convertHepMCToG4Event(McEventCollection& inputGenEvents,
+                                                           G4Event*& outputG4Event,
+                                                           EBC_EVCOLL kindOfCollection) const
+{
+  ISF::FaserISFParticleContainer simParticleList{}; // particles for ISF simulation
+  ATH_CHECK(this->convert(inputGenEvents, simParticleList, kindOfCollection));
+  //Convert from FaserISFParticleContainer to ConstFaserISFParticleVector
+  ISF::ConstFaserISFParticleVector simParticleVector{std::make_move_iterator(std::begin(simParticleList)),
+                                                     std::make_move_iterator(std::end(simParticleList))};
+  outputG4Event = this->ISF_to_G4Event(simParticleVector, inputGenEvents.back());
+  return StatusCode::SUCCESS;
+}
+
+
+/** get all generator particles which pass filters */
+std::vector<HepMC::GenParticle*>
+ISF::FaserInputConverter::getSelectedParticles(const HepMC::GenEvent& evnt, bool legacyOrdering) const {
+  auto allGenPartBegin = evnt.particles_begin();
+  auto allGenPartEnd = evnt.particles_end();
+
+  // reserve destination container with maximum size, i.e. number of particles in input event
+  std::vector<HepMC::GenParticle*> passedGenParticles{};
+  size_t maxParticles = std::distance(allGenPartBegin, allGenPartEnd);
+  passedGenParticles.reserve(maxParticles);
+
+  if (legacyOrdering) {
+    // FIXME: remove this block and the 'legacyOrdering' flag
+    //        once we don't need the legacy order any longer
+    auto vtxIt = evnt.vertices_begin();
+    auto vtxItEnd = evnt.vertices_end();
+    for ( ; vtxIt != vtxItEnd; ++vtxIt ) {
+      const auto vtxPtr = *vtxIt;
+      std::copy_if(vtxPtr->particles_begin(HepMC::children),
+                   vtxPtr->particles_end(HepMC::children),
+                   std::back_inserter(passedGenParticles),
+                   [this](HepMC::GenParticle* p){return this->passesFilters(*p);});
+    }
+  }
+  else {
+    std::copy_if(allGenPartBegin,
+                 allGenPartEnd,
+                 std::back_inserter(passedGenParticles),
+                 [this](HepMC::GenParticle* p){return this->passesFilters(*p);});
+  }
+
+  passedGenParticles.shrink_to_fit();
+
+  return passedGenParticles;
+}
+
+
+/** get all generator particles which pass filters */
+ISF::FaserISFParticle*
+ISF::FaserInputConverter::convertParticle(HepMC::GenParticle* genPartPtr, EBC_EVCOLL kindOfCollection) const {
+  if (!genPartPtr) { return nullptr; }
+  auto& genPart = *genPartPtr;
+
+  // @FIXME: set the bunch-crossing identifier for pile-up dynamically
+  // rather than a constant '1' (e.g. could use GenEvent index for that?)
+  const int bcid = (kindOfCollection==EBC_MAINEVCOLL) ? 0 : 1;
+
+  HepMC::GenVertex* pVertex = genPart.production_vertex();
+  if (!pVertex) {
+    ATH_MSG_ERROR("Unable to convert following generator particle due to missing "
+                  << "production vertex: " << genPart);
+    return nullptr;
+  }
+
+  const auto& pVertexPos(pVertex->point3d());
+  const Amg::Vector3D pos(pVertexPos.x(), pVertexPos.y(), pVertexPos.z());
+  const auto& pMomentum(genPart.momentum());
+  const Amg::Vector3D mom(pMomentum.px(), pMomentum.py(), pMomentum.pz());
+  const double pMass = this->getParticleMass(genPart);
+  const int pPdgId = genPart.pdg_id();
+  const double charge = HepPDT::ParticleID(pPdgId).charge();
+  const double pTime = pVertex->position().t() / Gaudi::Units::c_light;
+  /// particle origin (TODO: add proper GeoID, collision/cosmics)
+  FaserDetRegionSvcIDPair origin(FaserDetDescr::fUndefinedFaserRegion, ISF::fEventGeneratorSimID);
+  const auto pBarcode = genPart.barcode();
+  auto tBinding = std::make_unique<ISF::TruthBinding>(genPartPtr);
+
+  auto *parentEvent = genPart.parent_event();
+  if(!parentEvent) {
+    ATH_MSG_ERROR("Cannot convert a GenParticle without a parent GenEvent into a FaserISFParticle!!!");
+    return nullptr;
+  }
+  auto hmpl = std::make_unique<HepMcParticleLink>(&genPart, parentEvent->event_number(), kindOfCollection);
+  auto sParticle = std::make_unique<ISF::FaserISFParticle>( std::move(pos),
+                                                            std::move(mom),
+                                                            pMass,
+                                                            charge,
+                                                            pPdgId,
+                                                            pTime,
+                                                            origin,
+                                                            bcid,
+                                                            pBarcode,
+                                                            tBinding.release(),
+                                                            hmpl.release() );
+  return sParticle.release();
+}
+
+
+/** get right GenParticle mass */
+double
+ISF::FaserInputConverter::getParticleMass(const HepMC::GenParticle &part) const
+{
+  // default value: generated particle mass
+  double mass = part.generated_mass();
+  ATH_MSG_VERBOSE("part.generated_mass, mass="<<mass);
+
+  // 1. use PDT mass?
+  if ( !m_useGeneratedParticleMass ) {
+    const int absPDG = std::abs(part.pdg_id());
+    HepPDT::ParticleData const *pData = (m_particleDataTable)
+      ? m_particleDataTable->particle(absPDG)
+      : nullptr;
+    if (pData) {
+      mass = pData->mass();
+      ATH_MSG_VERBOSE("using pData mass, mass="<<mass);
+    }
+    else {
+      ATH_MSG_WARNING( "Unable to find mass of particle with PDG ID '" << absPDG << "' in ParticleDataTable. Will set mass to generated_mass: " << mass);
+    }
+  }
+  return mass;
+}
+
+
+/** check if the given particle passes all filters */
+bool
+ISF::FaserInputConverter::passesFilters(const HepMC::GenParticle& part) const
+{
+  // TODO: implement this as a std::find_if with a lambda function
+  for ( const auto& filter : m_genParticleFilters ) {
+    // determine if the particle passes current filter
+    bool passFilter = filter->pass(part);
+    ATH_MSG_VERBOSE("GenParticleFilter '" << filter.typeAndName() << "' returned: "
+                    << (passFilter ? "true, will keep particle."
+                        : "false, will remove particle."));
+    const auto& momentum = part.momentum();
+    ATH_MSG_VERBOSE("Particle: ("
+                    <<momentum.px()<<", "
+                    <<momentum.py()<<", "
+                    <<momentum.pz()<<"), pdgCode: "
+                    <<part.pdg_id() );
+
+    if (!passFilter) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
+
+//________________________________________________________________________
+G4Event* ISF::FaserInputConverter::ISF_to_G4Event(const ISF::ConstFaserISFParticleVector& ispVector, HepMC::GenEvent *genEvent) const
+{
+  const int eventID(1);
+  G4Event *g4evt = new G4Event(eventID);
+
+  // retrieve world solid (volume)
+  const G4VSolid *worldSolid = G4TransportationManager::GetTransportationManager()->GetNavigatorForTracking()->GetWorldVolume()->GetLogicalVolume()->GetSolid();
+
+  int n_pp=0;
+  for ( const ISF::FaserISFParticle *ispPtr: ispVector ) {
+    const ISF::FaserISFParticle &isp = *ispPtr;
+    if ( !isInsideG4WorldVolume(isp, worldSolid) ) {
+        ATH_MSG_WARNING("Unable to convert FaserISFParticle to G4PrimaryParticle!");
+        ATH_MSG_WARNING(" FaserISFParticle: " << isp );
+        if(worldSolid) {
+          ATH_MSG_WARNING(" is outside Geant4 world volume: ");
+          worldSolid->DumpInfo();
+          G4cout << std::flush;
+        }
+        else {
+          ATH_MSG_WARNING(" is outside Geant4 world volume.");
+	}
+        continue;
+    }
+    this->addG4PrimaryVertex(g4evt,isp);
+    n_pp++;
+  }
+
+  FaserEventInformation *eventInfo=new FaserEventInformation();
+  eventInfo->SetNrOfPrimaryParticles(n_pp);
+  eventInfo->SetNrOfPrimaryVertices(n_pp); // special case for ISF batches of particles
+  eventInfo->SetHepMCEvent(genEvent);
+  g4evt->SetUserInformation(eventInfo);
+
+  return g4evt;
+}
+
+//________________________________________________________________________
+const G4ParticleDefinition* ISF::FaserInputConverter::getG4ParticleDefinition(int pdgcode) const
+{
+  /// Special cases for Geantinos
+  if (pdgcode==998) {
+    return G4ChargedGeantino::Definition();
+  }
+  if (pdgcode==999) {
+    return G4Geantino::GeantinoDefinition();
+  }
+  /// Standard particles
+  G4ParticleTable *ptable = G4ParticleTable::GetParticleTable();
+  if(ptable) {
+    return ptable->FindParticle(pdgcode);
+  }
+  ATH_MSG_ERROR("getG4ParticleDefinition - Failed to retrieve G4ParticleTable!");
+  return nullptr;
+}
+
+//________________________________________________________________________
+G4PrimaryParticle* ISF::FaserInputConverter::getG4PrimaryParticle(const HepMC::GenParticle& genpart) const
+{
+  ATH_MSG_VERBOSE("Creating G4PrimaryParticle from GenParticle.");
+
+  const G4ParticleDefinition *particleDefinition = this->getG4ParticleDefinition(genpart.pdg_id());
+
+  if(particleDefinition==nullptr) {
+    ATH_MSG_ERROR("ISF_to_G4Event particle conversion failed. FaserISF_Particle PDG code = " << genpart.pdg_id() <<
+                  "\n This usually indicates a problem with the evgen step.\n" <<
+                  "Please report this to the Generators group, mentioning the release and generator used for evgen and the PDG code above." );
+    return nullptr;
+  }
+
+  // create new primaries and set them to the vertex
+  //  G4double mass =  particleDefinition->GetPDGMass();
+  auto &genpartMomentum = genpart.momentum();
+  G4double px = genpartMomentum.x();
+  G4double py = genpartMomentum.y();
+  G4double pz = genpartMomentum.z();
+
+  std::unique_ptr<G4PrimaryParticle> g4particle = std::make_unique<G4PrimaryParticle>(particleDefinition,px,py,pz);
+
+  if (genpart.end_vertex()) {
+    // Set the lifetime appropriately - this is slow but rigorous, and we
+    //  don't want to end up with something like vertex time that we have
+    //  to validate for every generator on earth...
+    const auto& prodVtx = genpart.production_vertex()->position();
+    const auto& endVtx = genpart.end_vertex()->position();
+    const G4LorentzVector lv0 ( prodVtx.x(), prodVtx.y(), prodVtx.z(), prodVtx.t() );
+    const G4LorentzVector lv1 ( endVtx.x(), endVtx.y(), endVtx.z(), endVtx.t() );
+    g4particle->SetProperTime( (lv1-lv0).mag()/Gaudi::Units::c_light );
+
+    if(m_quasiStableParticlesIncluded) {
+      ATH_MSG_VERBOSE( "Detected primary particle with end vertex." );
+      ATH_MSG_VERBOSE( "Will add the primary particle set on." );
+      ATH_MSG_VERBOSE( "Primary Particle: " << genpart );
+      ATH_MSG_VERBOSE( "Number of daughters of "<<genpart.barcode()<<": " << genpart.end_vertex()->particles_out_size() );
+    }
+    else {
+      ATH_MSG_WARNING( "Detected primary particle with end vertex." );
+      ATH_MSG_WARNING( "Will add the primary particle set on." );
+      ATH_MSG_WARNING( "Primary Particle: " << genpart );
+      ATH_MSG_WARNING( "Number of daughters of "<<genpart.barcode()<<": " << genpart.end_vertex()->particles_out_size() );
+    }
+    // Add all necessary daughter particles
+    for ( auto daughterIter=genpart.end_vertex()->particles_out_const_begin();
+          daughterIter!=genpart.end_vertex()->particles_out_const_end(); ++daughterIter ) {
+      if(m_quasiStableParticlesIncluded) {
+        ATH_MSG_VERBOSE ( "Attempting to add daughter particle of "<<genpart.barcode()<<": " << **daughterIter );
+      }
+      else {
+        ATH_MSG_WARNING ( "Attempting to add daughter particle of "<<genpart.barcode()<<": " << **daughterIter );
+      }
+      G4PrimaryParticle *daughterG4Particle = this->getG4PrimaryParticle( **daughterIter );
+      if(!daughterG4Particle) {
+        ATH_MSG_ERROR("Bailing out of loop over daughters of particle with barcode: "<<genpart.barcode() <<
+                      " due to errors - will not return G4Particle.");
+        return nullptr;
+      }
+      g4particle->SetDaughter( daughterG4Particle );
+    }
+  }
+
+  // Set the user information for this primary to point to the HepMcParticleLink...
+  FaserPrimaryParticleInformation* ppi = new FaserPrimaryParticleInformation(&genpart);
+  ppi->SetParticle(&genpart);
+  ppi->SetRegenerationNr(0);
+  g4particle->SetUserInformation(ppi);
+  ATH_MSG_VERBOSE("Making primary down the line with barcode " << ppi->GetParticleBarcode());
+
+  return g4particle.release();
+}
+
+
+//________________________________________________________________________
+G4PrimaryParticle* ISF::FaserInputConverter::getG4PrimaryParticle(const ISF::FaserISFParticle& isp) const
+{
+  ATH_MSG_VERBOSE("Creating G4PrimaryParticle from FaserISFParticle.");
+
+  const auto* truthBinding = isp.getTruthBinding();
+  if (!truthBinding) {
+      G4ExceptionDescription description;
+      description << G4String("getG4PrimaryParticle: ") + "No ISF::TruthBinding associated with ISParticle (" << isp <<")";
+      G4Exception("iGeant4::TransportTool", "NoISFTruthBinding", FatalException, description);
+      return nullptr; //The G4Exception call above should abort the job, but Coverity does not seem to pick this up.
+  }
+  HepMC::GenParticle*        genpart = truthBinding->getTruthParticle();
+  HepMC::GenParticle* primaryGenpart = truthBinding->getPrimaryTruthParticle();
+
+  const G4ParticleDefinition *particleDefinition = this->getG4ParticleDefinition(isp.pdgCode());
+
+  if(particleDefinition==nullptr) {
+    ATH_MSG_ERROR("ISF_to_G4Event particle conversion failed. FaserISF_Particle PDG code = " << isp.pdgCode() <<
+                  "\n This usually indicates a problem with the evgen step.\n" <<
+                  "Please report this to the Generators group, mentioning the release and generator used for evgen and the PDG code above." );
+    return nullptr;
+  }
+
+  // create new primaries and set them to the vertex
+  //  G4double mass =  particleDefinition->GetPDGMass();
+  G4double px(0.0);
+  G4double py(0.0);
+  G4double pz(0.0);
+  if(genpart) {
+    auto &genpartMomentum = genpart->momentum();
+    px = genpartMomentum.x();
+    py = genpartMomentum.y();
+    pz = genpartMomentum.z();
+  }
+  else {
+    auto &ispMomentum = isp.momentum();
+    px = ispMomentum.x();
+    py = ispMomentum.y();
+    pz = ispMomentum.z();
+  }
+
+  std::unique_ptr<G4PrimaryParticle> g4particle = std::make_unique<G4PrimaryParticle>(particleDefinition,px,py,pz);
+  // UserInformation
+  std::unique_ptr<FaserPrimaryParticleInformation> ppi = std::make_unique<FaserPrimaryParticleInformation>(primaryGenpart,&isp);
+
+  /// In the case that particles are being passed back to Geant4 then
+  /// we may have particles which have already interacted, so we
+  /// should set the regeneration number accordingly.
+  Barcode::ParticleBarcode barcode = isp.barcode();
+  const int regenerationNr = (barcode - barcode%m_barcodeGenerationIncrement)/m_barcodeGenerationIncrement;
+  ppi->SetRegenerationNr(regenerationNr);
+
+  if ( genpart ) {
+    if (genpart->end_vertex()) {
+
+      /// Set the lifetime appropriately - this is slow but rigorous,
+      /// and we don't want to end up with something like vertex time
+      /// that we have to validate for every generator on earth...
+      const auto& prodVtx = genpart->production_vertex()->position();
+      const auto& endVtx = genpart->end_vertex()->position();
+      const G4LorentzVector lv0( prodVtx.x(), prodVtx.y(), prodVtx.z(), prodVtx.t() );
+      const G4LorentzVector lv1( endVtx.x(), endVtx.y(), endVtx.z(), endVtx.t() );
+      g4particle->SetProperTime( (lv1-lv0).mag()/Gaudi::Units::c_light );
+
+      if(m_quasiStableParticlesIncluded) {
+        ATH_MSG_VERBOSE( "Detected primary particle with end vertex." );
+        ATH_MSG_VERBOSE( "Will add the primary particle set on." );
+        ATH_MSG_VERBOSE( "FaserISF Particle: " << isp );
+        ATH_MSG_VERBOSE( "Primary Particle: " << *genpart );
+        ATH_MSG_VERBOSE( "Number of daughters of "<<genpart->barcode()<<": " << genpart->end_vertex()->particles_out_size() );
+      }
+      else {
+        ATH_MSG_WARNING( "Detected primary particle with end vertex. This should only be the case if" );
+        ATH_MSG_WARNING( "you are running with quasi-stable particle simulation enabled.  This is not" );
+        ATH_MSG_WARNING( "yet validated - you'd better know what you're doing.  Will add the primary" );
+        ATH_MSG_WARNING( "particle set on." );
+        ATH_MSG_WARNING( "FaserISF Particle: " << isp );
+        ATH_MSG_WARNING( "Primary Particle: " << *genpart );
+        ATH_MSG_WARNING( "Number of daughters of "<<genpart->barcode()<<": " << genpart->end_vertex()->particles_out_size() );
+      }
+      // Add all necessary daughter particles
+      for ( auto daughterIter=genpart->end_vertex()->particles_out_const_begin();
+            daughterIter!=genpart->end_vertex()->particles_out_const_end(); ++daughterIter ) {
+        if(m_quasiStableParticlesIncluded) {
+          ATH_MSG_VERBOSE ( "Attempting to add daughter particle of "<<genpart->barcode()<<": " << **daughterIter );
+        }
+        else {
+          ATH_MSG_WARNING ( "Attempting to add daughter particle of "<<genpart->barcode()<<": " << **daughterIter );
+        }
+        G4PrimaryParticle *daughterG4Particle = this->getG4PrimaryParticle( **daughterIter );
+        if(!daughterG4Particle) {
+          ATH_MSG_ERROR("Bailing out of loop over daughters of particle with barcode: "<<genpart->barcode() <<
+                        " due to errors - will not return G4Particle.");
+          return nullptr;
+        }
+        g4particle->SetDaughter( daughterG4Particle );
+      }
+     } // particle had an end vertex
+    //Code copied from TruthHepMCEventConverter::TransformHepMCParticle
+    CLHEP::Hep3Vector gpv = g4particle->GetMomentum();
+    double pmass = g4particle->GetMass();
+    const double pe = sqrt(gpv.mag2() + pmass*pmass);  // this does only change for boosts, etc.
+    genpart->set_momentum(CLHEP::HepLorentzVector(gpv.x(),gpv.y(),gpv.z(),pe));
+    //End of code copied from TruthHepMCEventConverter::TransformHepMCParticle
+  } // Truth was detected
+
+  ATH_MSG_VERBOSE("PrimaryParticleInformation:");
+  ATH_MSG_VERBOSE("     GetParticleBarcode = " << ppi->GetParticleBarcode());
+  ATH_MSG_VERBOSE("     GetRegenerationNr = " << ppi->GetRegenerationNr());
+  ATH_MSG_VERBOSE("     GetHepMCParticle = " << ppi->GetHepMCParticle());
+  ATH_MSG_VERBOSE("     GetISFParticle = " << ppi->GetISFParticle());
+  g4particle->SetUserInformation(ppi.release());
+
+  return g4particle.release();
+}
+
+//________________________________________________________________________
+void ISF::FaserInputConverter::addG4PrimaryVertex(G4Event* g4evt, const ISF::FaserISFParticle& isp) const
+{
+  /*
+    see conversion from PrimaryParticleInformation to TrackInformation in
+    http://acode-browser.usatlas.bnl.gov/lxr/source/atlas/Simulation/G4Atlas/G4AtlasAlg/src/AthenaStackingAction.cxx#0044
+
+    need to check with
+    http://acode-browser.usatlas.bnl.gov/lxr/source/atlas/Simulation/G4Atlas/G4AtlasAlg/src/TruthHepMCEventConverter.cxx#0151
+
+    that we don't miss something
+  */
+
+  G4PrimaryParticle *g4particle = this->getG4PrimaryParticle( isp );
+  if (!g4particle) {
+    ATH_MSG_ERROR("Failed to create G4PrimaryParticle for ISParticle (" << isp <<")");
+    return;
+  }// Already printed a warning
+
+  // create a new vertex
+  G4PrimaryVertex *g4vertex = new G4PrimaryVertex(isp.position().x(),
+                                                  isp.position().y(),
+                                                  isp.position().z(),
+                                                  isp.timeStamp());
+  g4vertex->SetPrimary( g4particle );
+  ATH_MSG_VERBOSE("Print G4PrimaryVertex: ");
+  if (msgLevel(MSG::VERBOSE)) { g4vertex->Print(); }
+  g4evt->AddPrimaryVertex( g4vertex );
+  return;
+}
+
+//________________________________________________________________________
+bool ISF::FaserInputConverter::isInsideG4WorldVolume(const ISF::FaserISFParticle& isp, const G4VSolid* worldSolid) const
+{
+
+  const Amg::Vector3D &pos = isp.position();
+  const G4ThreeVector g4Pos( pos.x(), pos.y(), pos.z() );
+  EInside insideStatus = worldSolid->Inside( g4Pos );
+
+  bool insideWorld = insideStatus != kOutside;
+  return insideWorld;
+}
diff --git a/Simulation/ISF/ISF_Core/FaserISF_Services/src/FaserInputConverter.h b/Simulation/ISF/ISF_Core/FaserISF_Services/src/FaserInputConverter.h
new file mode 100644
index 00000000..87eb84eb
--- /dev/null
+++ b/Simulation/ISF/ISF_Core/FaserISF_Services/src/FaserInputConverter.h
@@ -0,0 +1,126 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// InputConverter.h, (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#ifndef FASERISF_FASERINPUTCONVERTER_H
+#define FASERISF_FASERINPUTCONVERTER_H 1
+
+// STL includes
+#include <string>
+// ISF include
+#include "FaserISF_Interfaces/IFaserInputConverter.h"
+// FrameWork includes
+#include "GaudiKernel/ToolHandle.h"
+#include "GaudiKernel/ServiceHandle.h"
+#include "AthenaBaseComps/AthService.h"
+
+#include "BarcodeEvent/Barcode.h"
+
+// forward declarations
+namespace Barcode {
+  class IBarcodeSvc;
+}
+namespace HepPDT {
+  class ParticleDataTable;
+}
+namespace HepMC {
+  class GenParticle;
+  class GenEvent;
+}
+class IPartPropSvc;
+class McEventCollection;
+namespace ISFTesting {
+  class InputConverter_test;
+}
+namespace ISF {
+  class FaserISFParticle;
+  class IGenParticleFilter;
+}
+
+class G4ParticleDefinition;
+class G4PrimaryParticle;
+class G4VSolid;
+
+namespace ISF {
+
+  /** @class InputConverter
+
+      Convert simulation input collections to ISFParticles for subsequent ISF simulation.
+
+      @author Elmar.Ritsch -at- cern.ch
+     */
+  class FaserInputConverter final: public extends<AthService, IFaserInputConverter> {
+
+    // allow test to access private data
+    friend ISFTesting::InputConverter_test;
+
+  public:
+    FaserInputConverter(const std::string& name, ISvcLocator* svc);
+    virtual ~FaserInputConverter();
+
+    /** Athena algtool Hooks */
+    virtual StatusCode  initialize() override final;
+    virtual StatusCode  finalize() override final;
+
+    /** Convert selected particles from the given McEventCollection into ISFParticles
+        and push them into the given ISFParticleContainer */
+    virtual StatusCode convert(const McEventCollection& inputGenEvents,
+                               ISF::FaserISFParticleContainer& simParticles,
+                               EBC_EVCOLL kindOfCollection=EBC_MAINEVCOLL) const override final;
+
+    /** */
+    virtual StatusCode convertHepMCToG4Event(McEventCollection& inputGenEvents,
+                                             G4Event*& outputG4Event,
+                                             EBC_EVCOLL kindOfCollection=EBC_MAINEVCOLL) const override final;
+
+    /** Converts vector of ISF::ISFParticles to G4Event */
+    G4Event* ISF_to_G4Event(const std::vector<const ISF::FaserISFParticle*>& isp, HepMC::GenEvent *genEvent) const override final;
+
+  private:
+
+    const G4ParticleDefinition* getG4ParticleDefinition(int pdgcode) const;
+
+    G4PrimaryParticle* getG4PrimaryParticle(const HepMC::GenParticle& gp) const;
+
+    G4PrimaryParticle* getG4PrimaryParticle(const ISF::FaserISFParticle& isp) const;
+
+    void addG4PrimaryVertex(G4Event* g4evt, const ISF::FaserISFParticle& isp) const;
+
+    /** Tests whether the given ISFParticle is within the Geant4 world volume */
+    bool isInsideG4WorldVolume(const ISF::FaserISFParticle& isp, const G4VSolid* worldSolid) const;
+
+    /** get right GenParticle mass */
+    double getParticleMass(const HepMC::GenParticle& p) const;
+
+    /** get all generator particles which pass filters */
+    std::vector<HepMC::GenParticle*> getSelectedParticles(const HepMC::GenEvent& evnt, bool legacyOrdering=false) const;
+
+    /** check if the given particle passes all filters */
+    bool passesFilters(const HepMC::GenParticle& p) const;
+
+    /** convert GenParticle to ISFParticle */
+    ISF::FaserISFParticle* convertParticle(HepMC::GenParticle* genPartPtr, EBC_EVCOLL kindOfCollection=EBC_MAINEVCOLL) const;
+
+    /** ParticlePropertyService and ParticleDataTable */
+    ServiceHandle<IPartPropSvc>           m_particlePropSvc;          //!< particle properties svc to retrieve PDT
+    const HepPDT::ParticleDataTable      *m_particleDataTable;        //!< PDT used to look up particle masses
+
+    bool                                  m_useGeneratedParticleMass; //!< use GenParticle::generated_mass() in simulation
+
+    ToolHandleArray<IGenParticleFilter>   m_genParticleFilters;       //!< HepMC::GenParticle filters
+
+    bool                                  m_quasiStableParticlesIncluded; //<! will quasi-stable particles be included in the simulation
+
+    ServiceHandle<Barcode::IBarcodeSvc>   m_barcodeSvc;                 //!< The ISF Barcode service
+    Barcode::ParticleBarcode              m_barcodeGenerationIncrement; //!< to be retrieved from ISF Barcode service
+
+  };
+
+}
+
+
+#endif //> !FASERISF_FASERNPUTCONVERTER_H
diff --git a/Simulation/ISF/ISF_Core/FaserISF_Services/src/FaserTruthSvc.cxx b/Simulation/ISF/ISF_Core/FaserISF_Services/src/FaserTruthSvc.cxx
new file mode 100644
index 00000000..93dd6023
--- /dev/null
+++ b/Simulation/ISF/ISF_Core/FaserISF_Services/src/FaserTruthSvc.cxx
@@ -0,0 +1,524 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// TruthSvc.cxx, (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+// class header
+#include "FaserTruthSvc.h"
+// other ISF_HepMC includes
+#include "FaserISF_HepMC_Interfaces/IFaserTruthStrategy.h"
+// ISF includes
+#include "FaserISF_Event/IFaserTruthIncident.h"
+// Framework
+#include "GaudiKernel/ISvcLocator.h"
+#include "StoreGate/StoreGateSvc.h"
+#include "GaudiKernel/SystemOfUnits.h"
+// Barcode
+#include "BarcodeInterfaces/IBarcodeSvc.h"
+//
+#include "TruthUtils/HepMCHelpers.h" // for MC::findChildren(...)
+// HepMC includes
+#include "HepMC/SimpleVector.h"
+#include "HepMC/GenParticle.h"
+#include "HepMC/GenEvent.h"
+#include "HepMC/GenVertex.h"
+// CLHEP includes
+#include "CLHEP/Geometry/Point3D.h"
+
+// DetectorDescription
+#include "FaserDetDescr/FaserRegionHelper.h"
+
+#include <sstream>
+
+#undef DEBUG_TRUTHSVC
+
+/** Constructor **/
+ISF::FaserTruthSvc::FaserTruthSvc(const std::string& name,ISvcLocator* svc) :
+  base_class(name,svc),
+  m_barcodeSvc("BarcodeSvc",name),
+  m_truthStrategies(this),
+  m_geoStrategies(),
+  m_numStrategies(),
+  m_skipIfNoChildren(true),
+  m_skipIfNoParentBarcode(true),
+  m_ignoreUndefinedBarcodes(false),
+  m_passWholeVertex(true),
+  m_forceEndVtxRegionsVec(),
+  m_forceEndVtx(),
+  m_quasiStableParticlesIncluded(false)
+{
+  // the barcode service (used to compute Vertex Barcodes)
+  declareProperty("BarcodeSvc",                        m_barcodeSvc              );
+  // MCTruth writing strategies
+  declareProperty("SkipIfNoChildren",                  m_skipIfNoChildren        );
+  declareProperty("SkipIfNoParentBarcode",             m_skipIfNoParentBarcode   );
+  declareProperty("IgnoreUndefinedBarcodes",           m_ignoreUndefinedBarcodes );
+  declareProperty("PassWholeVertices",                 m_passWholeVertex         );
+  declareProperty("TruthStrategies",                   m_truthStrategies);
+  // attach end-vertex if parent particle dies for the different AtlasDetDescr regions
+  declareProperty("ForceEndVtxInRegions",              m_forceEndVtxRegionsVec );
+
+  declareProperty("QuasiStableParticlesIncluded",      m_quasiStableParticlesIncluded);
+}
+
+ISF::FaserTruthSvc::~FaserTruthSvc()
+{}
+
+
+/** framework methods */
+StatusCode ISF::FaserTruthSvc::initialize()
+{
+  ATH_MSG_VERBOSE( "initialize()" );
+
+  // Screen output
+  ATH_MSG_DEBUG("--------------------------------------------------------");
+
+  // retrieve BarcodeSvc
+  if ( m_barcodeSvc.retrieve().isFailure() ) {
+    ATH_MSG_FATAL("Could not retrieve BarcodeService. Abort.");
+    return StatusCode::FAILURE;
+  }
+
+  // copy a pointer to the strategy instance to the local
+  // array of pointers (for faster access)
+  ATH_CHECK(m_truthStrategies.retrieve());
+  // Would be nicer to make m_geoStrategies a vector of vectors
+  for ( unsigned short geoID=FaserDetDescr::fFirstFaserRegion; geoID<FaserDetDescr::fNumFaserRegions; ++geoID) {
+    m_numStrategies[geoID] = 0;
+    for ( const auto &truthStrategy : m_truthStrategies) {
+      if(truthStrategy->appliesToRegion(geoID)) {
+        ++m_numStrategies[geoID];
+      }
+    }
+  }
+  for ( unsigned short geoID=FaserDetDescr::fFirstFaserRegion; geoID<FaserDetDescr::fNumFaserRegions; ++geoID) {
+    m_geoStrategies[geoID] = new ISF::IFaserTruthStrategy*[m_numStrategies[geoID]];
+    unsigned short curNumStrategies = m_truthStrategies.size();
+    unsigned short nStrat(0);
+    for ( unsigned short i = 0; i < curNumStrategies; ++i) {
+      if(m_truthStrategies[i]->appliesToRegion(geoID)) {
+        m_geoStrategies[geoID][nStrat++] = &(*m_truthStrategies[i]);
+      }
+    }
+
+    // setup whether we want to write end-vertices in this region whenever a truth particle dies
+    // create an end-vertex for all truth particles ending in the current AtlasRegion?
+    bool forceEndVtx = std::find( m_forceEndVtxRegionsVec.begin(),
+                                  m_forceEndVtxRegionsVec.end(),
+                                  geoID ) != m_forceEndVtxRegionsVec.end();
+    m_forceEndVtx[geoID] = forceEndVtx;
+  }
+  ATH_MSG_VERBOSE("initialize() successful");
+  return StatusCode::SUCCESS;
+}
+
+
+/** framework methods */
+StatusCode ISF::FaserTruthSvc::finalize()
+{
+  ATH_MSG_VERBOSE("Finalizing ...");
+  return StatusCode::SUCCESS;
+}
+
+
+/** Initialize the TruthSvc and the truthSvc */
+StatusCode ISF::FaserTruthSvc::initializeTruthCollection()
+{
+  ATH_CHECK( m_barcodeSvc->initializeBarcodes() );
+  return StatusCode::SUCCESS;
+}
+
+/** Delete child vertex */
+void ISF::FaserTruthSvc::deleteChildVertex(HepMC::GenVertex* vertex) const {
+  std::vector<HepMC::GenVertex*> verticesToDelete;
+  verticesToDelete.resize(0);
+  verticesToDelete.push_back(vertex);
+  for ( unsigned short i = 0; i<verticesToDelete.size(); ++i ) {
+    HepMC::GenVertex* vtx = verticesToDelete.at(i);
+    for (HepMC::GenVertex::particles_out_const_iterator iter = vtx->particles_out_const_begin();
+         iter != vtx->particles_out_const_end(); ++iter) {
+      if( (*iter) && (*iter)->end_vertex() ) {
+        verticesToDelete.push_back( (*iter)->end_vertex() );
+      }
+    }
+    vtx->parent_event()->remove_vertex(vtx);
+  }
+  return;
+}
+
+
+StatusCode ISF::FaserTruthSvc::releaseEvent() {
+  return StatusCode::SUCCESS;
+}
+
+
+/** Register a truth incident */
+void ISF::FaserTruthSvc::registerTruthIncident( ISF::IFaserTruthIncident& ti) const {
+
+  // pass whole vertex or individual child particles
+  ti.setPassWholeVertices(m_passWholeVertex);
+
+  // the GeoID
+  FaserDetDescr::FaserRegion geoID = ti.geoID();
+
+  // check geoID assigned to the TruthIncident
+  if ( !validFaserRegion(geoID) ) {
+    const auto& position = ti.position();
+    ATH_MSG_ERROR("Unable to register truth incident with unknown SimGeoID="<< geoID
+                  << " at position z=" << position.z() << " r=" << position.perp());
+    return;
+  }
+
+  ATH_MSG_VERBOSE( "Registering TruthIncident for SimGeoID="
+                   << FaserDetDescr::FaserRegionHelper::getName(geoID) );
+
+  // number of child particles
+  unsigned short numSec = ti.numberOfChildren();
+  if ( m_skipIfNoChildren && (numSec==0) ) {
+    ATH_MSG_VERBOSE( "No child particles present in the TruthIncident,"
+                     << " will not record this TruthIncident.");
+    return;
+  }
+
+  // the parent particle -> get its barcode
+  Barcode::ParticleBarcode parentBC = ti.parentBarcode();
+  if ( m_skipIfNoParentBarcode && (parentBC==Barcode::fUndefinedBarcode) ) {
+    ATH_MSG_VERBOSE( "Parent particle in TruthIncident does not have a barcode,"
+                     << " will not record this TruthIncident.");
+    return;
+  }
+
+  // loop over registered truth strategies for given geoID
+  bool pass = false;
+  for ( unsigned short stratID=0; (!pass) && (stratID<m_numStrategies[geoID]); stratID++) {
+    // (*) test if given TruthIncident passes current strategy
+    pass = m_geoStrategies[geoID][stratID]->pass(ti);
+  }
+
+  if (pass) {
+    ATH_MSG_VERBOSE("At least one TruthStrategy passed.");
+    // at least one truth strategy returned true
+    //  -> record incident
+    recordIncidentToMCTruth( ti);
+
+  } else {
+    // none of the truth strategies returned true
+    //  -> child particles will NOT be added to the TruthEvent collection
+    // attach parent particle end vertex if it gets killed by this interaction
+    if ( m_forceEndVtx[geoID] && !ti.parentSurvivesIncident() ) {
+      ATH_MSG_VERBOSE("No TruthStrategies passed and parent destroyed - create end vertex.");
+      const bool replaceVertex(true);
+      this->createGenVertexFromTruthIncident( ti, replaceVertex );
+
+#ifdef DEBUG_TRUTHSVC
+      const std::string survival = (ti.parentSurvivesIncident()) ? "parent survives" : "parent destroyed";
+      const std::string vtxType = (ti.interactionClassification()==ISF::STD_VTX) ? "Normal" : "Quasi-stable";
+      ATH_MSG_INFO("TruthSvc: " << vtxType << " vertex + " << survival
+                   << ", TI Class: " << ti.interactionClassification()
+                   << ", ProcessType: " << ti.physicsProcessCategory()
+                   << ", ProcessSubType: " << ti.physicsProcessCode());
+#endif
+
+    }
+
+    //  -> assign shared barcode to all child particles (if barcode service supports it)
+    setSharedChildParticleBarcode( ti);
+  }
+
+  return;
+}
+
+/** Record the given truth incident to the MC Truth */
+void ISF::FaserTruthSvc::recordIncidentToMCTruth( ISF::IFaserTruthIncident& ti) const {
+#ifdef  DEBUG_TRUTHSVC
+  ATH_MSG_INFO("Starting recordIncidentToMCTruth(...)");
+#endif
+  Barcode::PhysicsProcessCode processCode = ti.physicsProcessCode();
+  Barcode::ParticleBarcode       parentBC = ti.parentBarcode();
+
+  // record the GenVertex
+  const bool replaceVertex(false);
+  HepMC::GenVertex *vtx = createGenVertexFromTruthIncident(ti, replaceVertex);
+  const ISF::InteractionClass_t classification = ti.interactionClassification();
+#ifdef DEBUG_TRUTHSVC
+  const std::string survival = (ti.parentSurvivesIncident()) ? "parent survives" : "parent destroyed";
+  const std::string vtxType = (ti.interactionClassification()==ISF::STD_VTX) ? "Normal" : "Quasi-stable";
+  ATH_MSG_INFO("TruthSvc: " << vtxType << " vertex + " << survival
+               << ", TI Class: " << ti.interactionClassification()
+               << ", ProcessType: " << ti.physicsProcessCategory()
+               << ", ProcessSubType: " << ti.physicsProcessCode());
+#endif
+
+  ATH_MSG_VERBOSE ( "Outgoing particles:" );
+  // update parent barcode and add it to the vertex as outgoing particle
+  Barcode::ParticleBarcode newPrimBC = Barcode::fUndefinedBarcode;
+  if (classification == ISF::QS_SURV_VTX) {
+    // Special case when a particle with a pre-defined decay interacts
+    // and survives.
+    // Set the barcode to the next available value below the simulation
+    // barcode offset.
+    newPrimBC = this->maxGeneratedParticleBarcode(ti.parentParticle()->parent_event())+1;
+  }
+  else {
+    newPrimBC = m_barcodeSvc->incrementBarcode( parentBC, processCode);
+  }
+  if ( newPrimBC == Barcode::fUndefinedBarcode) {
+    if (m_ignoreUndefinedBarcodes) {
+      ATH_MSG_WARNING("Unable to generate new Particle Barcode. Continuing due to 'IgnoreUndefinedBarcodes'==True");
+    } else {
+      ATH_MSG_FATAL("Unable to generate new Particle Barcode. Aborting");
+      abort();
+    }
+  }
+
+  HepMC::GenParticle *parentBeforeIncident = ti.parentParticle();
+  HepMC::GenParticle *parentAfterIncident = ti.parentParticleAfterIncident( newPrimBC ); // This call changes ti.parentParticle() output
+  if(parentAfterIncident) {
+    ATH_MSG_VERBOSE ( "Parent After Incident: " << *parentAfterIncident);
+    if (classification==ISF::QS_SURV_VTX) {
+      // Special case when a particle with a pre-defined decay
+      // interacts and survives.
+      // 1) As the parentParticleAfterIncident has a pre-defined decay
+      // its status should be to 2.
+      parentAfterIncident->set_status(2);
+      // 2) A new GenVertex for the intermediate interaction should be
+      // added.
+      std::unique_ptr<HepMC::GenVertex> newVtx = std::make_unique<HepMC::GenVertex>( vtx->position(), vtx->id(), vtx->weights() );
+#ifdef DEBUG_TRUTHSVC
+      ATH_MSG_INFO("New GenVertex 1: " << *(newVtx.get()) );
+      ATH_MSG_INFO("New QS GenVertex 1: " << *(newVtx.get()) );
+#endif
+      HepMC::GenEvent *mcEvent = parentBeforeIncident->parent_event();
+      newVtx->suggest_barcode( this->maxGeneratedVertexBarcode(mcEvent)-1 );
+#ifdef DEBUG_TRUTHSVC
+      ATH_MSG_INFO("New QSGenVertex 2: " << *(newVtx.get()) );
+#endif
+      auto tmpVtx = newVtx.get();
+#ifdef DEBUG_TRUTHSVC
+      ATH_MSG_INFO("New QS GenVertex 3: " << (*tmpVtx) );
+#endif
+      if(!mcEvent->add_vertex( newVtx.release() )) {
+        ATH_MSG_FATAL("Failed to add GenVertex to GenEvent.");
+        abort();
+      }
+      tmpVtx->add_particle_in( parentBeforeIncident );
+      tmpVtx->add_particle_out( parentAfterIncident );
+      vtx->add_particle_in( parentAfterIncident );
+      vtx = tmpVtx;
+    }
+    else {
+      vtx->add_particle_out( parentAfterIncident );
+    }
+  }
+
+  const bool isQuasiStableVertex = (classification == ISF::QS_PREDEF_VTX); // QS_DEST_VTX and QS_SURV_VTX should be treated as normal from now on.
+  // add child particles to the vertex
+  unsigned short numSec = ti.numberOfChildren();
+  if (isQuasiStableVertex) {
+    // Here we are checking if the existing GenVertex has the same
+    // number of child particles as the truth incident.
+    // FIXME should probably make this part a separate function and
+    // also check if the pdgids of the child particles are the same
+    // too.
+    unsigned short nVertexChildren=vtx->particles_out_size();
+    if(parentAfterIncident) { nVertexChildren-=1; }
+    if(nVertexChildren!=numSec) {
+      ATH_MSG_WARNING("Existing vertex has " << nVertexChildren << " children. " <<
+                      "Number of secondaries in current truth incident = " << numSec);
+    }
+    ATH_MSG_VERBOSE("Existing vertex has " << nVertexChildren << " children. " <<
+                 "Number of secondaries in current truth incident = " << numSec);
+  }
+  const std::vector<HepMC::GenParticle*> childParticleVector = (isQuasiStableVertex) ? MC::findChildren(ti.parentParticle()) : std::vector<HepMC::GenParticle*>();
+  std::vector<HepMC::GenParticle*> matchedChildParticles;
+  for ( unsigned short i=0; i<numSec; ++i) {
+
+    bool writeOutChild = isQuasiStableVertex || m_passWholeVertex || ti.childPassedFilters(i);
+
+    if (writeOutChild) {
+      HepMC::GenParticle *p = nullptr;
+      if(isQuasiStableVertex) {
+        //Find matching GenParticle in GenVertex
+        const int childPDGcode= ti.childPdgCode(i);
+        bool noMatch(true);
+        for(auto childParticle : childParticleVector) {
+          if( (childParticle->pdg_id() == childPDGcode) && std::count(matchedChildParticles.begin(),matchedChildParticles.end(),childParticle)==0) {
+            noMatch=false;
+            ATH_MSG_VERBOSE("Found a matching Quasi-stable GenParticle with PDGcode " << childPDGcode << ":\n\t" << *childParticle );
+            matchedChildParticles.push_back(childParticle);
+            // FIXME There is a weakness in the code here for
+            // vertices with multiple children with the same
+            // pdgid. The code relies on the order of the children in
+            // childParticleVector being the same as in the
+            // truthIncident...
+            p = ti.updateChildParticle( i, childParticle );
+            break;
+          }
+        }
+        if (noMatch) {
+          std::ostringstream warnStream;
+          warnStream << "Failed to find a Quasi-stable GenParticle with PDGID " << childPDGcode << ". Options are: \n";
+          for(auto childParticle : childParticleVector) {
+            warnStream << childParticle->pdg_id() <<"\n";
+          }
+          ATH_MSG_WARNING(warnStream.str());
+        }
+      }
+      else {
+        // generate a new barcode for the child particle
+        Barcode::ParticleBarcode secBC = m_barcodeSvc->newSecondary( parentBC, processCode);
+        if ( secBC == Barcode::fUndefinedBarcode) {
+          if (m_ignoreUndefinedBarcodes)
+            ATH_MSG_WARNING("Unable to generate new Secondary Particle Barcode. Continuing due to 'IgnoreUndefinedBarcodes'==True");
+          else {
+            ATH_MSG_ERROR("Unable to generate new Secondary Particle Barcode. Aborting");
+            abort();
+          }
+        }
+        p = ti.childParticle( i, secBC );
+        // add particle to vertex
+        vtx->add_particle_out( p);
+      }
+      ATH_MSG_VERBOSE ( "Writing out " << i << "th child particle: " << *p);
+    } // <-- if write out child particle
+    else {
+      ATH_MSG_VERBOSE ( "Not writing out " << i << "th child particle." );
+    }
+
+  } // <-- loop over all child particles
+  ATH_MSG_VERBOSE("--------------------------------------------------------");
+}
+
+/** Record the given truth incident to the MC Truth */
+HepMC::GenVertex *ISF::FaserTruthSvc::createGenVertexFromTruthIncident( ISF::IFaserTruthIncident& ti,
+                                                                   bool replaceExistingGenVertex) const {
+
+  Barcode::PhysicsProcessCode processCode = ti.physicsProcessCode();
+  Barcode::ParticleBarcode       parentBC = ti.parentBarcode();
+
+  std::vector<double> weights(1);
+  Barcode::ParticleBarcode primaryBC = parentBC % m_barcodeSvc->particleGenerationIncrement();
+  weights[0] = static_cast<double>( primaryBC );
+
+  // Check for a previous end vertex on this particle.  If one existed, then we should put down next to this
+  //  a new copy of the particle.  This is the agreed upon version of the quasi-stable particle truth, where
+  //  the vertex at which we start Q-S simulation no longer conserves energy, but we keep both copies of the
+  //  truth particles
+  HepMC::GenParticle *parent = ti.parentParticle();
+  if (!parent) {
+    ATH_MSG_ERROR("Unable to write particle interaction to MC truth due to missing parent HepMC::GenParticle instance");
+    abort();
+  }
+  HepMC::GenEvent *mcEvent = parent->parent_event();
+  if (!mcEvent) {
+    ATH_MSG_ERROR("Unable to write particle interaction to MC truth due to missing parent HepMC::GenEvent instance");
+    abort();
+  }
+
+  // generate vertex
+  Barcode::VertexBarcode vtxbcode = m_barcodeSvc->newVertex( parentBC, processCode );
+  if ( vtxbcode == Barcode::fUndefinedBarcode) {
+    if (m_ignoreUndefinedBarcodes) {
+      ATH_MSG_WARNING("Unable to generate new Truth Vertex Barcode. Continuing due to 'IgnoreUndefinedBarcodes'==True");
+    } else {
+      ATH_MSG_ERROR("Unable to generate new Truth Vertex Barcode. Aborting");
+      abort();
+    }
+  }
+  int vtxID = 1000 + static_cast<int>(processCode);
+  std::unique_ptr<HepMC::GenVertex> vtx = std::make_unique<HepMC::GenVertex>( ti.position(), vtxID, weights );
+  vtx->suggest_barcode( vtxbcode );
+
+  if (parent->end_vertex()){
+    if(!m_quasiStableParticlesIncluded) {
+      ATH_MSG_WARNING("Parent particle found with an end vertex attached.  This should only happen");
+      ATH_MSG_WARNING("in the case of simulating quasi-stable particles.  That functionality");
+      ATH_MSG_WARNING("is not yet validated in ISF, so you'd better know what you're doing.");
+      ATH_MSG_WARNING("Will delete the old vertex and swap in the new one.");
+    }
+    auto* oldVertex = parent->end_vertex();
+#ifdef DEBUG_TRUTHSVC
+    ATH_MSG_VERBOSE("createGVfromTI Existing QS GenVertex 1: " << *oldVertex );
+    ATH_MSG_VERBOSE("createGVfromTI QS Parent 1: " << *parent);
+#endif
+    if(replaceExistingGenVertex) {
+      vtx->add_particle_in( parent );
+      ATH_MSG_VERBOSE("createGVfromTI Replacement QS GenVertex: " << *(vtx.get()) );
+      mcEvent->add_vertex( vtx.release() );
+      // Delete oldVertex and children here
+      this->deleteChildVertex(oldVertex);
+    }
+    else {
+      //oldVertex->suggest_barcode( vtxbcode );
+      oldVertex->set_position( ti.position() );
+      oldVertex->set_id( vtxID );
+      oldVertex->weights() = weights;
+#ifdef DEBUG_TRUTHSVC
+      ATH_MSG_VERBOSE("createGVfromTI Existing QS GenVertex 2: " << *oldVertex );
+#endif
+    }
+#ifdef DEBUG_TRUTHSVC
+    ATH_MSG_VERBOSE ( "createGVfromTI QS End Vertex representing process: " << processCode << ", for parent with barcode "<<parentBC<<". Creating." );
+    ATH_MSG_VERBOSE ( "createGVfromTI QS Parent 2: " << *parent);
+#endif
+  } else { // Normal simulation
+#ifdef DEBUG_TRUTHSVC
+    ATH_MSG_VERBOSE ("createGVfromTI Parent 1: " << *parent);
+#endif
+    // add parent particle to vtx
+    vtx->add_particle_in( parent );
+#ifdef DEBUG_TRUTHSVC
+    ATH_MSG_VERBOSE ( "createGVfromTI End Vertex representing process: " << processCode << ", for parent with barcode "<<parentBC<<". Creating." );
+    ATH_MSG_VERBOSE ( "createGVfromTI Parent 2: " << *parent);
+#endif
+    mcEvent->add_vertex( vtx.release() );
+  }
+
+  return parent->end_vertex();
+}
+
+/** Set shared barcode for child particles particles */
+void ISF::FaserTruthSvc::setSharedChildParticleBarcode( ISF::IFaserTruthIncident& ti) const {
+  Barcode::PhysicsProcessCode processCode = ti.physicsProcessCode();
+  Barcode::ParticleBarcode       parentBC = ti.parentBarcode();
+
+  ATH_MSG_VERBOSE ( "End Vertex representing process: " << processCode << ". TruthIncident failed cuts. Skipping.");
+
+  // generate one new barcode for all child particles
+  Barcode::ParticleBarcode childBC = m_barcodeSvc->sharedChildBarcode( parentBC, processCode);
+
+  // propagate this barcode into the TruthIncident only if
+  // it is a proper barcode, ie !=fUndefinedBarcode
+  if (childBC != Barcode::fUndefinedBarcode) {
+    ti.setAllChildrenBarcodes( childBC );
+  }
+}
+
+int ISF::FaserTruthSvc::maxGeneratedParticleBarcode(HepMC::GenEvent *genEvent) const {
+  int maxBarcode=0;
+  const int firstSecondaryParticleBarcode(m_barcodeSvc->secondaryParticleBcOffset());
+  HepMC::GenEvent::particle_const_iterator currentGenParticleIter;
+  for (currentGenParticleIter= genEvent->particles_begin();
+       currentGenParticleIter!= genEvent->particles_end();
+       ++currentGenParticleIter) {
+    const int barcode((*currentGenParticleIter)->barcode());
+    if(barcode > maxBarcode && barcode < firstSecondaryParticleBarcode) { maxBarcode=barcode; }
+  }
+  return maxBarcode;
+}
+
+int ISF::FaserTruthSvc::maxGeneratedVertexBarcode(HepMC::GenEvent *genEvent) const {
+  int maxBarcode=0;
+  const int firstSecondaryVertexBarcode(m_barcodeSvc->secondaryVertexBcOffset());
+  HepMC::GenEvent::vertex_const_iterator currentGenVertexIter;
+  for (currentGenVertexIter= genEvent->vertices_begin();
+       currentGenVertexIter!= genEvent->vertices_end();
+       ++currentGenVertexIter) {
+    const int barcode((*currentGenVertexIter)->barcode());
+    if(barcode < maxBarcode && barcode > firstSecondaryVertexBarcode) { maxBarcode=barcode; }
+  }
+  return maxBarcode;
+}
diff --git a/Simulation/ISF/ISF_Core/FaserISF_Services/src/FaserTruthSvc.h b/Simulation/ISF/ISF_Core/FaserISF_Services/src/FaserTruthSvc.h
new file mode 100644
index 00000000..d674d807
--- /dev/null
+++ b/Simulation/ISF/ISF_Core/FaserISF_Services/src/FaserTruthSvc.h
@@ -0,0 +1,133 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// FaserTruthSvc.h, (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#ifndef FASERISF_SERVICES_FASERTRUTHSVC_H
+#define FASERISF_SERVICES_FASERTRUTHSVC_H 1
+
+// STL includes
+#include <string>
+
+// FrameWork includes
+#include "GaudiKernel/ToolHandle.h"
+#include "GaudiKernel/ServiceHandle.h"
+#include "AthenaBaseComps/AthService.h"
+
+// ISF include
+#include "FaserISF_Interfaces/IFaserTruthSvc.h"
+#include "FaserISF_Event/IFaserTruthIncident.h"
+
+// DetectorDescription
+#include "FaserDetDescr/FaserRegion.h"
+
+// Barcode
+#include "BarcodeEvent/Barcode.h"
+
+// McEventCollection
+#include "GeneratorObjects/McEventCollection.h"
+
+// forward declarations
+class StoreGateSvc;
+
+namespace Barcode {
+  class IBarcodeSvc;
+}
+
+namespace HepMC {
+  class GenEvent;
+}
+
+namespace ISFTesting {
+  class TruthSvc_test;
+}
+
+namespace ISF {
+
+  class IFaserTruthStrategy;
+  typedef ToolHandleArray<IFaserTruthStrategy>     FaserTruthStrategyArray;
+
+  /** @class FaserTruthSvc
+
+      HepMC based version of the ISF::ITruthSvc,
+      currently it takes an IFaserTruthIncident base class
+
+
+      @author Andreas.Salzburger -at- cern.ch , Elmar.Ritsch -at- cern.ch
+  */
+  class FaserTruthSvc final : public extends<AthService, IFaserTruthSvc> {
+
+    // allow test to access private data
+    friend ISFTesting::TruthSvc_test;
+
+  public:
+
+    //** Constructor with parameters */
+    FaserTruthSvc( const std::string& name, ISvcLocator* pSvcLocator );
+
+    /** Destructor */
+    virtual ~FaserTruthSvc();
+
+    /** Athena algorithm's interface method initialize() */
+    StatusCode  initialize() override;
+    /** Athena algorithm's interface method finalize() */
+    StatusCode  finalize() override;
+
+    /** Register a truth incident */
+    void registerTruthIncident( IFaserTruthIncident& truthincident) const override;
+
+    /** Initialize the Truth Svc at the beginning of each event */
+    StatusCode initializeTruthCollection() override;
+
+    /** Finalize the Truth Svc at the end of each event*/
+    StatusCode releaseEvent() override;
+
+  private:
+    /** Record the given truth incident to the MC Truth */
+    void recordIncidentToMCTruth( IFaserTruthIncident& truthincident) const;
+    /** Record and end vertex to the MC Truth for the parent particle */
+    HepMC::GenVertex *createGenVertexFromTruthIncident( IFaserTruthIncident& truthincident,
+                                                        bool replaceExistingGenVertex=false) const;
+
+    /** Set shared barcode for child particles */
+    void setSharedChildParticleBarcode( IFaserTruthIncident& truthincident) const;
+
+    /** Delete child vertex */
+    void deleteChildVertex(HepMC::GenVertex* vertex) const;
+
+    /** Helper function to determine the largest particle barcode set by the generator */
+    int maxGeneratedParticleBarcode(HepMC::GenEvent *genEvent) const;
+
+    /** Helper function to determine the largest vertex barcode set by the generator */
+    int maxGeneratedVertexBarcode(HepMC::GenEvent *genEvent) const;
+
+    ServiceHandle<Barcode::IBarcodeSvc>       m_barcodeSvc;           //!< The Barcode service
+
+    /** the truth strategies applied (as AthenaToolHandle Array) */
+    FaserTruthStrategyArray                   m_truthStrategies;
+    /** for faster access: using an internal pointer to the actual ITruthStrategy instances */
+    IFaserTruthStrategy**                     m_geoStrategies[FaserDetDescr::fNumFaserRegions];
+    unsigned short                            m_numStrategies[FaserDetDescr::fNumFaserRegions];
+
+    /** MCTruth steering */
+    bool                                      m_skipIfNoChildren;       //!< do not record incident if numChildren==0
+    bool                                      m_skipIfNoParentBarcode;  //!< do not record if parentBarcode==fUndefinedBarcode
+    bool                                      m_ignoreUndefinedBarcodes;//!< do/don't abort if retrieve an undefined barcode
+
+    bool                                      m_passWholeVertex;
+
+    std::vector<int>                         m_forceEndVtxRegionsVec; //!< property containing AtlasRegions for which
+                                                                              //   to write end-vtx
+    bool                                      m_forceEndVtx[FaserDetDescr::fNumFaserRegions]; //!< attach end vertex to
+                                                                                                     //   all parent particles if they die
+
+    bool                                      m_quasiStableParticlesIncluded; //!< does this job simulate quasi-stable particles.
+
+  };
+}
+
+
+#endif //> !FASERISF_SERVICES_FASERTRUTHSVC_H
diff --git a/Simulation/ISF/ISF_Core/FaserISF_Services/src/components/FaserISF_Services_entries.cxx b/Simulation/ISF/ISF_Core/FaserISF_Services/src/components/FaserISF_Services_entries.cxx
new file mode 100644
index 00000000..ebce64ca
--- /dev/null
+++ b/Simulation/ISF/ISF_Core/FaserISF_Services/src/components/FaserISF_Services_entries.cxx
@@ -0,0 +1,7 @@
+#include "../FaserGeoIDSvc.h"
+#include "../FaserTruthSvc.h"
+#include "../FaserInputConverter.h"
+
+DECLARE_COMPONENT( ISF::FaserGeoIDSvc )
+DECLARE_COMPONENT( ISF::FaserTruthSvc )
+DECLARE_COMPONENT( ISF::FaserInputConverter )
diff --git a/Simulation/ISF/ISF_Core/FaserISF_Services/test/FaserISF_ServicesConfigNew_test.py b/Simulation/ISF/ISF_Core/FaserISF_Services/test/FaserISF_ServicesConfigNew_test.py
new file mode 100644
index 00000000..60000958
--- /dev/null
+++ b/Simulation/ISF/ISF_Core/FaserISF_Services/test/FaserISF_ServicesConfigNew_test.py
@@ -0,0 +1,48 @@
+#!/usr/bin/env python
+"""Run tests on FaserISF_ServicesConfigNew.py
+
+Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+"""
+if __name__ == '__main__':
+  from AthenaConfiguration.MainServicesConfig import MainServicesSerialCfg
+  import os
+
+  # Set up logging and config behaviour
+  from AthenaCommon.Logging import log
+  from AthenaCommon.Constants import DEBUG
+  from AthenaCommon.Configurable import Configurable
+  log.setLevel(DEBUG)
+  Configurable.configurableRun3Behavior = 1
+
+
+  #import config flags
+  from AthenaConfiguration.AllConfigFlags import ConfigFlags
+  
+  from AthenaConfiguration.TestDefaults import defaultTestFiles
+  inputDir = defaultTestFiles.d
+  ConfigFlags.Input.Files = defaultTestFiles.EVNT
+
+  ConfigFlags.Sim.WorldRRange = 15000
+  ConfigFlags.Sim.WorldZRange = 27000 #change defaults?
+  ConfigFlags.Detector.SimulateForward = False
+  # Finalize 
+  ConfigFlags.lock()
+
+  from FaserISF_Services.FaserISF_ServicesConfigNew import FaserTruthServiceCfg, FaserGeoIDSvcCfg
+
+  ## Initialize a new component accumulator
+  cfg = MainServicesSerialCfg()
+
+  #add the algorithm
+  cfg.merge(FaserTruthServiceCfg(ConfigFlags))
+  cfg.merge(InputConverterCfg(ConfigFlags))
+  cfg.merge(FaserGeoIDSvcCfg(ConfigFlags))
+
+  # Dump config
+  cfg.printConfig(withDetails=True, summariseProps = True)
+  ConfigFlags.dump()
+
+
+  f=open("test.pkl","wb")
+  cfg.store(f)
+  f.close()
diff --git a/Simulation/ISF/ISF_Core/FaserISF_Services/test/FaserTruthSvc_test.cxx b/Simulation/ISF/ISF_Core/FaserISF_Services/test/FaserTruthSvc_test.cxx
new file mode 100644
index 00000000..4b0d2d28
--- /dev/null
+++ b/Simulation/ISF/ISF_Core/FaserISF_Services/test/FaserTruthSvc_test.cxx
@@ -0,0 +1,631 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+/**
+ * @author Elmar Ritsch <Elmar.Ritsch@cern.ch>
+ * @date June, 2016
+ * @brief Tests for ISF::FaserTruthSvc.
+ */
+
+#undef NDEBUG
+
+// Tested service
+#include "../src/FaserTruthSvc.h"
+
+// Framework
+#include "GaudiKernel/PhysicalConstants.h"
+#include "GaudiKernel/Bootstrap.h"
+#include "GaudiKernel/IProperty.h"
+#include "GaudiKernel/ISvcManager.h"
+#include "GaudiKernel/ISvcLocator.h"
+#include "GaudiKernel/IAppMgrUI.h"
+#include "GaudiKernel/SmartIF.h"
+#include "AthenaBaseComps/AthAlgTool.h"
+
+// Framework testing
+#include "TestTools/initGaudi.h"
+
+// Google Test
+#include "gtest/gtest.h"
+// Google Mock
+#include "gmock/gmock.h"
+
+// ISF
+#include "FaserISF_Event/FaserISFParticle.h"
+#include "FaserISF_Event/IFaserTruthIncident.h"
+#include "FaserISF_HepMC_Interfaces/IFaserTruthStrategy.h"
+
+// CLHEP includes
+#include "CLHEP/Vector/LorentzVector.h"
+#include "CLHEP/Units/SystemOfUnits.h"
+
+// HepMC
+#include "HepMC/GenParticle.h"
+#include "HepMC/GenVertex.h"
+#include "HepMC/GenEvent.h"
+
+// STL includes
+#include <cstdlib> // quick_exit
+
+
+namespace ISFTesting {
+
+  // Athena Tool to emulate a TruthStrategy
+  class MockTruthStrategy : public extends<AthAlgTool, ISF::IFaserTruthStrategy> {
+  public:
+    MockTruthStrategy(const std::string& type, const std::string& name, const IInterface* parent)
+      : base_class(type,name,parent)
+    { };
+
+    virtual ~MockTruthStrategy() {};
+
+    // This TruthStrategy only applies to the Inner Detector region
+    bool appliesToRegion(unsigned short geoID) const { return (FaserDetDescr::fFaserTracker==geoID); }
+    // mock methods which will be called by tested code
+    MOCK_CONST_METHOD1(pass, bool(ISF::IFaserTruthIncident&));
+  };
+
+  DECLARE_COMPONENT( MockTruthStrategy )
+
+  class DummyTruthIncident : public ISF::IFaserTruthIncident {
+  public:
+    DummyTruthIncident(FaserDetDescr::FaserRegion geoID, unsigned short numChildren)
+      : ISF::IFaserTruthIncident(geoID, numChildren)
+    { };
+
+    virtual ~DummyTruthIncident() {};
+    virtual const HepMC::FourVector&  position() const {return m_myPosition;};
+    virtual int                       physicsProcessCategory() const { return 1;};
+    virtual Barcode::PhysicsProcessCode physicsProcessCode() const {return 1;};
+    virtual double                    parentP2() const {return 1.0;};
+    virtual double                    parentPt2() const {return 1.0;};
+    /** Return Ekin of the parent particle */
+    virtual double                    parentEkin() const {return 1.0;};
+    /** Return the PDG Code of the parent particle */
+    virtual int                       parentPdgCode() const {return 1;};
+    /** Return the parent particle as a HepMC particle type
+        (only called for particles that will enter the HepMC truth event) */
+    virtual HepMC::GenParticle*       parentParticle() const {return nullptr;};
+    /** Return the barcode of the parent particle */
+    virtual Barcode::ParticleBarcode  parentBarcode() const {return 1;};
+    /** Return the extra barcode of the parent particle */
+    virtual Barcode::ParticleBarcode  parentBCID() const {return 1;};
+    /** Return a boolean whether or not the parent particle survives the incident */
+    virtual bool                      parentSurvivesIncident() const {return false;};
+    /** Return the parent particle after the TruthIncident vertex (and assign
+        a new barcode to it) */
+    virtual HepMC::GenParticle*       parentParticleAfterIncident(Barcode::ParticleBarcode) {return nullptr;};
+
+    /** Return p^2 of the i-th child particle */
+    virtual double                    childP2(unsigned short) const {return 1.0;};
+    /** Return pT^2 of the i-th child particle */
+    virtual double                    childPt2(unsigned short) const {return 1.0;};
+    /** Return Ekin of the i-th child particle */
+    virtual double                    childEkin(unsigned short) const {return 1.0;};
+    /** Return the PDG Code of the i-th child particle */
+    virtual int                       childPdgCode(unsigned short) const {return 1;};
+    /** Return the i-th child as a HepMC particle type and assign the given
+        Barcode to the simulator particle (only called for particles that will
+        enter the HepMC truth event) */
+    virtual HepMC::GenParticle*       childParticle(unsigned short,
+                                                    Barcode::ParticleBarcode) const {return nullptr;};
+    /** 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). */
+    virtual HepMC::GenParticle*       updateChildParticle(unsigned short,
+                                                          HepMC::GenParticle*) const {return nullptr;};
+    /** Set the the barcode of all child particles to the given bc */
+    virtual void                      setAllChildrenBarcodes(Barcode::ParticleBarcode) {};
+  private:
+    const HepMC::FourVector m_myPosition{0.0, 40.0, 0.0, 40.0};
+  };
+
+  class MockTruthIncident : public DummyTruthIncident {
+  public:
+    MockTruthIncident(FaserDetDescr::FaserRegion geoID, unsigned short numChildren)
+      : DummyTruthIncident(geoID, numChildren)
+    { };
+
+    virtual ~MockTruthIncident() {};
+    MOCK_METHOD0(geoID, FaserDetDescr::FaserRegion());
+    //MOCK_CONST_METHOD0(position, HepMC::FourVector&());
+    MOCK_CONST_METHOD0(physicsProcessCode, Barcode::PhysicsProcessCode());
+    MOCK_CONST_METHOD0(parentParticle, HepMC::GenParticle*());
+    MOCK_CONST_METHOD0(parentBarcode, Barcode::ParticleBarcode());
+    MOCK_METHOD1(parentParticleAfterIncident, HepMC::GenParticle*(Barcode::ParticleBarcode));
+    MOCK_METHOD1(setPassWholeVertices, void(bool));
+    MOCK_CONST_METHOD0(numberOfChildren, unsigned short());
+  };
+
+  // class AllGoodMatcher : public ::testing::MatcherInterface<ISF::ITruthIncident> {
+  // public:
+  //   virtual bool MatchAndExplain(ISF::ITruthIncident n, ::testing::MatchResultListener* listener) const {
+  //     return true;
+  //   }
+
+  //   virtual void DescribeTo(::std::ostream* os) const {
+  //     *os << "is divisible by 7";
+  //   }
+
+  //   virtual void DescribeNegationTo(::std::ostream* os) const {
+  //     *os << "is not divisible by 7";
+  //   }
+  // };
+
+  // inline ::testing::Matcher<ISF::ITruthIncident> AllGood() {
+  //   return ::testing::MakeMatcher(new AllGoodMatcher);
+  // }
+
+  class TruthSvc_test: public ::testing::Test {
+
+  protected:
+    virtual void SetUp() override {
+      m_appMgr = Gaudi::createApplicationMgr();
+      ASSERT_TRUE( m_appMgr!=nullptr );
+
+      m_svcLoc = m_appMgr;
+      ASSERT_TRUE( m_svcLoc.isValid() );
+
+      m_svcMgr = m_appMgr;
+      ASSERT_TRUE( m_svcMgr.isValid() );
+
+      m_propMgr = m_appMgr;
+      ASSERT_TRUE( m_propMgr.isValid() );
+      ASSERT_TRUE( m_propMgr->setProperty( "EvtSel", "NONE" ).isSuccess() );
+      ASSERT_TRUE( m_propMgr->setProperty( "JobOptionsType", "FILE" ).isSuccess() );
+      ASSERT_TRUE( m_propMgr->setProperty( "JobOptionsPath", "TruthSvc_test.txt" ).isSuccess() );
+
+      m_toolSvc = m_svcLoc->service("ToolSvc");
+      ASSERT_TRUE( m_toolSvc.isValid() );
+
+      ASSERT_TRUE( m_appMgr->configure().isSuccess() );
+      ASSERT_TRUE( m_appMgr->initialize().isSuccess() );
+
+      // the tested AthenaService
+      const auto& truthSvcTypeAndName = "ISF::FaserTruthSvc/FaserTruthSvc";
+      SmartIF<IService> svc = m_svcLoc->service(truthSvcTypeAndName);
+      m_svc = dynamic_cast<ISF::FaserTruthSvc*>(svc.get());
+      ASSERT_NE(nullptr, m_svc);
+
+      ASSERT_TRUE( m_svc->setProperties().isSuccess() );
+      ASSERT_TRUE( m_svc->configure().isSuccess() );
+    }
+
+    virtual void TearDown() override {
+      m_svcMgr->removeService(m_svc);
+      ASSERT_TRUE( m_svc->finalize().isSuccess() );
+      ASSERT_TRUE( m_svc->terminate().isSuccess() );
+      ReleaseSmartIFComponent(m_svc);
+
+      ASSERT_TRUE( m_appMgr->finalize().isSuccess() );
+      ASSERT_TRUE( m_appMgr->terminate().isSuccess() );
+      Gaudi::setInstance( static_cast<IAppMgrUI*>(nullptr)) ;
+    }
+
+    void ReleaseSmartIFComponent(IInterface* comp) {
+      size_t finalRefCount = 1; // keep one reference for the SmartIF destructor
+      for (size_t refCount = comp->refCount(); refCount>finalRefCount; refCount--) {
+        comp->release();
+      }
+    }
+
+    //
+    // accessors for private methods
+    // NB: This works because TruthSvc_test is a friend
+    //     of the tested TruthSvc service
+    //
+    template<typename... Args>
+    HepMC::GenVertex* createGenVertexFromTruthIncident(Args&&... args) const {
+      return m_svc->createGenVertexFromTruthIncident(std::forward<Args>(args)...);
+    }
+
+    template<typename... Args>
+    void recordIncidentToMCTruth(Args&&... args) const {
+      return m_svc->recordIncidentToMCTruth(std::forward<Args>(args)...);
+    }
+
+    template<typename... Args>
+    void registerTruthIncident(Args&&... args) const {
+      return m_svc->registerTruthIncident(std::forward<Args>(args)...);
+    }
+
+    template<typename... Args>
+    void deleteChildVertex(Args&&... args) const {
+      return m_svc->deleteChildVertex(std::forward<Args>(args)...);
+    }
+
+    ISF::IFaserTruthStrategy** getIDTruthStrategies(unsigned int& nStrategies) const {
+      nStrategies = static_cast<unsigned int>(m_svc->m_numStrategies[FaserDetDescr::fFaserTracker]);
+      return m_svc->m_geoStrategies[FaserDetDescr::fFaserTracker];
+    }
+
+    // void forceEndVertexInID() const {
+    //   m_svc->m_forceEndVtx[1] = true;
+    // }
+
+    // protected member variables
+    //
+
+    // Core Gaudi components
+    IAppMgrUI*             m_appMgr = nullptr;
+    SmartIF<ISvcLocator>   m_svcLoc;
+    SmartIF<ISvcManager>   m_svcMgr;
+    SmartIF<IToolSvc>      m_toolSvc;
+    SmartIF<IProperty>     m_propMgr;
+
+    ISF::FaserTruthSvc*   m_svc; // the tested AthenaService
+
+  };  // TruthSvc_test fixture
+
+
+  TEST_F(TruthSvc_test, initialize_empty) {
+    ASSERT_TRUE( m_svc->initialize().isSuccess() );
+  }
+
+
+  TEST_F(TruthSvc_test, createGenVertexFromTruthIncident) {
+    ASSERT_TRUE( m_svc->initialize().isSuccess() );
+    /// Create dummy GenEvent
+    const int process_id1(20);
+    const int event_number1(17);
+    const int pdgid1(-13);
+    const int pdgid2(13);
+    std::unique_ptr<HepMC::GenEvent> anEvent = std::make_unique<HepMC::GenEvent>(process_id1, event_number1);
+    const CLHEP::HepLorentzVector myPos( 0.0, 0.0, 0.0, 0.0);
+    HepMC::GenVertex *myVertex = new HepMC::GenVertex( myPos, -1 );
+    const HepMC::FourVector fourMomentum1( 0.0, 0.0, 1.0, 1.0*CLHEP::TeV);
+    HepMC::GenParticle* inParticle1 = new HepMC::GenParticle(fourMomentum1, pdgid1, 2);
+    myVertex->add_particle_in(inParticle1);
+    const HepMC::FourVector fourMomentum2( 0.0, 0.0, -1.0, 1.0*CLHEP::TeV);
+    HepMC::GenParticle* inParticle2 = new HepMC::GenParticle(fourMomentum2, pdgid2, 2);
+    myVertex->add_particle_in(inParticle2);
+    const HepMC::FourVector fourMomentum3( 0.0, 1.0, 0.0, 1.0*CLHEP::TeV);
+    HepMC::GenParticle* inParticle3 = new HepMC::GenParticle(fourMomentum3, pdgid1, 1);
+    myVertex->add_particle_out(inParticle3);
+    const HepMC::FourVector fourMomentum4( 0.0, -1.0, 0.0, 1.0*CLHEP::TeV);
+    HepMC::GenParticle* inParticle4 = new HepMC::GenParticle(fourMomentum4, pdgid2, 1);
+    myVertex->add_particle_out(inParticle4);
+    anEvent->add_vertex( myVertex );
+    anEvent->set_signal_process_vertex( myVertex );
+    anEvent->set_beam_particles(inParticle1,inParticle2);
+
+    MockTruthIncident ti(FaserDetDescr::fFaserTracker, 2);
+    HepMC::FourVector vtxPosition(0.0, 40.0, 0.0, 40.0);
+    EXPECT_CALL(ti, physicsProcessCode())
+      .Times(1)
+      .WillOnce(::testing::Return(21));
+    EXPECT_CALL(ti, parentBarcode())
+      .Times(1)
+      .WillOnce(::testing::Return(inParticle3->barcode()));
+    EXPECT_CALL(ti, parentParticle())
+      .Times(1)
+      .WillOnce(::testing::Return(inParticle3));
+    HepMC::GenVertex *generated = createGenVertexFromTruthIncident(ti);
+
+    ASSERT_EQ( vtxPosition, generated->position() );
+    ASSERT_EQ( 1021, generated->id() );
+    ASSERT_EQ( -200001, generated->barcode() );
+    ASSERT_EQ( 1, generated->particles_in_size());
+    ASSERT_EQ( 0, generated->particles_out_size());
+    ASSERT_EQ( inParticle3, *(generated->particles_in_const_begin()));
+  }
+
+
+  TEST_F(TruthSvc_test, recordIncidentToMCTruth_noChildParticles) {
+    ASSERT_TRUE( m_svc->initialize().isSuccess() );
+    /// Create dummy GenEvent
+    const int process_id1(20);
+    const int event_number1(17);
+    const int pdgid1(-13);
+    const int pdgid2(13);
+    std::unique_ptr<HepMC::GenEvent> anEvent = std::make_unique<HepMC::GenEvent>(process_id1, event_number1);
+    const CLHEP::HepLorentzVector myPos( 0.0, 0.0, 0.0, 0.0);
+    HepMC::GenVertex *myVertex = new HepMC::GenVertex( myPos, -1 );
+    const HepMC::FourVector fourMomentum1( 0.0, 0.0, 1.0, 1.0*CLHEP::TeV);
+    HepMC::GenParticle* inParticle1 = new HepMC::GenParticle(fourMomentum1, pdgid1, 2);
+    myVertex->add_particle_in(inParticle1);
+    const HepMC::FourVector fourMomentum2( 0.0, 0.0, -1.0, 1.0*CLHEP::TeV);
+    HepMC::GenParticle* inParticle2 = new HepMC::GenParticle(fourMomentum2, pdgid2, 2);
+    myVertex->add_particle_in(inParticle2);
+    const HepMC::FourVector fourMomentum3( 0.0, 1.0, 0.0, 1.0*CLHEP::TeV);
+    HepMC::GenParticle* inParticle3 = new HepMC::GenParticle(fourMomentum3, pdgid1, 1);
+    myVertex->add_particle_out(inParticle3);
+    const HepMC::FourVector fourMomentum4( 0.0, -1.0, 0.0, 1.0*CLHEP::TeV);
+    HepMC::GenParticle* inParticle4 = new HepMC::GenParticle(fourMomentum4, pdgid2, 1);
+    myVertex->add_particle_out(inParticle4);
+    anEvent->add_vertex( myVertex );
+    anEvent->set_signal_process_vertex( myVertex );
+    anEvent->set_beam_particles(inParticle1,inParticle2);
+
+    MockTruthIncident ti(FaserDetDescr::fFaserTracker, 2);
+    HepMC::FourVector vtxPosition(0.0, 40.0, 0.0, 40.0);
+    EXPECT_CALL(ti, physicsProcessCode())
+      .Times(2)
+      .WillOnce(::testing::Return(21))
+      .WillOnce(::testing::Return(21));
+    EXPECT_CALL(ti, parentBarcode())
+      .Times(2)
+      .WillOnce(::testing::Return(inParticle3->barcode()))
+      .WillOnce(::testing::Return(inParticle3->barcode()));
+    EXPECT_CALL(ti, parentParticle())
+      .Times(2)
+      .WillOnce(::testing::Return(inParticle3))
+      .WillOnce(::testing::Return(inParticle3));
+    EXPECT_CALL(ti, parentParticleAfterIncident(1010003))
+      .Times(1)
+      .WillOnce(::testing::Return(nullptr));
+
+    recordIncidentToMCTruth(ti);
+    HepMC::GenVertex* generated = anEvent->barcode_to_vertex(-200001); //Find a nicer way to get this.
+    ASSERT_EQ( vtxPosition, generated->position() );
+    ASSERT_EQ( 1021, generated->id() );
+    ASSERT_EQ( -200001, generated->barcode() ); // by construction at the moment
+    ASSERT_EQ( 1, generated->particles_in_size());
+    ASSERT_EQ( 0, generated->particles_out_size());
+    ASSERT_EQ( inParticle3, *(generated->particles_in_const_begin()));
+  }
+
+
+  TEST_F(TruthSvc_test, registerTruthIncident_noStrat_noForceEndVtx) {
+    ASSERT_TRUE( m_svc->initialize().isSuccess() );
+    /// Create dummy GenEvent
+    const int process_id1(20);
+    const int event_number1(17);
+    const int pdgid1(-13);
+    const int pdgid2(13);
+    std::unique_ptr<HepMC::GenEvent> anEvent = std::make_unique<HepMC::GenEvent>(process_id1, event_number1);
+    const CLHEP::HepLorentzVector myPos( 0.0, 0.0, 0.0, 0.0);
+    HepMC::GenVertex *myVertex = new HepMC::GenVertex( myPos, -1 );
+    const HepMC::FourVector fourMomentum1( 0.0, 0.0, 1.0, 1.0*CLHEP::TeV);
+    HepMC::GenParticle* inParticle1 = new HepMC::GenParticle(fourMomentum1, pdgid1, 2);
+    myVertex->add_particle_in(inParticle1);
+    const HepMC::FourVector fourMomentum2( 0.0, 0.0, -1.0, 1.0*CLHEP::TeV);
+    HepMC::GenParticle* inParticle2 = new HepMC::GenParticle(fourMomentum2, pdgid2, 2);
+    myVertex->add_particle_in(inParticle2);
+    const HepMC::FourVector fourMomentum3( 0.0, 1.0, 0.0, 1.0*CLHEP::TeV);
+    HepMC::GenParticle* inParticle3 = new HepMC::GenParticle(fourMomentum3, pdgid1, 1);
+    myVertex->add_particle_out(inParticle3);
+    const HepMC::FourVector fourMomentum4( 0.0, -1.0, 0.0, 1.0*CLHEP::TeV);
+    HepMC::GenParticle* inParticle4 = new HepMC::GenParticle(fourMomentum4, pdgid2, 1);
+    myVertex->add_particle_out(inParticle4);
+    anEvent->add_vertex( myVertex );
+    anEvent->set_signal_process_vertex( myVertex );
+    anEvent->set_beam_particles(inParticle1,inParticle2);
+
+    MockTruthIncident ti(FaserDetDescr::fFaserTracker, 2);
+    EXPECT_CALL(ti, physicsProcessCode())
+      .Times(1)
+      .WillOnce(::testing::Return(21));
+    EXPECT_CALL(ti, parentBarcode())
+      .Times(2)
+      .WillOnce(::testing::Return(inParticle3->barcode()))
+      .WillOnce(::testing::Return(inParticle3->barcode()));
+
+    registerTruthIncident(ti);
+    HepMC::GenVertex* generated = anEvent->barcode_to_vertex(-200001); //Find a nicer way to get this.
+    HepMC::GenVertex* expectedVtx(nullptr);
+    ASSERT_EQ( expectedVtx, generated);
+  }
+
+
+  TEST_F(TruthSvc_test, registerTruthIncident_noStrat_ForceEndVtx) {
+    bool forceEndVtx[FaserDetDescr::fNumFaserRegions] = {true, true, true, true, true, true};
+    ASSERT_TRUE( m_svc->setProperty( "ForceEndVtxInRegions", forceEndVtx ).isSuccess() );
+    ASSERT_TRUE( m_svc->initialize().isSuccess() );
+    /// Create dummy GenEvent
+    const int process_id1(20);
+    const int event_number1(17);
+    const int pdgid1(-13);
+    const int pdgid2(13);
+    std::unique_ptr<HepMC::GenEvent> anEvent = std::make_unique<HepMC::GenEvent>(process_id1, event_number1);
+    const CLHEP::HepLorentzVector myPos( 0.0, 0.0, 0.0, 0.0);
+    HepMC::GenVertex *myVertex = new HepMC::GenVertex( myPos, -1 );
+    const HepMC::FourVector fourMomentum1( 0.0, 0.0, 1.0, 1.0*CLHEP::TeV);
+    HepMC::GenParticle* inParticle1 = new HepMC::GenParticle(fourMomentum1, pdgid1, 2);
+    myVertex->add_particle_in(inParticle1);
+    const HepMC::FourVector fourMomentum2( 0.0, 0.0, -1.0, 1.0*CLHEP::TeV);
+    HepMC::GenParticle* inParticle2 = new HepMC::GenParticle(fourMomentum2, pdgid2, 2);
+    myVertex->add_particle_in(inParticle2);
+    const HepMC::FourVector fourMomentum3( 0.0, 1.0, 0.0, 1.0*CLHEP::TeV);
+    HepMC::GenParticle* inParticle3 = new HepMC::GenParticle(fourMomentum3, pdgid1, 1);
+    myVertex->add_particle_out(inParticle3);
+    const HepMC::FourVector fourMomentum4( 0.0, -1.0, 0.0, 1.0*CLHEP::TeV);
+    HepMC::GenParticle* inParticle4 = new HepMC::GenParticle(fourMomentum4, pdgid2, 1);
+    myVertex->add_particle_out(inParticle4);
+    anEvent->add_vertex( myVertex );
+    anEvent->set_signal_process_vertex( myVertex );
+    anEvent->set_beam_particles(inParticle1,inParticle2);
+
+    MockTruthIncident ti(FaserDetDescr::fFaserTracker, 2);
+    HepMC::FourVector vtxPosition(0.0, 40.0, 0.0, 40.0);
+    EXPECT_CALL(ti, physicsProcessCode())
+      .Times(2)
+      .WillOnce(::testing::Return(21))
+      .WillOnce(::testing::Return(21));
+    EXPECT_CALL(ti, parentBarcode())
+      .Times(3)
+      .WillOnce(::testing::Return(inParticle3->barcode()))
+      .WillOnce(::testing::Return(inParticle3->barcode()))
+      .WillOnce(::testing::Return(inParticle3->barcode()));
+    EXPECT_CALL(ti, parentParticle())
+      .Times(1)
+      .WillOnce(::testing::Return(inParticle3));
+
+    registerTruthIncident(ti);
+    HepMC::GenVertex* generated = anEvent->barcode_to_vertex(-200001); //Find a nicer way to get this.
+    ASSERT_EQ( vtxPosition, generated->position() );
+    ASSERT_EQ( 1021, generated->id() );
+    ASSERT_EQ( -200001, generated->barcode() ); // by construction at the moment
+    ASSERT_EQ( 1, generated->particles_in_size());
+    ASSERT_EQ( 0, generated->particles_out_size());
+    ASSERT_EQ( inParticle3, *(generated->particles_in_const_begin()));
+  }
+
+
+  TEST_F(TruthSvc_test, registerTruthIncident_failMockStrat_ForceEndVtx) {
+    bool forceEndVtx[FaserDetDescr::fNumFaserRegions] = {true, true, true, true, true, true};
+    ASSERT_TRUE( m_svc->setProperty( "ForceEndVtxInRegions", forceEndVtx ).isSuccess() );
+    m_svc->setProperty("TruthStrategies", "['ISFTesting::MockTruthStrategy/DummyTruthStrategy']");
+
+    ASSERT_TRUE( m_svc->initialize().isSuccess() );
+    unsigned int nIDTruthStrategies(0);
+    ISF::IFaserTruthStrategy** truthStrategies = getIDTruthStrategies(nIDTruthStrategies);
+    const unsigned int expectedSize(1);
+    ASSERT_EQ (nIDTruthStrategies, expectedSize);
+    MockTruthStrategy* truthStrategy = dynamic_cast<MockTruthStrategy*>(truthStrategies[0]);
+    ASSERT_TRUE( truthStrategy );
+
+    /// Create dummy GenEvent
+    const int process_id1(20);
+    const int event_number1(17);
+    const int pdgid1(-13);
+    const int pdgid2(13);
+    std::unique_ptr<HepMC::GenEvent> anEvent = std::make_unique<HepMC::GenEvent>(process_id1, event_number1);
+    const CLHEP::HepLorentzVector myPos( 0.0, 0.0, 0.0, 0.0);
+    HepMC::GenVertex *myVertex = new HepMC::GenVertex( myPos, -1 );
+    const HepMC::FourVector fourMomentum1( 0.0, 0.0, 1.0, 1.0*CLHEP::TeV);
+    HepMC::GenParticle* inParticle1 = new HepMC::GenParticle(fourMomentum1, pdgid1, 2);
+    myVertex->add_particle_in(inParticle1);
+    const HepMC::FourVector fourMomentum2( 0.0, 0.0, -1.0, 1.0*CLHEP::TeV);
+    HepMC::GenParticle* inParticle2 = new HepMC::GenParticle(fourMomentum2, pdgid2, 2);
+    myVertex->add_particle_in(inParticle2);
+    const HepMC::FourVector fourMomentum3( 0.0, 1.0, 0.0, 1.0*CLHEP::TeV);
+    HepMC::GenParticle* inParticle3 = new HepMC::GenParticle(fourMomentum3, pdgid1, 1);
+    myVertex->add_particle_out(inParticle3);
+    const HepMC::FourVector fourMomentum4( 0.0, -1.0, 0.0, 1.0*CLHEP::TeV);
+    HepMC::GenParticle* inParticle4 = new HepMC::GenParticle(fourMomentum4, pdgid2, 1);
+    myVertex->add_particle_out(inParticle4);
+    anEvent->add_vertex( myVertex );
+    anEvent->set_signal_process_vertex( myVertex );
+    anEvent->set_beam_particles(inParticle1,inParticle2);
+
+
+    MockTruthIncident ti(FaserDetDescr::fFaserTracker, 2);
+    HepMC::FourVector vtxPosition(0.0, 40.0, 0.0, 40.0);
+    EXPECT_CALL(ti, physicsProcessCode())
+      .Times(2)
+      .WillOnce(::testing::Return(21))
+      .WillOnce(::testing::Return(21));
+    EXPECT_CALL(ti, parentBarcode())
+      .Times(3)
+      .WillOnce(::testing::Return(inParticle3->barcode()))
+      .WillOnce(::testing::Return(inParticle3->barcode()))
+      .WillOnce(::testing::Return(inParticle3->barcode()));
+    EXPECT_CALL(ti, parentParticle())
+      .Times(1)
+      .WillOnce(::testing::Return(inParticle3));
+    // _ is a matcher where the argument can be any value of the
+    // correct type. Needed because the argument to the pass method is
+    // a reference to an abstract interface class (IFaserTruthIncident).
+    EXPECT_CALL(*truthStrategy, pass(::testing::_))
+      .Times(1)
+      .WillOnce(::testing::Return(false));
+
+    registerTruthIncident(ti);
+    HepMC::GenVertex* generated = anEvent->barcode_to_vertex(-200001); //Find a nicer way to get this.
+    ASSERT_EQ( vtxPosition, generated->position() );
+    ASSERT_EQ( 1021, generated->id() );
+    ASSERT_EQ( -200001, generated->barcode() ); // by construction at the moment
+    ASSERT_EQ( 1, generated->particles_in_size());
+    ASSERT_EQ( 0, generated->particles_out_size());
+    ASSERT_EQ( inParticle3, *(generated->particles_in_const_begin()));
+  }
+
+
+  TEST_F(TruthSvc_test, registerTruthIncident_passMockStrat_parentSurvives) {
+    m_svc->setProperty("TruthStrategies", "['ISFTesting::MockTruthStrategy/DummyTruthStrategy']");
+    ASSERT_TRUE( m_svc->initialize().isSuccess() );
+    unsigned int nIDTruthStrategies(0);
+    ISF::IFaserTruthStrategy** truthStrategies = getIDTruthStrategies(nIDTruthStrategies);
+    const unsigned int expectedSize(1);
+    ASSERT_EQ (nIDTruthStrategies, expectedSize);
+    MockTruthStrategy* truthStrategy = dynamic_cast<MockTruthStrategy*>(truthStrategies[0]);
+    ASSERT_TRUE( truthStrategy );
+
+    /// Create dummy GenEvent
+    const int process_id1(20);
+    const int event_number1(17);
+    const int pdgid1(-13);
+    const int pdgid2(13);
+    std::unique_ptr<HepMC::GenEvent> anEvent = std::make_unique<HepMC::GenEvent>(process_id1, event_number1);
+    const CLHEP::HepLorentzVector myPos( 0.0, 0.0, 0.0, 0.0);
+    HepMC::GenVertex *myVertex = new HepMC::GenVertex( myPos, -1 );
+    const HepMC::FourVector fourMomentum1( 0.0, 0.0, 1.0, 1.0*CLHEP::TeV);
+    HepMC::GenParticle* inParticle1 = new HepMC::GenParticle(fourMomentum1, pdgid1, 2);
+    myVertex->add_particle_in(inParticle1);
+    const HepMC::FourVector fourMomentum2( 0.0, 0.0, -1.0, 1.0*CLHEP::TeV);
+    HepMC::GenParticle* inParticle2 = new HepMC::GenParticle(fourMomentum2, pdgid2, 2);
+    myVertex->add_particle_in(inParticle2);
+    const HepMC::FourVector fourMomentum3( 0.0, 1.0, 0.0, 1.0*CLHEP::TeV);
+    HepMC::GenParticle* inParticle3 = new HepMC::GenParticle(fourMomentum3, pdgid1, 1);
+    myVertex->add_particle_out(inParticle3);
+    const HepMC::FourVector fourMomentum4( 0.0, -1.0, 0.0, 1.0*CLHEP::TeV);
+    HepMC::GenParticle* inParticle4 = new HepMC::GenParticle(fourMomentum4, pdgid2, 1);
+    myVertex->add_particle_out(inParticle4);
+    anEvent->add_vertex( myVertex );
+    anEvent->set_signal_process_vertex( myVertex );
+    anEvent->set_beam_particles(inParticle1,inParticle2);
+    HepMC::GenParticle* inParticle5 = new HepMC::GenParticle(fourMomentum3, pdgid1, 1);
+    inParticle5->suggest_barcode(1010003);
+    inParticle5->set_status(1);
+
+    MockTruthIncident ti(FaserDetDescr::fFaserTracker, 2);
+    HepMC::FourVector vtxPosition(0.0, 40.0, 0.0, 40.0);
+    EXPECT_CALL(ti, physicsProcessCode())
+      .Times(2)
+      .WillOnce(::testing::Return(21))
+      .WillOnce(::testing::Return(21));
+    EXPECT_CALL(ti, parentBarcode())
+      .Times(3)
+      .WillOnce(::testing::Return(inParticle3->barcode()))
+      .WillOnce(::testing::Return(inParticle3->barcode()))
+      .WillOnce(::testing::Return(inParticle3->barcode()));
+    EXPECT_CALL(ti, parentParticle())
+      .Times(2)
+      .WillOnce(::testing::Return(inParticle3))
+      .WillOnce(::testing::Return(inParticle3));
+    EXPECT_CALL(ti, parentParticleAfterIncident(1010003))
+      .Times(1)
+      .WillOnce(::testing::Return(inParticle5));
+    // _ is a matcher where the argument can be any value of the
+    // correct type. Needed because the argument to the pass method is
+    // a reference to an abstract interface class (IFaserTruthIncident).
+    EXPECT_CALL(*truthStrategy, pass(::testing::_))
+      .Times(1)
+      .WillOnce(::testing::Return(true));
+
+    registerTruthIncident(ti);
+    HepMC::GenVertex* generated = anEvent->barcode_to_vertex(-200001); //Find a nicer way to get this.
+    ASSERT_EQ( vtxPosition, generated->position() );
+    ASSERT_EQ( 1021, generated->id() );
+    ASSERT_EQ( -200001, generated->barcode() ); // by construction at the moment
+    ASSERT_EQ( 1, generated->particles_in_size());
+    ASSERT_EQ( inParticle3, *(generated->particles_in_const_begin()));
+    ASSERT_EQ( 1, generated->particles_out_size());
+    ASSERT_EQ( inParticle5, *(generated->particles_out_const_begin()));
+  }
+
+  //TODO Add tests for the following cases:
+  // 1) parent destroyed, all child particles pass cuts
+  // 2) parent destroyed, some child particles pass cuts
+  // 3) parent survives, all child particles pass cuts
+  // 4) parent survives, some child particles pass cuts
+  // 5) quasi-stable particle, pre-defined decay
+  // 6) quasi-stable particle, additional interaction, survives, no child particles pass cuts
+  // 7) quasi-stable particle, additional interaction, survives, some child particles pass cuts
+  // 8) quasi-stable particle, additional interaction, destroyed, no child particles pass cuts
+  // 9) quasi-stable particle, additional interaction, destroyed, some child particles pass cuts
+
+} // <-- namespace ISFTesting
+
+int main(int argc, char *argv[]) {
+  ::testing::InitGoogleTest( &argc, argv );
+
+  // gets stuck forever while trying to finalize boost stuff inside SGTools:
+  //return RUN_ALL_TESTS();
+  // skips proper finalization:
+  std::quick_exit( RUN_ALL_TESTS() );
+}
+
diff --git a/Simulation/ISF/ISF_Core/FaserISF_Services/test/TruthSvc_test.txt b/Simulation/ISF/ISF_Core/FaserISF_Services/test/TruthSvc_test.txt
new file mode 100644
index 00000000..c2e90e97
--- /dev/null
+++ b/Simulation/ISF/ISF_Core/FaserISF_Services/test/TruthSvc_test.txt
@@ -0,0 +1,2 @@
+// Need to set a BarcodeService as TruthSvc will otherwise fail to initialize
+TruthSvc.BarcodeSvc = "Barcode::LegacyBarcodeSvc/LegacyBarcodeSvc";
diff --git a/Simulation/ISF/ISF_Geant4/FaserISF_Geant4Event/CMakeLists.txt b/Simulation/ISF/ISF_Geant4/FaserISF_Geant4Event/CMakeLists.txt
new file mode 100644
index 00000000..0922e0b1
--- /dev/null
+++ b/Simulation/ISF/ISF_Geant4/FaserISF_Geant4Event/CMakeLists.txt
@@ -0,0 +1,49 @@
+################################################################################
+# Package: FaserISF_Geant4Event
+################################################################################
+
+# Declare the package name:
+atlas_subdir( FaserISF_Geant4Event )
+
+# Declare the package's dependencies:
+atlas_depends_on_subdirs( PUBLIC
+                          Simulation/ISF/ISF_Core/FaserISF_Event
+                          Simulation/ISF/ISF_Core/ISF_Event
+                          Simulation/ISF/ISF_Core/FaserISF_Interfaces
+                          Simulation/ISF/ISF_Core/ISF_Interfaces
+                          Simulation/G4Sim/SimHelpers
+                          Simulation/Barcode/BarcodeEvent
+                          Simulation/G4Sim/FaserMCTruth
+                          PRIVATE
+                          DetectorDescription/GeoPrimitives )
+
+
+        
+# External dependencies:
+find_package( CLHEP )
+find_package( Eigen )
+find_package( Geant4 )
+find_package( HepMC )
+find_package( ROOT COMPONENTS Core Tree MathCore Hist RIO pthread )
+find_package( XercesC )
+
+# Component(s) in the package:
+atlas_add_library( FaserISF_Geant4Event
+                   src/*.cxx
+                   PUBLIC_HEADERS FaserISF_Geant4Event
+                   INCLUDE_DIRS ${ROOT_INCLUDE_DIRS}
+                   ${XERCESC_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS}
+                   ${HEPMC_INCLUDE_DIRS} ${GEANT4_INCLUDE_DIRS}
+                   ${EIGEN_INCLUDE_DIRS}
+                   LINK_LIBRARIES ${ROOT_LIBRARIES}
+                   ${XERCESC_LIBRARIES} ${CLHEP_LIBRARIES} ${HEPMC_LIBRARIES}
+                   ${GEANT4_LIBRARIES} ${EIGEN_LIBRARIES} FaserISF_Event ISF_Event
+                   SimHelpers GeoPrimitives FaserMCTruth)
+
+#atlas_add_test(SOURCES
+#               INCLUDE_DIRS ${CLHEP_INCLUDE_DIRS}
+#              ${HEPMC_INCLUDE_DIRS} ${EIGEN_INCLUDE_DIRS}
+#               LINK_LIBRARIES
+#              ${CLHEP_LIBRARIES} ${HEPMC_LIBRARIES}
+#               ${EIGEN_LIBRARIES} ISF_Event SimHelpers GeoPrimitives
+#               BarcodeEvent MCTruth)
diff --git a/Simulation/ISF/ISF_Geant4/FaserISF_Geant4Event/FaserISF_Geant4Event/FaserGeant4TruthIncident.h b/Simulation/ISF/ISF_Geant4/FaserISF_Geant4Event/FaserISF_Geant4Event/FaserGeant4TruthIncident.h
new file mode 100644
index 00000000..da2d10d8
--- /dev/null
+++ b/Simulation/ISF/ISF_Geant4/FaserISF_Geant4Event/FaserISF_Geant4Event/FaserGeant4TruthIncident.h
@@ -0,0 +1,124 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef ISF_GEANT4TOOLS_FaserGeant4TruthIncident_H
+#define ISF_GEANT4TOOLS_FaserGeant4TruthIncident_H
+
+// std
+#include <vector>
+
+// ISF includes
+#include "FaserISF_Event/IFaserTruthIncident.h"
+
+// HepMC includes
+#include "HepMC/SimpleVector.h"
+
+//Geant4 includes
+#include "G4ThreeVector.hh"
+
+// forward declarations
+class G4Step;
+class G4Track;
+class FaserEventInformation;
+
+namespace iGeant4 {
+
+  /** @class FaserGeant4TruthIncident
+
+      ISF_Geant4 specific implementation of the ISF::IFaserTruthIncident
+
+      @author Andreas.Schaelicke@cern.ch
+   */
+
+  class FaserGeant4TruthIncident : public ISF::IFaserTruthIncident {
+    public:
+      FaserGeant4TruthIncident( const G4Step*,
+                           FaserDetDescr::FaserRegion geoID,
+                           FaserEventInformation* eventInfo);
+      virtual ~FaserGeant4TruthIncident() {};
+
+      /** Return HepMC position of the truth vertex */
+      const HepMC::FourVector&  position() const override final;
+
+      /** Return category of the physics process represented by the truth incident (eg hadronic, em, ..) */
+      int                       physicsProcessCategory() const override final;
+      /** Return specific physics process code of the truth incident (eg ionisation, bremsstrahlung, ..)*/
+      Barcode::PhysicsProcessCode physicsProcessCode() const override final;
+
+      /** Return p^2 of the parent particle */
+      double                    parentP2() const override final;
+      /** Return pT^2 of the parent particle */
+      double                    parentPt2() const override final;
+      /** Return Ekin of the parent particle */
+      double                    parentEkin() const override final;
+      /** 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;
+      /** 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;
+
+      /** Return p of the i-th child particle */
+      const G4ThreeVector       childP(unsigned short index) const;
+      /** Return p^2 of the i-th child particle */
+      double                    childP2(unsigned short index) const override final;
+      /** Return pT^2 of the i-th child particle */
+      double                    childPt2(unsigned short index) const override final;
+      /** Return Ekin of the i-th child particle */
+      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;
+      /** Set the the barcode of all child particles to the given bc */
+      void                      setAllChildrenBarcodes(Barcode::ParticleBarcode bc) override final;
+
+      /**  The interaction classifications are described as follows:
+           STD_VTX: interaction of a particle without a pre-defined decay;
+           QS_SURV_VTX: a particle with a pre-defined decay under-going a
+           non-destructive interaction;
+           QS_DEST_VTX: a particle with a pre-defined decay under-going a
+           destructive interaction other than its pre-defined decay;
+           QS_PREDEF_VTX: a particle under-going its pre-defined decay */
+      ISF::InteractionClass_t interactionClassification() const override final;
+
+      // only called once accepted
+
+      /** Return the parent particle as a HepMC particle type */
+      HepMC::GenParticle*       parentParticle() const 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,
+                                              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;
+    private:
+      FaserGeant4TruthIncident();
+      /** prepare the child particles */
+      inline void prepareChildren() const;
+
+      /** 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
+
+      mutable bool                  m_positionSet;
+      mutable HepMC::FourVector     m_position;
+      const G4Step*                 m_step;
+
+      FaserEventInformation*        m_eventInfo;
+      mutable bool                  m_childrenPrepared;
+      mutable std::vector<const G4Track*> m_children;
+
+      HepMC::GenParticle*           m_parentParticleAfterIncident;
+   };
+
+}
+
+#endif // ISF_GEANT4TOOLS_FaserGeant4TruthIncident_H
diff --git a/Simulation/ISF/ISF_Geant4/FaserISF_Geant4Event/FaserISF_Geant4Event/FaserISFG4GeoHelper.h b/Simulation/ISF/ISF_Geant4/FaserISF_Geant4Event/FaserISF_Geant4Event/FaserISFG4GeoHelper.h
new file mode 100644
index 00000000..8dc36356
--- /dev/null
+++ b/Simulation/ISF/ISF_Geant4/FaserISF_Geant4Event/FaserISF_Geant4Event/FaserISFG4GeoHelper.h
@@ -0,0 +1,29 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef ISF_GEANT4EVENT_FASERISFG4GEOHELPER_H
+#define ISF_GEANT4EVENT_FASERISFG4GEOHELPER_H
+
+
+#include "FaserDetDescr/FaserRegion.h"
+#include "G4Step.hh"
+
+namespace iGeant4 {
+
+class FaserISFG4GeoHelper 
+{
+
+ public:
+  FaserISFG4GeoHelper() = delete;
+
+  static FaserDetDescr::FaserRegion nextGeoId(const G4Step* aStep, int truthVolLevel);
+  static bool checkVolumeDepth(G4LogicalVolume* logicalVol, int volLevel, int depth=0);
+
+  private:
+  static G4LogicalVolume *s_vetoLV, *s_triggerLV, *s_preshowerLV, *s_sctLV, *s_dipoleLV, *s_ecalLV, *s_emulsionLV;
+
+};
+
+}
+#endif
diff --git a/Simulation/ISF/ISF_Geant4/FaserISF_Geant4Event/FaserISF_Geant4Event/FaserISFG4Helper.h b/Simulation/ISF/ISF_Geant4/FaserISF_Geant4Event/FaserISF_Geant4Event/FaserISFG4Helper.h
new file mode 100644
index 00000000..33211d1e
--- /dev/null
+++ b/Simulation/ISF/ISF_Geant4/FaserISF_Geant4Event/FaserISF_Geant4Event/FaserISFG4Helper.h
@@ -0,0 +1,64 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef ISF_GEANT4TOOLS_FASERISFG4HELPER_H
+#define ISF_GEANT4TOOLS_FASERISFG4HELPER_H
+
+// Barcode includes
+#include "BarcodeEvent/Barcode.h"
+
+// ISF Includes
+#include "FaserISF_Event/FaserISFParticle.h"
+
+// MCTruth includes
+#include "FaserMCTruth/FaserVTrackInformation.h"
+
+// forward declarations
+namespace HepMC {
+  class GenParticle;
+}
+namespace ISF {
+  class TruthBinding;
+}
+class FaserVTrackInformation;
+class FaserTrackInformation;
+class FaserEventInformation;
+class G4Track;
+
+namespace iGeant4 {
+
+class FaserISFG4Helper {
+
+ public:
+  FaserISFG4Helper() = delete;
+  
+  /** convert the given G4Track into an ISFParticle */
+  static ISF::FaserISFParticle* convertG4TrackToISFParticle(const G4Track& aTrack,
+                                                       const ISF::FaserISFParticle& parent,
+                                                       ISF::TruthBinding* truth = nullptr);
+  
+  /** return a valid UserInformation object of the G4Track for use within the ISF */
+  static FaserVTrackInformation* getISFTrackInfo(const G4Track& aTrack);
+  
+  /** link the given G4Track to the given ISFParticle */
+  static void setG4TrackInfoFromBaseISFParticle( G4Track& aTrack,
+                                                 const ISF::FaserISFParticle& baseIsp,
+                                                 bool setReturnToISF=false );
+  
+  /** 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,
+                                   TrackClassification classification,
+                                   HepMC::GenParticle *nonRegeneratedTruthParticle = nullptr);
+  
+  /** return pointer to current EventInformation */
+  static FaserEventInformation* getEventInformation();
+ 
+ private:
+ 
+};
+}
+
+#endif // ISF_GEANT4TOOLS_FASERISFG4HELPER_H
diff --git a/Simulation/ISF/ISF_Geant4/FaserISF_Geant4Event/src/FaserGeant4TruthIncident.cxx b/Simulation/ISF/ISF_Geant4/FaserISF_Geant4Event/src/FaserGeant4TruthIncident.cxx
new file mode 100644
index 00000000..293dc427
--- /dev/null
+++ b/Simulation/ISF/ISF_Geant4/FaserISF_Geant4Event/src/FaserGeant4TruthIncident.cxx
@@ -0,0 +1,374 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// class header
+#include "FaserISF_Geant4Event/FaserGeant4TruthIncident.h"
+
+// package includes
+#include "FaserISF_Geant4Event/FaserISFG4Helper.h"
+
+// Atlas G4 Helpers
+#include "FaserMCTruth/FaserEventInformation.h"
+#include "FaserMCTruth/FaserTrackBarcodeInfo.h"
+#include "FaserMCTruth/FaserTrackHelper.h"
+#include "FaserMCTruth/FaserTrackInformation.h"
+#include "FaserMCTruth/FaserPrimaryParticleInformation.h"
+
+// Units
+#include "GaudiKernel/PhysicalConstants.h"
+
+// HepMC includes
+#include "HepMC/GenParticle.h"
+
+// Geant4 includes
+#include "G4Step.hh"
+#include "G4Track.hh"
+#include "G4ThreeVector.hh"
+#include "G4VProcess.hh"
+
+#include "G4TrackStatus.hh"
+#include "G4ProcessType.hh"
+#include "G4EmProcessSubType.hh"
+#include "G4DynamicParticle.hh"
+#include "G4PrimaryParticle.hh"
+
+#include "G4EventManager.hh"
+#include "G4Event.hh"
+
+/*
+  Comments:
+  what about parent particle surviving (e.g. bremstrahlung)
+
+
+  Existing code:
+  Simulation/G4Sim/SimHelpers/src/StepHelper.cxx
+  - provids convenient information of a G4Step
+  Simulation/G4Utilities/G4TruthStrategies/src/BremsstrahlungStrategy.cxx
+  - retrives information from a G4Step (via StepHelper)
+  Simulation/G4Sim/FaserMCTruth/MCTruth/TruthStrategy.h
+  - common base for different truth strategies
+  Simulation/G4Sim/FaserMCTruth/src/EventInformation.cxx
+  - stores HepMCevent in G4
+  Simulation/G4Sim/FaserMCTruth/src/TrackInformation.cxx
+  Simulation/G4Sim/FaserMCTruth/src/TrackHelper.cxx
+  - store/manage barcode
+*/
+
+
+iGeant4::FaserGeant4TruthIncident::FaserGeant4TruthIncident( const G4Step *step,
+                                               FaserDetDescr::FaserRegion geoID,
+                                               FaserEventInformation *eventInfo) :
+  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)
+{
+}
+
+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;
+  }
+
+  return m_position;
+}
+
+int iGeant4::FaserGeant4TruthIncident::physicsProcessCategory() const {
+  const G4VProcess *process = m_step->GetPostStepPoint()->GetProcessDefinedStep();
+  // TODO: need to check that G4ProcessSubTypes Match Barcode::PhysicsProcessCode
+  return process->GetProcessType();
+}
+
+Barcode::PhysicsProcessCode iGeant4::FaserGeant4TruthIncident::physicsProcessCode() const {
+  const G4VProcess *process = m_step->GetPostStepPoint()->GetProcessDefinedStep();
+  // TODO: need to check that G4ProcessSubTypes Match Barcode::PhysicsProcessCode
+  return process->GetProcessSubType();
+}
+
+double iGeant4::FaserGeant4TruthIncident::parentP2() const {
+  const G4ThreeVector & mom= m_step->GetPreStepPoint()->GetMomentum();
+  return mom.mag2();
+}
+
+double iGeant4::FaserGeant4TruthIncident::parentPt2() const {
+  const G4ThreeVector & mom= m_step->GetPreStepPoint()->GetMomentum();
+  return mom.perp2();
+}
+
+double iGeant4::FaserGeant4TruthIncident::parentEkin() const {
+  return (m_step->GetPreStepPoint()->GetKineticEnergy()/CLHEP::MeV);
+}
+
+int iGeant4::FaserGeant4TruthIncident::parentPdgCode() const {
+  return  m_step->GetTrack()->GetDefinition()->GetPDGEncoding();
+}
+
+Barcode::ParticleBarcode iGeant4::FaserGeant4TruthIncident::parentBarcode() const {
+  auto parent = parentParticle();
+
+  return (parent) ? parent->barcode() : Barcode::fUndefinedBarcode;
+}
+
+HepMC::GenParticle* iGeant4::FaserGeant4TruthIncident::parentParticle() const {
+  HepMC::GenParticle* hepParticle = m_eventInfo->GetCurrentlyTraced();
+
+  return hepParticle;
+}
+
+bool iGeant4::FaserGeant4TruthIncident::parentSurvivesIncident() const { 
+  const G4Track *track = m_step->GetTrack();
+
+  // check if particle is a alive in G4 or in ISF
+  if ( particleAlive(track) ) {
+    return true;
+  } else {
+    return false;
+  }
+}
+
+HepMC::GenParticle* iGeant4::FaserGeant4TruthIncident::parentParticleAfterIncident(Barcode::ParticleBarcode newBarcode) {
+  const G4Track *track = m_step->GetTrack();
+
+  // check if particle is a alive in G4 or in ISF
+  if ( !parentSurvivesIncident() ) {
+    return nullptr;
+  }
+
+  // internally cache the HepMC representation of the parent particle
+  // (to allow multiple calls to this method on the same instance)
+  if ( !m_parentParticleAfterIncident ) {
+    // create new HepMC particle, using momentum and energy
+    // from G4DynamicParticle (which should be equivalent to postStep)
+    m_parentParticleAfterIncident = convert(track, newBarcode, false);
+    
+    m_eventInfo->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)
+      //tInfo->SetParticle( m_parentParticleAfterIncident );
+      int regenerationNr = tInfo->GetRegenerationNr();
+      regenerationNr++;
+      tInfo->SetRegenerationNr(regenerationNr);
+      if ( tHelper.IsPrimary() ) { 
+        tInfo->SetClassification(RegeneratedPrimary);
+      }
+    }
+
+  } // <-- end if m_parentParticleAfterIncident is not filled
+
+
+  // return the HepMC particle representation of the parent
+  return m_parentParticleAfterIncident;
+}
+
+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();
+}
+
+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);
+}
+
+HepMC::GenParticle* iGeant4::FaserGeant4TruthIncident::childParticle(unsigned short i,
+                                                            Barcode::ParticleBarcode newBarcode) const {
+  prepareChildren();
+
+  // the G4Track instance for the current child particle
+  const G4Track* thisChildTrack = m_children[i];
+
+  // NB: NOT checking if secondary is actually alive. Even with zero momentum,
+  //     secondary could decay right away and create further particles which pass the
+  //     truth strategies.
+
+  HepMC::GenParticle* 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 );    
+  } 
+    
+  trackInfo->SetParticle(hepParticle);
+  trackInfo->SetClassification(RegisteredSecondary);
+  trackInfo->SetRegenerationNr(0);
+
+  return hepParticle;
+}
+
+
+HepMC::GenParticle* iGeant4::FaserGeant4TruthIncident::updateChildParticle(unsigned short index,
+                                                                      HepMC::GenParticle *existingChild) const {
+  prepareChildren();
+
+  // the G4Track instance for the current child particle
+  const G4Track* thisChildTrack = m_children[index];
+
+  // NB: NOT checking if secondary is actually alive. Even with zero momentum,
+  //     secondary could decay right away and create further particles which pass the
+  //     truth strategies.
+
+  const G4ThreeVector & mom =  thisChildTrack->GetMomentum();
+  const double energy =  thisChildTrack->GetTotalEnergy();
+  const int pdgCode = thisChildTrack->GetDefinition()->GetPDGEncoding();
+  const HepMC::FourVector fourMomentum( mom.x(), mom.y(), mom.z(), energy);
+
+  // This is the case for quasi-stable particle simulation
+  if(existingChild->pdg_id()!=pdgCode) {
+    G4ExceptionDescription description;
+    description << G4String("updateChildParticle: ") + "Wrong PDG ID mismatch between G4Track and GenParticle";
+    G4Exception("iGeant4::FaserGeant4TruthIncident", "PDGIDMisMatch", FatalException, description);
+  }
+  existingChild->set_momentum(fourMomentum);
+
+  FaserTrackHelper tHelper(thisChildTrack);
+  FaserTrackInformation *trackInfo = tHelper.GetTrackInformation();
+
+  // needed to make AtlasG4 work with ISF TruthService
+  if(trackInfo==nullptr) {
+    trackInfo = new FaserTrackInformation( existingChild );
+    thisChildTrack->SetUserInformation( trackInfo );
+  }
+
+  trackInfo->SetParticle(existingChild);
+  trackInfo->SetClassification(RegisteredSecondary);
+  trackInfo->SetRegenerationNr(0);
+
+  //FIXME!!
+  return existingChild;
+}
+
+
+bool iGeant4::FaserGeant4TruthIncident::particleAlive(const G4Track *track) const {
+  G4TrackStatus  trackStatus = track->GetTrackStatus();
+
+  if ( trackStatus!=fAlive ) {
+    // parent does not exist in G4 anymore after this step
+
+    // check whether the particle was returned to ISF
+    auto*    trackInfo = FaserISFG4Helper::getISFTrackInfo( *track );
+    bool returnedToISF = trackInfo ? trackInfo->GetReturnedToISF() : false;
+    if ( !returnedToISF ) {
+      // particle was not sent to ISF either
+      return false;
+    }
+  }
+
+  return true;
+}
+
+
+HepMC::GenParticle* iGeant4::FaserGeant4TruthIncident::convert(const G4Track *track, const int barcode, const bool secondary) const {
+
+  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);
+
+  // 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 (secondary &&
+      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() );
+    newParticle->suggest_barcode( ppi->GetParticleBarcode() );
+  } else {
+    newParticle->suggest_barcode( barcode );
+  }
+
+  return newParticle;
+}
+
+
+void iGeant4::FaserGeant4TruthIncident::prepareChildren() const {
+
+  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;
+  }
+}
+
+/**  The interaction classifications are described as follows:
+     STD_VTX: interaction of a particle without a pre-defined decay;
+     QS_SURV_VTX: a particle with a pre-defined decay under-going a
+     non-destructive interaction;
+     QS_DEST_VTX: a particle with a pre-defined decay under-going a
+     destructive interaction other than its pre-defined decay;
+     QS_PREDEF_VTX: a particle under-going its pre-defined decay */
+ISF::InteractionClass_t iGeant4::FaserGeant4TruthIncident::interactionClassification() const {
+  G4Track* track=m_step->GetTrack();
+  const G4DynamicParticle* dynPart = track->GetDynamicParticle();
+  bool parentIsQuasiStable = (nullptr!=(dynPart->GetPreAssignedDecayProducts()));
+  const G4VProcess *process = m_step->GetPostStepPoint()->GetProcessDefinedStep();
+  const int processType = process->GetProcessType();
+  const int processSubType = process->GetProcessSubType();
+  ISF::InteractionClass_t classification(ISF::STD_VTX);
+  if(parentIsQuasiStable) {
+    if(this->parentSurvivesIncident()) {
+      classification = ISF::QS_SURV_VTX;
+    }
+    else if(processType==6 && processSubType==201) {
+      classification = ISF::QS_PREDEF_VTX;
+    }
+    else {
+      classification = ISF::QS_DEST_VTX;
+    }
+  }
+  return classification;
+  // end of code to determine interaction type
+}
diff --git a/Simulation/ISF/ISF_Geant4/FaserISF_Geant4Event/src/FaserISFG4GeoHelper.cxx b/Simulation/ISF/ISF_Geant4/FaserISF_Geant4Event/src/FaserISFG4GeoHelper.cxx
new file mode 100644
index 00000000..5dd4fa5d
--- /dev/null
+++ b/Simulation/ISF/ISF_Geant4/FaserISF_Geant4Event/src/FaserISFG4GeoHelper.cxx
@@ -0,0 +1,153 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "FaserISF_Geant4Event/FaserISFG4GeoHelper.h"
+
+// Athena includes
+#include "FaserDetDescr/FaserRegion.h"
+
+//Geant4
+#include "G4LogicalVolumeStore.hh"
+#include "G4Step.hh"
+#include "globals.hh"
+
+#include "G4TransportationManager.hh"
+#include "SimHelpers/StepHelper.h"
+
+#include <iostream>
+
+G4LogicalVolume* iGeant4::FaserISFG4GeoHelper::s_sctLV = nullptr;
+G4LogicalVolume* iGeant4::FaserISFG4GeoHelper::s_vetoLV = nullptr;
+G4LogicalVolume* iGeant4::FaserISFG4GeoHelper::s_triggerLV = nullptr;
+G4LogicalVolume* iGeant4::FaserISFG4GeoHelper::s_preshowerLV = nullptr;
+G4LogicalVolume* iGeant4::FaserISFG4GeoHelper::s_ecalLV = nullptr;
+G4LogicalVolume* iGeant4::FaserISFG4GeoHelper::s_dipoleLV = nullptr;
+G4LogicalVolume* iGeant4::FaserISFG4GeoHelper::s_emulsionLV = nullptr;
+
+//________________________________________________________________________
+FaserDetDescr::FaserRegion
+iGeant4::FaserISFG4GeoHelper::nextGeoId(const G4Step* aStep, int truthVolLevel)
+{
+
+  if (s_sctLV == nullptr && s_vetoLV == nullptr && s_triggerLV == nullptr && s_preshowerLV == nullptr && s_ecalLV == nullptr && s_emulsionLV == nullptr && s_dipoleLV == nullptr) // Initialize
+  { 
+    G4LogicalVolumeStore * lvs = G4LogicalVolumeStore::GetInstance();
+    for (size_t i = 0; i < lvs->size(); ++i) {
+      G4LogicalVolume* thisLV = (*lvs)[i];
+      if ( thisLV == nullptr ) { continue; }
+      G4String thisName = thisLV->GetName();
+      if ( ( s_sctLV == nullptr && thisName == "SCT::Station" ) || thisName == "SCT::SCT" ) { s_sctLV = thisLV; }
+      else if ( ( s_vetoLV == nullptr && thisName == "Veto::VetoStationA" ) || thisName == "Veto::Veto" ) { s_vetoLV = thisLV; }
+      else if ( ( s_triggerLV == nullptr && thisName == "Trigger::TriggerStationA" ) || thisName == "Trigger::Trigger" ) { s_triggerLV = thisLV; }
+      else if ( ( s_preshowerLV == nullptr && thisName == "Preshower::PreshowerStationA" ) || thisName == "Preshower::Preshower" ) { s_preshowerLV = thisLV; }
+      else if ( thisName == "Ecal::Ecal" ) { s_ecalLV = thisLV; }
+      else if ( thisName == "Dipole::Dipole" ) { s_dipoleLV = thisLV; }
+      else if ( ( s_emulsionLV == nullptr && thisName == "Emulsion::EmulsionStationA" ) || thisName == "Emulsion::Emulsion" )  { s_emulsionLV = thisLV; }
+    }
+
+    const auto& worldVolume = G4TransportationManager::GetTransportationManager()->GetNavigatorForTracking()->GetWorldVolume()->GetLogicalVolume();
+    FaserISFG4GeoHelper::checkVolumeDepth(worldVolume, truthVolLevel);
+  }
+
+  FaserDetDescr::FaserRegion nextGeoID = truthVolLevel > 1 ? FaserDetDescr::fFaserCavern
+                                                           : FaserDetDescr::fUndefinedFaserRegion;
+
+  const G4StepPoint *postStep = aStep->GetPostStepPoint();
+  bool leavingG4World       = postStep->GetStepStatus()==fWorldBoundary;
+
+  if ( leavingG4World ) {
+    nextGeoID = FaserDetDescr::fFaserCavern;
+    return nextGeoID;
+  }
+
+  // If in mother volume, treat as cavern
+  if (G4StepHelper::postStepBranchDepth(aStep)<truthVolLevel) {
+    nextGeoID = FaserDetDescr::fFaserCavern;
+    return nextGeoID;
+  }
+
+  G4LogicalVolume* postStepVolume = G4StepHelper::getPostStepLogicalVolume(aStep, truthVolLevel);
+  if (s_sctLV != nullptr && s_sctLV == postStepVolume )
+  {
+    nextGeoID = FaserDetDescr::fFaserTracker;
+  }
+  else if ((s_vetoLV != nullptr && s_vetoLV == postStepVolume) || 
+           (s_triggerLV != nullptr && s_triggerLV == postStepVolume) || 
+           (s_preshowerLV != nullptr && s_preshowerLV == postStepVolume))
+  {
+    nextGeoID = FaserDetDescr::fFaserScintillator;
+  }
+  else if (s_ecalLV != nullptr && s_ecalLV == postStepVolume)
+  {
+    nextGeoID = FaserDetDescr::fFaserCalorimeter;
+  }
+  else if (s_emulsionLV != nullptr && s_emulsionLV == postStepVolume)
+  {
+    nextGeoID = FaserDetDescr::fFaserNeutrino;
+  }
+  else if (s_dipoleLV != nullptr && s_dipoleLV == postStepVolume)
+  {
+    nextGeoID = FaserDetDescr::fFaserDipole;
+  }
+  else
+  {
+    nextGeoID = FaserDetDescr::fFaserCavern;
+  }
+  
+  return nextGeoID;
+}
+
+bool iGeant4::FaserISFG4GeoHelper::checkVolumeDepth(G4LogicalVolume* lv, int volLevel, int depth) 
+{
+  if (lv==nullptr) { return false; }
+
+  bool Cavern = false;
+  // Check the volumes rather explicitly
+
+  if ( ((s_sctLV != nullptr) && (lv->GetName() == s_sctLV->GetName())) ||
+       ((s_vetoLV != nullptr) && (lv->GetName() == s_vetoLV->GetName())) ||
+       ((s_triggerLV != nullptr) && (lv->GetName() == s_triggerLV->GetName())) ||
+       ((s_preshowerLV != nullptr) && (lv->GetName() == s_preshowerLV->GetName())) ||
+       ((s_dipoleLV != nullptr) && (lv->GetName() == s_dipoleLV->GetName())) ||
+       ((s_ecalLV != nullptr) && (lv->GetName() == s_ecalLV->GetName())) ||
+       ((s_emulsionLV != nullptr) && (lv->GetName() == s_emulsionLV->GetName())) ) {
+    if(depth!=volLevel) {
+      G4ExceptionDescription description;
+      description << "Volume " << lv->GetName() << " at depth " << depth << " instead of depth " << volLevel;
+      G4Exception("iGeant4::FaserISFG4GeoHelper", "checkVolumeDepth", FatalException, description);
+      return false; //The G4Exception call above should abort the job, but Coverity does not seem to pick this up.
+    }
+    G4cout << "Volume " << lv->GetName() << " is correctly registered at depth " << depth << G4endl;
+  }
+  // else if ( lv->GetName()=="BeamPipe::BeamPipeCentral" ) { // Things that are supposed to be one deeper
+  //   if (depth!=volLevel+1) {
+  //     G4ExceptionDescription description;
+  //     description << "Volume " << lv->GetName() << " at depth " << depth << " instead of depth " << volLevel+1;
+  //     G4Exception("iGeant4::FaserISFG4GeoHelper", "checkVolumeDepth", FatalException, description);
+  //     return false; //The G4Exception call above should abort the job, but Coverity does not seem to pick this up.
+  //   }
+  //   //ATH_MSG_DEBUG("Volume " << lv->GetName() << " is correctly registered at depth " << depth);
+  // }
+  else if ( lv->GetName().find("CavernInfra")!=std::string::npos ) { // Things that are supposed to be one shallower
+    if (depth==volLevel-1) {
+      Cavern=true;
+    G4cout << "Volume " << lv->GetName() << " is correctly registered at depth " << depth << G4endl;
+      // Note: a number of volumes exist with "CavernInfra" in the name at the wrong depth, so we just need to
+      //   check that there's at least one at the right depth
+    } // Check of volume level
+  } // Check of volume name
+
+  // Going through the volume depth
+  for (int i=0; i<lv->GetNoDaughters(); ++i) {
+    Cavern = Cavern || checkVolumeDepth( lv->GetDaughter(i)->GetLogicalVolume() , volLevel , depth+1 );
+  }
+  if (depth==0 && !Cavern && volLevel>1) {
+    G4ExceptionDescription description;
+    description << "No CavernInfra volume registered at depth " << volLevel-1;
+    G4Exception("iGeant4::FaserISFG4GeoHelper", "checkVolumeDepth", FatalException, description);
+    return false; //The G4Exception call above should abort the job, but Coverity does not seem to pick this up.
+  }
+
+  return Cavern;
+}
diff --git a/Simulation/ISF/ISF_Geant4/FaserISF_Geant4Event/src/FaserISFG4Helper.cxx b/Simulation/ISF/ISF_Geant4/FaserISF_Geant4Event/src/FaserISFG4Helper.cxx
new file mode 100644
index 00000000..10698d4b
--- /dev/null
+++ b/Simulation/ISF/ISF_Geant4/FaserISF_Geant4Event/src/FaserISFG4Helper.cxx
@@ -0,0 +1,115 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// class header
+#include "FaserISF_Geant4Event/FaserISFG4Helper.h"
+
+// Geant4 includes
+#include "G4Track.hh"
+#include "G4ThreeVector.hh"
+#include "G4EventManager.hh"
+#include "G4Event.hh"
+
+// G4Atlas includes
+#include "FaserMCTruth/FaserEventInformation.h"
+#include "FaserMCTruth/FaserTrackBarcodeInfo.h"
+#include "FaserMCTruth/FaserTrackInformation.h"
+
+// ISF includes
+#include "FaserISF_Event/FaserISFParticle.h"
+
+// ATLAS GeoPrimitves (Amg::Vector3D etc)
+#include "GeoPrimitives/GeoPrimitives.h"
+
+
+/** convert the given G4Track into an ISFParticle */
+ISF::FaserISFParticle*
+iGeant4::FaserISFG4Helper::convertG4TrackToISFParticle(const G4Track& aTrack,
+                                                       const ISF::FaserISFParticle& parent,
+                                                       ISF::TruthBinding* truth)
+{
+  const G4ThreeVector& g4pos = aTrack.GetPosition();
+  const double         gTime = aTrack.GetGlobalTime();
+  const Amg::Vector3D  position(g4pos.x(),g4pos.y(),g4pos.z());
+  
+  const G4ThreeVector& g4mom = aTrack.GetMomentum();
+  const Amg::Vector3D  momentum(g4mom.x(),g4mom.y(),g4mom.z());
+  
+  const G4ParticleDefinition &particleDefinition = *aTrack.GetDefinition();
+  double mass    = particleDefinition.GetPDGMass();
+  double charge  = particleDefinition.GetPDGCharge();
+  int    pdgID   = particleDefinition.GetPDGEncoding();
+
+  auto* genParticle = (truth) ? truth->getTruthParticle(): nullptr;
+  Barcode::ParticleBarcode barcode = (genParticle) ? genParticle->barcode() : Barcode::fUndefinedBarcode;
+
+  ISF::FaserISFParticle *isp = new ISF::FaserISFParticle( position,
+                                                momentum,
+                                                mass,
+                                                charge,
+                                                pdgID,
+                                                gTime,
+                                                parent,
+                                                barcode,
+                                                truth
+                                               );
+
+  return isp;
+}
+
+
+/** return a valid UserInformation object of the G4Track for use within the ISF */
+FaserVTrackInformation *
+iGeant4::FaserISFG4Helper::getISFTrackInfo(const G4Track& aTrack) 
+{
+  FaserVTrackInformation* trackInfo = static_cast<FaserVTrackInformation*>(aTrack.GetUserInformation());
+  return trackInfo;
+}
+
+
+/** link the given G4Track to the given ISFParticle */
+FaserTrackInformation*
+iGeant4::FaserISFG4Helper::attachTrackInfoToNewG4Track( G4Track& aTrack,
+                                                        const ISF::FaserISFParticle& baseIsp,
+                                                        TrackClassification classification,
+                                                        HepMC::GenParticle *nonRegeneratedTruthParticle)
+{
+  if ( aTrack.GetUserInformation() ) {
+    G4ExceptionDescription description;
+    description << G4String("FaserISFG4Helper::attachTrackInfoToNewG4Track: ")
+                << "Trying to attach new FaserTrackInformation object to G4Track which already has a TrackUserInformation attached (trackID: "
+                << aTrack.GetTrackID() << ", track pos: "<<aTrack.GetPosition() << ", mom: "<<aTrack.GetMomentum()
+                << ", parentID " << aTrack.GetParentID() << ")";
+    G4Exception("FaserISFG4Helper::attachTrackInfoToNewG4Track", "TrackUserInformationAlreadyExists", FatalException, description);
+    return nullptr;
+  }
+
+  auto* truthBinding = baseIsp.getTruthBinding();
+  if ( !truthBinding ) {
+    G4ExceptionDescription description;
+    description << G4String("FaserISFG4Helper::attachTrackInfoToNewG4Track: ")
+                << "No TruthBinding present in base FaserISFParticle (trackID: "
+                << aTrack.GetTrackID() << ", track pos: "<<aTrack.GetPosition() << ", mom: "<<aTrack.GetMomentum()
+                << ", parentID " << aTrack.GetParentID() << ", FaserISFParticle: "<<baseIsp<<")";
+    G4Exception("FaserISFG4Helper::attachTrackInfoToNewG4Track", "NoISFTruthBinding", FatalException, description);
+    return nullptr;
+  }
+
+  FaserTrackInformation *trackInfo = new FaserTrackInformation( nonRegeneratedTruthParticle, &baseIsp );
+  auto primaryTruthParticle   = truthBinding->getPrimaryTruthParticle();
+
+  trackInfo->SetPrimaryHepMCParticle( primaryTruthParticle );
+  trackInfo->SetClassification( classification );
+  aTrack.SetUserInformation( trackInfo );
+
+  return trackInfo;
+}
+
+/** return pointer to current EventInformation */
+FaserEventInformation*
+iGeant4::FaserISFG4Helper::getEventInformation()
+{
+  return ( static_cast<FaserEventInformation*> (G4EventManager::GetEventManager()->GetConstCurrentEvent()->GetUserInformation()) );
+}
+
diff --git a/Simulation/ISF/ISF_HepMC/FaserISF_HepMC_Interfaces/CMakeLists.txt b/Simulation/ISF/ISF_HepMC/FaserISF_HepMC_Interfaces/CMakeLists.txt
new file mode 100644
index 00000000..48e02e4b
--- /dev/null
+++ b/Simulation/ISF/ISF_HepMC/FaserISF_HepMC_Interfaces/CMakeLists.txt
@@ -0,0 +1,15 @@
+################################################################################
+# Package: FaserISF_HepMC_Interfaces
+################################################################################
+
+# Declare the package name:
+atlas_subdir( FaserISF_HepMC_Interfaces )
+
+# Declare the package's dependencies:
+atlas_depends_on_subdirs( PUBLIC
+                          GaudiKernel
+                          Simulation/ISF/ISF_Core/FaserISF_Event )
+
+# Install files from the package:
+atlas_install_headers( FaserISF_HepMC_Interfaces )
+
diff --git a/Simulation/ISF/ISF_HepMC/FaserISF_HepMC_Interfaces/FaserISF_HepMC_Interfaces/IFaserTruthStrategy.h b/Simulation/ISF/ISF_HepMC/FaserISF_HepMC_Interfaces/FaserISF_HepMC_Interfaces/IFaserTruthStrategy.h
new file mode 100644
index 00000000..47192a0d
--- /dev/null
+++ b/Simulation/ISF/ISF_HepMC/FaserISF_HepMC_Interfaces/FaserISF_HepMC_Interfaces/IFaserTruthStrategy.h
@@ -0,0 +1,44 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// IFaserTruthStrategy.h, (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#ifndef FASERISF_HEPMC_INTERFACES_IFASERTRUTHSTRATEGY_H
+#define FASERISF_HEPMC_INTERFACES_IFASERTRUTHSTRATEGY_H 1
+
+// Gaudi
+#include "GaudiKernel/IAlgTool.h"
+ 
+// forward declarations
+namespace HepMC {
+  class GenVertex;
+}
+namespace ISF {
+  class IFaserTruthIncident;
+
+  /**
+   @class IFaserTruthStrategy
+      
+   @todo : class description
+       
+   @author Elmar.Ritsch -at- cern.ch
+   */
+     
+  class IFaserTruthStrategy : virtual public IAlgTool {
+    public:
+       /// Creates the InterfaceID and interfaceID() method
+       DeclareInterfaceID(IFaserTruthStrategy, 1, 0);
+      
+      /** true if the IFaserTruthStrategy implementation applies to the given IFaserTruthIncident */
+      virtual bool pass( IFaserTruthIncident& incident) const = 0;
+      /** returns true if this truth strategy should be applied to the
+          region indicated by geoID*/
+      virtual bool appliesToRegion(unsigned short geoID) const = 0;
+  };
+
+} // end of namespace
+
+#endif // ISF_HEPMC_INTERFACES_ITRUTHSTRATEGY_H
diff --git a/Simulation/ISF/ISF_HepMC/FaserISF_HepMC_Tools/CMakeLists.txt b/Simulation/ISF/ISF_HepMC/FaserISF_HepMC_Tools/CMakeLists.txt
new file mode 100644
index 00000000..f533d839
--- /dev/null
+++ b/Simulation/ISF/ISF_HepMC/FaserISF_HepMC_Tools/CMakeLists.txt
@@ -0,0 +1,56 @@
+################################################################################
+# Package: FaserISF_HepMC_Tools
+################################################################################
+
+# Declare the package name:
+atlas_subdir( FaserISF_HepMC_Tools )
+
+# Declare the package's dependencies:
+atlas_depends_on_subdirs( PUBLIC
+                          GaudiKernel
+                          PRIVATE
+                          Control/AthenaBaseComps
+                          DetectorDescription/FaserDetDescr
+                          Generators/TruthUtils
+                          Simulation/ISF/ISF_Core/FaserISF_Event
+                          Simulation/ISF/ISF_Core/FaserISF_Interfaces
+                          Simulation/ISF/ISF_HepMC/FaserISF_HepMC_Interfaces
+                          Simulation/ISF/ISF_HepMC/ISF_HepMC_Interfaces
+                          Tools/PathResolver )
+
+# External dependencies:
+find_package( HepMC )
+find_package( ROOT COMPONENTS Core Tree MathCore Hist RIO pthread )
+find_package( GTest )
+find_package( GMock )
+
+# tag rootGraphicsLibs was not recognized in automatic conversion in cmt2cmake
+
+# Component(s) in the package:
+atlas_add_component( FaserISF_HepMC_Tools
+                     src/*.cxx
+                     src/components/*.cxx
+                     INCLUDE_DIRS ${ROOT_INCLUDE_DIRS} ${HEPMC_INCLUDE_DIRS}
+                     LINK_LIBRARIES ${ROOT_LIBRARIES} ${HEPMC_LIBRARIES} GaudiKernel FaserDetDescr AthenaBaseComps TruthUtils FaserISF_Event FaserISF_Interfaces PathResolver )
+
+# Tests
+#atlas_add_test( GenParticleGenericFilter_test
+#                SOURCES test/GenParticleGenericFilter_test.cxx src/GenParticleGenericFilter.cxx
+#                INCLUDE_DIRS ${GTEST_INCLUDE_DIRS} ${GMOCK_INCLUDE_DIRS} ${HEPMC_INCLUDE_DIRS}
+#                LINK_LIBRARIES ${GTEST_LIBRARIES} ${GMOCK_LIBRARIES} ${HEPMC_LIBRARIES} AthenaBaseComps )
+
+# Tests
+#atlas_add_test( GenParticleInteractingFilter_test
+#                SOURCES test/GenParticleInteractingFilter_test.cxx src/GenParticleInteractingFilter.cxx
+#                INCLUDE_DIRS ${GTEST_INCLUDE_DIRS} ${GMOCK_INCLUDE_DIRS} ${HEPMC_INCLUDE_DIRS}
+#                LINK_LIBRARIES ${GTEST_LIBRARIES} ${GMOCK_LIBRARIES} ${HEPMC_LIBRARIES} AthenaBaseComps TruthUtils )
+
+# Tests
+#atlas_add_test( GenParticleLifetimeFilter_test
+#                SOURCES test/GenParticleLifetimeFilter_test.cxx src/GenParticleLifetimeFilter.cxx
+#                INCLUDE_DIRS ${GTEST_INCLUDE_DIRS} ${GMOCK_INCLUDE_DIRS} ${HEPMC_INCLUDE_DIRS}
+#                LINK_LIBRARIES ${GTEST_LIBRARIES} ${GMOCK_LIBRARIES} ${HEPMC_LIBRARIES} AthenaBaseComps TruthUtils )
+
+# Install files from the package:
+atlas_install_python_modules( python/*.py )
+
diff --git a/Simulation/ISF/ISF_HepMC/FaserISF_HepMC_Tools/python/FaserISF_HepMC_ToolsConfigDb.py b/Simulation/ISF/ISF_HepMC/FaserISF_HepMC_Tools/python/FaserISF_HepMC_ToolsConfigDb.py
new file mode 100644
index 00000000..5c35e30d
--- /dev/null
+++ b/Simulation/ISF/ISF_HepMC/FaserISF_HepMC_Tools/python/FaserISF_HepMC_ToolsConfigDb.py
@@ -0,0 +1 @@
+from AthenaCommon.CfgGetter import addTool
diff --git a/Simulation/ISF/ISF_HepMC/FaserISF_HepMC_Tools/python/FaserISF_HepMC_ToolsConfigNew.py b/Simulation/ISF/ISF_HepMC/FaserISF_HepMC_Tools/python/FaserISF_HepMC_ToolsConfigNew.py
new file mode 100644
index 00000000..b4c32b99
--- /dev/null
+++ b/Simulation/ISF/ISF_HepMC/FaserISF_HepMC_Tools/python/FaserISF_HepMC_ToolsConfigNew.py
@@ -0,0 +1,208 @@
+# Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+
+"""
+Tools configurations for ISF
+KG Tan, 17/06/2012
+"""
+
+from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator
+from AthenaConfiguration.ComponentFactory import CompFactory
+
+ISF__FaserTruthStrategy, ISF__FaserGenParticlePositionFilter, ISF__FaserGenParticleGenericFilter=CompFactory.getComps("ISF__FaserTruthStrategy","ISF__FaserGenParticlePositionFilter","ISF__FaserGenParticleGenericFilter")
+
+from AthenaCommon.SystemOfUnits import MeV, mm
+
+#Functions yet to be migrated:
+#getParticleSimWhiteList, getParticlePositionFilterMS
+#getTruthStrategyGroupID, getTruthStrategyGroupIDHadInt, getTruthStrategyGroupCaloMuBrem_MC15, getTruthStrategyGroupCaloDecay, getValidationTruthStrategy, getLLPTruthStrategy
+
+#--------------------------------------------------------------------------------------------------
+## GenParticleFilters
+
+# def ParticleFinalStateFilterCfg(ConfigFlags, name="ISF_ParticleFinalStateFilter", **kwargs):
+#     result = ComponentAccumulator()
+#     G4NotInUse = not ConfigFlags.Sim.UsingGeant4
+#     G4NotInUse = G4NotInUse and ConfigFlags.Sim.ISFRun
+#     # use CheckGenInteracting==False to allow GenEvent neutrinos to propagate into the simulation
+#     kwargs.setdefault("CheckGenSimStable", G4NotInUse)
+#     kwargs.setdefault("CheckGenInteracting", G4NotInUse)
+
+#     result.setPrivateTools(ISF__GenParticleFinalStateFilter(name, **kwargs))
+#     return result
+
+# placeholder
+
+def FaserParticlePositionFilterCfg(ConfigFlags, name="ISF_FaserParticlePositionFilter", **kwargs):
+    result = ComponentAccumulator()
+    # ParticlePositionFilter
+    kwargs.setdefault('GeoIDService' , 'ISF_FaserGeoIDSvc'    ) 
+
+    result.setPrivateTools(ISF__FaserGenParticlePositionFilter(name, **kwargs))
+    return result
+
+# def ParticlePositionFilterIDCfg(ConfigFlags, name="ISF_ParticlePositionFilterID", **kwargs):
+#     # importing Reflex dictionary to access AtlasDetDescr::AtlasRegion enum
+#     import ROOT, cppyy
+#     cppyy.loadDictionary('AtlasDetDescrDict')
+#     AtlasRegion = ROOT.AtlasDetDescr
+
+#     kwargs.setdefault('CheckRegion'  , [ AtlasRegion.fAtlasID ] )
+#     return ParticlePositionFilterCfg(ConfigFlags, name, **kwargs)
+
+# def ParticlePositionFilterCaloCfg(ConfigFlags, name="ISF_ParticlePositionFilterCalo", **kwargs):
+#     # importing Reflex dictionary to access AtlasDetDescr::AtlasRegion enum
+#     import ROOT, cppyy
+#     cppyy.loadDictionary('AtlasDetDescrDict')
+#     AtlasRegion = ROOT.AtlasDetDescr
+
+#     kwargs.setdefault('CheckRegion'  , [ AtlasRegion.fAtlasID,
+#                                             AtlasRegion.fAtlasForward,
+#                                             AtlasRegion.fAtlasCalo ] )
+#     return ParticlePositionFilterCfg(ConfigFlags, name, **kwargs)
+
+# def ParticlePositionFilterMSCfg(name="ISF_ParticlePositionFilterMS", **kwargs):
+#     # importing Reflex dictionary to access AtlasDetDescr::AtlasRegion enum
+#     import ROOT, cppyy
+#     cppyy.loadDictionary('AtlasDetDescrDict')
+#     AtlasRegion = ROOT.AtlasDetDescr
+
+#     kwargs.setdefault('CheckRegion'  , [ AtlasRegion.fAtlasID,
+#                                             AtlasRegion.fAtlasForward,
+#                                             AtlasRegion.fAtlasCalo,
+#                                             AtlasRegion.fAtlasMS ] )
+#     return ParticlePositionFilterCfg(name, **kwargs)
+
+# def ParticlePositionFilterWorldCfg(ConfigFlags, name="ISF_ParticlePositionFilterWorld", **kwargs):
+#     # importing Reflex dictionary to access AtlasDetDescr::AtlasRegion enum
+#     import ROOT, cppyy
+#     cppyy.loadDictionary('AtlasDetDescrDict')
+#     AtlasRegion = ROOT.AtlasDetDescr
+#     kwargs.setdefault('CheckRegion'  , [ AtlasRegion.fAtlasID,
+#                                             AtlasRegion.fAtlasForward,
+#                                             AtlasRegion.fAtlasCalo,
+#                                             AtlasRegion.fAtlasMS,
+#                                             AtlasRegion.fAtlasCavern ] )
+#     return ParticlePositionFilterCfg(ConfigFlags, name, **kwargs)
+
+# def ParticlePositionFilterDynamicCfg(ConfigFlags, name="ISF_ParticlePositionFilterDynamic", **kwargs):
+#     # automatically choose the best fitting filter region
+    
+#     #if ConfigFlags.Detector.SimulateMuon:
+#     if True:
+#       return ParticlePositionFilterWorldCfg(ConfigFlags, name, **kwargs)
+#     elif ConfigFlags.Detector.SimulateCalo:
+#       return ParticlePositionFilterCaloCfg(ConfigFlags, name, **kwargs)
+#     elif ConfigFlags.Detector.SimulateID:
+#       return ParticlePositionFilterIDCfg(ConfigFlags, name, **kwargs)
+#     else:
+#       return ParticlePositionFilterWorldCfg(ConfigFlags, name, **kwargs)
+
+# def GenParticleInteractingFilterCfg(ConfigFlags, name="ISF_GenParticleInteractingFilter", **kwargs):
+#     result = ComponentAccumulator()
+
+#     #todo (dnoel) - add this functionality
+#     #from G4AtlasApps.SimFlags import simFlags
+#     #simdict = simFlags.specialConfiguration.get_Value()
+#     #if simdict is not None and "InteractingPDGCodes" in simdict:
+#     #    kwargs.setdefault('AdditionalInteractingParticleTypes', eval(simdict["InteractingPDGCodes"]))
+#     #if simdict is not None and "NonInteractingPDGCodes" in simdict:
+#     #    kwargs.setdefault('AdditionalNonInteractingParticleTypes', eval(simdict["InteractingNonPDGCodes"]))
+
+#     result.setPrivateTools(ISF__GenParticleInteractingFilter(name, **kwargs))
+#     return result
+
+# def EtaPhiFilterCfg(ConfigFlags, name="ISF_EtaPhiFilter", **kwargs):
+#     result = ComponentAccumulator()
+#     # EtaPhiFilter
+#     EtaRange = 7.0 if ConfigFlags.Detector.SimulateLucid else 6.0
+#     kwargs.setdefault('MinEta' , -EtaRange)
+#     kwargs.setdefault('MaxEta' , EtaRange)
+#     kwargs.setdefault('MaxApplicableRadius', 30*mm)
+
+#     result.setPrivateTools(ISF__GenParticleGenericFilter(name, **kwargs))
+#     return result
+
+# placeholder
+
+def FaserParticleGenericFilterCfg(ConfigFlags, name="ISF_FaserGenericFilter", **kwargs):
+    result = ComponentAccumulator()
+    result.setPrivateTools(ISF__FaserGenParticleGenericFilter(name, **kwargs))
+    return result
+
+
+#--------------------------------------------------------------------------------------------------
+## Truth Strategies
+
+# Brems: fBremsstrahlung (3)
+# Conversion: fGammaConversion (14), fGammaConversionToMuMu (15), fPairProdByCharged (4)
+# Decay: 201-298, fAnnihilation(5), fAnnihilationToMuMu (6), fAnnihilationToHadrons (7)
+# Ionization: fIonisation (2), fPhotoElectricEffect (12)
+# Hadronic: (111,121,131,141,151,161,210)
+# Compton: fComptonScattering (13)
+# G4 process types:
+#  http://www-geant4.kek.jp/lxr/source//processes/management/include/G4ProcessType.hh
+# G4 EM sub types:
+#  http://www-geant4.kek.jp/lxr/source//processes/electromagnetic/utils/include/G4EmProcessSubType.hh
+# G4 HadInt sub types:
+#  http://www-geant4.kek.jp/lxr/source//processes/hadronic/management/include/G4HadronicProcessType.hh#L46
+
+def FaserTruthStrategyCfg(ConfigFlags, name="ISF_FaserTruthStrategy", **kwargs):
+    result = ComponentAccumulator()
+    import ROOT, cppyy
+    cppyy.loadDictionary('FaserDetDescrDict')
+    FaserRegion = ROOT.FaserDetDescr
+    #
+    # Save truth in all regions
+    #
+    kwargs.setdefault('Regions', [FaserRegion.fFaserNeutrino,
+                                  FaserRegion.fFaserScintillator,
+                                  FaserRegion.fFaserTracker,
+                                  FaserRegion.fFaserDipole,
+                                  FaserRegion.fFaserCalorimeter,
+                                  FaserRegion.fFaserCavern])
+    kwargs.setdefault('ParentMinEkin', 1*MeV)
+    kwargs.setdefault('ChildMinEkin', 1*MeV)
+    result.setPrivateTools(ISF__FaserTruthStrategy(name, **kwargs))
+    return result
+
+# def TruthStrategyGroupID_MC15Cfg(ConfigFlags, name="ISF_MCTruthStrategyGroupID_MC15", **kwargs):
+#     result = ComponentAccumulator()
+#     kwargs.setdefault('ParentMinPt'         , 100.*MeV)
+#     kwargs.setdefault('ChildMinPt'          , 300.*MeV)
+#     kwargs.setdefault('VertexTypes'         , [ 3, 14, 15, 4, 5, 6, 7, 2, 12, 13 ])
+#     kwargs.setdefault('VertexTypeRangeLow'  , 201)  # All kinds of decay processes
+#     kwargs.setdefault('VertexTypeRangeHigh' , 298)  # ...
+#     kwargs.setdefault('Regions', [1,2]) # Could import AtlasDetDescr::AtlasRegion enum as in TruthService CfgGetter methods here
+#     result.setPrivateTools(ISF__GenericTruthStrategy(name, **kwargs))
+#     return result
+
+# def TruthStrategyGroupIDHadInt_MC15Cfg(ConfigFlags, name="ISF_MCTruthStrategyGroupIDHadInt_MC15", **kwargs):
+#     result = ComponentAccumulator()
+#     kwargs.setdefault('ParentMinPt'                       , 100.*MeV)
+#     kwargs.setdefault('ChildMinPt'                        , 300.*MeV)
+#     kwargs.setdefault('VertexTypes'                       , [ 111, 121, 131, 141, 151, 161, 210 ])
+#     kwargs.setdefault('AllowChildrenOrParentPassKineticCuts' , True)
+#     kwargs.setdefault('Regions', [1])
+#     result.setPrivateTools(ISF__GenericTruthStrategy(name, **kwargs))
+#     return result
+
+# def TruthStrategyGroupCaloMuBremCfg(ConfigFlags, name="ISF_MCTruthStrategyGroupCaloMuBrem", **kwargs):
+#     result = ComponentAccumulator()
+#     kwargs.setdefault('ParentMinEkin'       , 500.*MeV)
+#     kwargs.setdefault('ChildMinEkin'        , 100.*MeV)
+#     kwargs.setdefault('VertexTypes'         , [ 3 ])
+#     kwargs.setdefault('ParentPDGCodes'      , [ 13, -13 ])
+#     kwargs.setdefault('Regions', [3])
+#     result.setPrivateTools(ISF__GenericTruthStrategy(name, **kwargs))
+#     return result
+
+# def TruthStrategyGroupCaloDecay_MC15Cfg(ConfigFlags, name="ISF_MCTruthStrategyGroupCaloDecay_MC15", **kwargs):
+#     result = ComponentAccumulator()
+#     kwargs.setdefault('ParentMinEkin'       , 1000.*MeV)
+#     kwargs.setdefault('ChildMinEkin'        , 500.*MeV)
+#     kwargs.setdefault('VertexTypes'         , [ 5, 6, 7 ])
+#     kwargs.setdefault('VertexTypeRangeLow'  , 201)  # All kinds of decay processes
+#     kwargs.setdefault('VertexTypeRangeHigh' , 298)  # ...
+#     kwargs.setdefault('Regions', [3])
+#     result.setPrivateTools(ISF__GenericTruthStrategy(name, **kwargs))
+#     return result
diff --git a/Simulation/ISF/ISF_HepMC/FaserISF_HepMC_Tools/src/FaserGenParticleGenericFilter.cxx b/Simulation/ISF/ISF_HepMC/FaserISF_HepMC_Tools/src/FaserGenParticleGenericFilter.cxx
new file mode 100644
index 00000000..85666c62
--- /dev/null
+++ b/Simulation/ISF/ISF_HepMC/FaserISF_HepMC_Tools/src/FaserGenParticleGenericFilter.cxx
@@ -0,0 +1,134 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+/*
+ * @author Elmar Ritsch
+ * @date October 2016
+ * @brief A generic particle filter tool for HepMC::GenParticle types
+ */
+
+
+// class header include
+#include "FaserGenParticleGenericFilter.h"
+
+// HepMC includes
+#include "HepMC/GenParticle.h"
+#include "HepMC/GenVertex.h"
+
+// STL includes
+#include <limits>
+#include <algorithm>
+
+/** Constructor **/
+ISF::FaserGenParticleGenericFilter::FaserGenParticleGenericFilter( const std::string& t,
+                                                                   const std::string& n,
+                                                                   const IInterface* p )
+  : base_class(t,n,p),
+    m_minTheta(0),
+    m_maxTheta(M_PI),
+    m_minEnergy(std::numeric_limits<decltype(m_minEnergy)>::lowest()),
+    m_maxEnergy(std::numeric_limits<decltype(m_maxEnergy)>::max()),
+    m_pdgs(),
+    m_maxTransverseDistance(std::numeric_limits<decltype(m_maxTransverseDistance)>::max()),
+    m_minLongitudinalPosition(std::numeric_limits<decltype(m_minLongitudinalPosition)>::max()),
+    m_maxLongitudinalPosition(std::numeric_limits<decltype(m_maxLongitudinalPosition)>::max())
+{
+    // different cut parameters
+    declareProperty("MinTheta",
+                    m_minTheta,
+                    "Minimum Particle Polar Angle");
+    declareProperty("MaxTheta",
+                    m_maxTheta,
+                    "Maximum Particle Polar Angle");
+    declareProperty("MinEnergy",
+                    m_minEnergy,
+                    "Minimum Particle Kinetic Energy");
+    declareProperty("MaxEnergy",
+                    m_maxEnergy,
+                    "Maximum Particle Kinetic Energy");
+    declareProperty("ParticlePDG",
+                    m_pdgs,
+                    "List of accepted particle PDG IDs (any accepted if empty)");
+    declareProperty("MaxTransverseDistance",
+                    m_maxTransverseDistance,
+                    "Only particles with std::max(ProductionVertex[0],ProductionVertex[1])<MaxTransverseDistance may get filtered out");
+    declareProperty("MinLongitudinalPosition",
+                    m_minLongitudinalPosition,
+                    "Minimum value of ProductionVertex[2] for which cut applies");
+    declareProperty("MaxLongitudinalPosition",
+                    m_maxLongitudinalPosition,
+                    "Maximum value of ProductionVertex[2] for which cut applies");
+}
+
+
+/** Athena algtool's Hooks */
+StatusCode  ISF::FaserGenParticleGenericFilter::initialize()
+{
+    ATH_MSG_VERBOSE("initialize() ...");
+    ATH_MSG_VERBOSE("initialize() successful");
+    return StatusCode::SUCCESS;
+}
+
+
+/** Athena algtool's Hooks */
+StatusCode  ISF::FaserGenParticleGenericFilter::finalize()
+{
+    ATH_MSG_VERBOSE("finalize() ...");
+    ATH_MSG_VERBOSE("finalize() successful");
+    return StatusCode::SUCCESS;
+}
+
+
+/** Returns whether the given particle passes all cuts or not */
+bool ISF::FaserGenParticleGenericFilter::pass(const HepMC::GenParticle& particle) const
+{
+  bool pass = true;
+
+  const auto* productionVertex = particle.production_vertex();
+  const auto* position = productionVertex ? &productionVertex->position() : nullptr;
+  if (!position || 
+    (std::max(position->x(),position->y()) <= m_maxTransverseDistance && 
+     position->z()>= m_minLongitudinalPosition && 
+     position->z()<= m_maxLongitudinalPosition)) {
+    pass = check_cuts_passed(particle);
+  }
+
+  const auto& momentum = particle.momentum();
+  ATH_MSG_VERBOSE( "GenParticle '" << particle << "' with "
+                   << (position ? "pos: (" + std::to_string(position->x()) + "," + std::to_string(position->y()) + "," + std::to_string(position->z()) + ")" : "")
+                   << ", mom: Ek = " << std::max(0.0,momentum.e() - momentum.m()) << ", theta = " << momentum.theta() 
+                   << " did " << (pass ? "" : "NOT ")
+                   << "pass the cuts.");
+  return pass;
+}
+
+
+/** Check whether the given particle passes all configure cuts or not */
+bool ISF::FaserGenParticleGenericFilter::check_cuts_passed(const HepMC::GenParticle &particle) const {
+  const auto& momentum = particle.momentum();
+  double ek = std::max(0.0, momentum.e() - momentum.m());
+  double theta = momentum.theta();
+  int pdg = particle.pdg_id();
+
+  // check the particle pdg code
+  if( m_pdgs.size() && std::find(std::begin(m_pdgs), std::end(m_pdgs), pdg) == std::end(m_pdgs) ) {
+    return false;
+  }
+
+  // check the momentum cuts
+  if (ek < m_minEnergy) {
+    return false;
+  }
+  if (ek > m_maxEnergy) {
+    return false;
+  }
+
+  // check the theta cuts
+  if (theta<m_minTheta || theta>m_maxTheta) {
+    return false;
+  }
+
+  // all cuts passed
+  return true;
+}
diff --git a/Simulation/ISF/ISF_HepMC/FaserISF_HepMC_Tools/src/FaserGenParticleGenericFilter.h b/Simulation/ISF/ISF_HepMC/FaserISF_HepMC_Tools/src/FaserGenParticleGenericFilter.h
new file mode 100644
index 00000000..31538631
--- /dev/null
+++ b/Simulation/ISF/ISF_HepMC/FaserISF_HepMC_Tools/src/FaserGenParticleGenericFilter.h
@@ -0,0 +1,78 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+/**
+ * @author Elmar Ritsch
+ * @date October 2016
+ * @brief A generic particle filter tool for HepMC::GenParticle types
+ */
+
+#ifndef FASERISF_HEPMC_FASERGENPARTICLEGENERICFILTER_H
+#define FASERISF_HEPMC_FASERGENPARTICLEGENERICFILTER_H 1
+
+// STL includes
+#include <string>
+#include <vector>
+
+// FrameWork includes
+#include "AthenaBaseComps/AthAlgTool.h"
+// ISF includes
+#include "ISF_HepMC_Interfaces/IGenParticleFilter.h"
+
+namespace ISF {
+
+// ISF forward declarations
+class FaserISFParticle;
+
+/// used to store a list of PDG particle codes
+typedef std::vector<int>      PDGCodes;
+
+
+/**
+ * @class FaserGenParticleGenericFilter
+ * @headerfile FaserGenParticleGenericFilter.h
+ *
+ * @brief Core Athena algorithm for the Integrated Simulation Framework
+ *
+ * This GenParticle filter provides a general way of selecting/filtering out particles
+ * during GenEvent read-in.
+ */
+  class FaserGenParticleGenericFilter : public extends<AthAlgTool, IGenParticleFilter> {
+
+  public:
+    /// Constructor with framework parameters
+    FaserGenParticleGenericFilter( const std::string& t, const std::string& n, const IInterface* p );
+
+    /// Empty Destructor
+    ~FaserGenParticleGenericFilter(){}
+
+    /// Athena algtool's Hooks
+    StatusCode  initialize();
+    StatusCode  finalize();
+
+    /// Interface method that returns whether the given particle passes all cuts or not
+    bool pass(const HepMC::GenParticle& particle) const;
+
+  private:
+    /// Check whether the given particle passes all configure cuts or not
+    bool check_cuts_passed(const HepMC::GenParticle& particle) const;
+
+    /// the cuts defined by the use
+    double        m_minTheta;   //!< min polar angle
+    double        m_maxTheta;   //!< max polar angle
+    double        m_minEnergy;  //!< min kinetic energy cut
+    double        m_maxEnergy;  //!< max kinetic energy cut
+    PDGCodes      m_pdgs;       //!< list of accepted particle PDG IDs (any accepted if empty)
+
+    /// Geometrical region (=transverse distance from z-axis) within which this filter is applicable
+    double        m_maxTransverseDistance;
+    /// Range along z-axis that filter applies
+    double        m_minLongitudinalPosition;
+    double        m_maxLongitudinalPosition;
+};
+
+} // ISF namespace
+
+
+#endif //> !FASERISF_HEPMC_FASERGENPARTICLEGENERICFILTER_H
diff --git a/Simulation/ISF/ISF_HepMC/FaserISF_HepMC_Tools/src/FaserGenParticlePositionFilter.cxx b/Simulation/ISF/ISF_HepMC/FaserISF_HepMC_Tools/src/FaserGenParticlePositionFilter.cxx
new file mode 100644
index 00000000..7c710b64
--- /dev/null
+++ b/Simulation/ISF/ISF_HepMC/FaserISF_HepMC_Tools/src/FaserGenParticlePositionFilter.cxx
@@ -0,0 +1,95 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// FaserGenParticlePositionFilter.cxx, (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+// class header include
+#include "FaserGenParticlePositionFilter.h"
+
+// HepMC includes
+#include "HepMC/GenParticle.h"
+#include "HepMC/GenVertex.h"
+
+/** Constructor **/
+ISF::FaserGenParticlePositionFilter::FaserGenParticlePositionFilter( const std::string& t,
+                                                                const std::string& n,
+                                                                const IInterface* p )
+  : base_class(t,n,p),
+    m_geoIDSvc("ISF_FaserGeoIDSvc", n),
+    m_checkRegion()
+{
+    // the GeoID indentification service
+    declareProperty("GeoIDService",
+        m_geoIDSvc,
+        "The FaserGeoID Service");
+    declareProperty("CheckRegion",
+        m_checkRegion,
+        "Check if the given particles are within the specified regions");
+}
+
+
+// Athena algtool's Hooks
+StatusCode  ISF::FaserGenParticlePositionFilter::initialize()
+{
+    ATH_MSG_VERBOSE("initialize()");
+
+    // retrieve the GeoIDService
+    if ( m_geoIDSvc.retrieve().isFailure()){
+        ATH_MSG_ERROR( "Could not retrieve " << m_geoIDSvc << ". Abort.");
+        return StatusCode::FAILURE;
+    }
+
+    ATH_MSG_VERBOSE("initialize() successful");
+    return StatusCode::SUCCESS;
+}
+
+
+/** does the given particle pass the filter? */
+bool ISF::FaserGenParticlePositionFilter::pass(const HepMC::GenParticle& particle) const
+{
+  // the GenParticle production vertex
+  HepMC::GenVertex* vtx = particle.production_vertex();
+
+  // no production vertex?
+  if (!vtx) {
+    ATH_MSG_DEBUG("GenParticle does not have a production vertex, filtering it out");
+    return false;
+  }
+
+  // (x,y,z) position
+  HepMC::ThreeVector pos = vtx->point3d();
+
+  bool inside = false;
+  // check if the particle position is inside (or on surface)
+  // of any of the given ISF Simulation GeoIDs
+  std::vector<int>::const_iterator checkRegionIt    = m_checkRegion.begin();
+  std::vector<int>::const_iterator checkRegionItEnd = m_checkRegion.end();
+  for ( ; (checkRegionIt!=checkRegionItEnd) && (!inside); checkRegionIt++) {
+    // consult the GeoID identification service
+    ISF::InsideType insideCheck = m_geoIDSvc->inside( pos.x(),
+                                                      pos.y(),
+                                                      pos.z(),
+                                                      FaserDetDescr::FaserRegion(*checkRegionIt) );
+    // is inside only if ==fInside or ==fSurface
+    inside |= (insideCheck==ISF::fInside) || (insideCheck==ISF::fSurface);
+  }
+
+
+  // return whether pos was inside any of the simulation geometries
+  if (inside)
+    ATH_MSG_VERBOSE("GenParticle is inside FaserVolume and passed the filter");
+  else
+    ATH_MSG_VERBOSE("GenParticle is outside FaserVolume and got fitered out");
+  return inside;
+}
+
+
+StatusCode  ISF::FaserGenParticlePositionFilter::finalize()
+{
+  ATH_MSG_VERBOSE("Finalizing ...");
+  return StatusCode::SUCCESS;
+}
+
diff --git a/Simulation/ISF/ISF_HepMC/FaserISF_HepMC_Tools/src/FaserGenParticlePositionFilter.h b/Simulation/ISF/ISF_HepMC/FaserISF_HepMC_Tools/src/FaserGenParticlePositionFilter.h
new file mode 100644
index 00000000..41387278
--- /dev/null
+++ b/Simulation/ISF/ISF_HepMC/FaserISF_HepMC_Tools/src/FaserGenParticlePositionFilter.h
@@ -0,0 +1,58 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// GenParticlePositionFilter.h, (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#ifndef FASERISF_HEPMC_FASERGENPARTICLEPOSITIONFILTER_H
+#define FASERISF_HEPMC_FASERGENPARTICLEPOSITIONFILTER_H 1
+
+// STL includes
+#include <string>
+#include <vector>
+
+// FrameWork includes
+#include "GaudiKernel/ServiceHandle.h"
+#include "AthenaBaseComps/AthAlgTool.h"
+
+// ISF includes
+#include "ISF_HepMC_Interfaces/IGenParticleFilter.h"
+
+// ISF includes
+#include "FaserISF_Interfaces/IFaserGeoIDSvc.h"
+
+namespace ISF {
+
+  /** @class FaserGenParticlePositionFilter
+  
+      Particle filter by position, to be used for initial GenEvent read-in.
+  
+      @author Andreas.Salzburger -at- cern.ch
+     */
+  class FaserGenParticlePositionFilter : public extends<AthAlgTool, IGenParticleFilter> { 
+      
+    public: 
+      //** Constructor with parameters */
+      FaserGenParticlePositionFilter( const std::string& t, const std::string& n, const IInterface* p );
+      
+      /** Destructor */
+      ~FaserGenParticlePositionFilter(){}
+
+      /** Athena algtool's Hooks */
+      StatusCode  initialize();
+      StatusCode  finalize();
+
+      /** does the given particle pass the filter? */
+      bool pass(const HepMC::GenParticle& particle) const;
+	  
+	private:
+      ServiceHandle<IFaserGeoIDSvc>     m_geoIDSvc;
+      std::vector<int>                  m_checkRegion;
+  }; 
+  
+}
+
+
+#endif //> !FASERISF_HEPMC_FASERGENPARTICLEPOSITIONFILTER_H
diff --git a/Simulation/ISF/ISF_HepMC/FaserISF_HepMC_Tools/src/FaserTruthStrategy.cxx b/Simulation/ISF/ISF_HepMC/FaserISF_HepMC_Tools/src/FaserTruthStrategy.cxx
new file mode 100644
index 00000000..933dae8f
--- /dev/null
+++ b/Simulation/ISF/ISF_HepMC/FaserISF_HepMC_Tools/src/FaserTruthStrategy.cxx
@@ -0,0 +1,166 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// FaserTruthStrategy.cxx, (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+// class header include
+#include "FaserTruthStrategy.h"
+
+// ISF includes
+#include "FaserISF_Event/IFaserTruthIncident.h"
+#include "FaserISF_Event/FaserISFParticle.h"
+
+/** Constructor **/
+ISF::FaserTruthStrategy::FaserTruthStrategy(const std::string& t, const std::string& n, const IInterface* p) :
+  base_class(t,n,p),
+  m_parentEkin(-1.),
+  m_childEkin(-1.),
+  m_allowChildrenOrParentPass(false),
+  m_vertexTypesVector(0),
+  m_vertexTypes(),
+  m_doVertexRangeCheck(false),
+  m_vertexTypeRangeLow(0),
+  m_vertexTypeRangeHigh(0),
+  m_vertexTypeRangeLength(0),
+  m_parentPdgCodesVector(0),
+  m_parentPdgCodes()
+{
+    // provide either a Ekin cut for the parent and child particles respectively.
+    // if none are given, it will not use Ekin cuts
+    declareProperty("ParentMinEkin"             , m_parentEkin           );
+    declareProperty("ChildMinEkin"              , m_childEkin        );
+    // if set to true, kinetic cuts are passed even if only child particles pass them
+    // (used for special cases such as de-excitation)
+    declareProperty("AllowChildrenOrParentPassKineticCuts" , m_allowChildrenOrParentPass );
+    declareProperty("VertexTypes"                , m_vertexTypesVector   );
+    declareProperty("VertexTypeRangeLow"         , m_vertexTypeRangeLow  );
+    declareProperty("VertexTypeRangeHigh"        , m_vertexTypeRangeHigh );
+    declareProperty("ParentPDGCodes"            , m_parentPdgCodesVector  );
+    declareProperty("Regions"                   , m_regionListProperty );
+}
+
+/** Destructor **/
+ISF::FaserTruthStrategy::~FaserTruthStrategy()
+{
+}
+
+// Athena algtool's Hooks
+StatusCode  ISF::FaserTruthStrategy::initialize()
+{
+    ATH_MSG_VERBOSE("Initializing ...");
+
+    // (*) setup parent particle cuts
+    // -----
+    //     (compute and store the squared cut parameters (faster comparisons))
+    // check whether the user input makes sense (error case)
+    if ( m_parentEkin<0. ) m_parentEkin  = 0.; 
+
+    // (*) setup child particle cuts
+    // check whether the user input makes sense (error case)
+    if ( m_childEkin<0. ) m_childEkin  = 0.;
+
+    // VertexTypeRanges:
+    //
+    // check whether user input makes sense:
+    if ( m_vertexTypeRangeHigh < m_vertexTypeRangeLow) {
+      ATH_MSG_ERROR("The given parameter VertexTypeRangeLow is bigger than VertexTypeRangeHigh. ABORT");
+      return StatusCode::FAILURE;
+    }
+    // the length of the given vertex type range
+    m_vertexTypeRangeLength = unsigned(m_vertexTypeRangeHigh - m_vertexTypeRangeLow) + 1;
+    // if neither lower now upper range limit given, disable range check
+    m_doVertexRangeCheck    = m_vertexTypeRangeLow && m_vertexTypeRangeHigh;
+
+
+    // fill PDG code std::set used for optimized search
+    m_parentPdgCodes.insert( m_parentPdgCodesVector.begin(), m_parentPdgCodesVector.end());
+
+    // fill vertex type std::set used for optimized search
+    m_vertexTypes.insert( m_vertexTypesVector.begin(), m_vertexTypesVector.end());
+
+    for(auto region : m_regionListProperty.value()) {
+      if(region < FaserDetDescr::fFirstFaserRegion || region >= FaserDetDescr::fNumFaserRegions) {
+        ATH_MSG_ERROR("Unknown Region (" << region << ") specified. Please check your configuration.");
+        return StatusCode::FAILURE;
+      }
+    }
+    return StatusCode::SUCCESS;
+}
+
+StatusCode  ISF::FaserTruthStrategy::finalize()
+{
+    ATH_MSG_VERBOSE("Finalizing ...");
+    return StatusCode::SUCCESS;
+}
+
+bool ISF::FaserTruthStrategy::pass( IFaserTruthIncident& ti) const {
+
+  // (1.) energy check
+  // ----
+  //
+  {
+    // check whether parent particle passes cut or not
+    bool primFail = (ti.parentEkin() < m_parentEkin) ;
+
+    // if parent particle failed and strategy does not
+    // allow for child-only pass -> failed
+    if ( ( primFail && (!m_allowChildrenOrParentPass) ) ) {
+      return false;
+    }
+
+    // check child particles
+    bool secPass =  ti.childrenEkinPass(m_childEkin);
+
+    // if child particles do not pass cuts
+    if (!secPass) {
+      if (!m_allowChildrenOrParentPass) {
+        // child particles were required to pass cuts but did not
+        return false;
+      } else if (primFail) {
+        // neither parent nor child particles passed cuts
+        return false;
+      }
+    }
+  }
+
+
+  // (2.) parent particle PDG code check
+  // ----
+  // check whether parent PDG code matches with any of the given ones
+  if (  m_parentPdgCodes.size() &&
+       (m_parentPdgCodes.find(ti.parentPdgCode()) == m_parentPdgCodes.end()) ) {
+
+    // parent particle PDG code not found
+    return false;
+  }
+
+
+  // (3.) vertex type check
+  // ----
+  if ( m_doVertexRangeCheck || m_vertexTypes.size()) {
+    int vxtype = ti.physicsProcessCode();
+
+    // (3.1) vxtype in given range?: this is a small performance trick (only one comparison operator to check if within range)
+    //  -> exactly equivalent to:  m_doVertexRangeCheck  && (m_vertexTypeLow<=vxtype) && (vxtype<=m_vertexTypeRangeHigh)
+    bool vtxTypeRangePassed = m_doVertexRangeCheck && ( unsigned(vxtype-m_vertexTypeRangeLow) < m_vertexTypeRangeLength );
+    // (3.2) if not in range or range check disabled, check whether vxtype
+    //       std::set contains the given vertex type
+    if ( (!vtxTypeRangePassed) && (m_vertexTypes.find(vxtype)==m_vertexTypes.end()) ) {
+        // vxtype not registered -> not passed
+        return false;
+    }
+  }
+
+  // all cuts passed
+  return true;
+}
+
+bool ISF::FaserTruthStrategy::appliesToRegion(unsigned short geoID) const
+{
+  return std::find( m_regionListProperty.begin(),
+                    m_regionListProperty.end(),
+                    geoID ) != m_regionListProperty.end();
+}
diff --git a/Simulation/ISF/ISF_HepMC/FaserISF_HepMC_Tools/src/FaserTruthStrategy.h b/Simulation/ISF/ISF_HepMC/FaserISF_HepMC_Tools/src/FaserTruthStrategy.h
new file mode 100644
index 00000000..9a7b0475
--- /dev/null
+++ b/Simulation/ISF/ISF_HepMC/FaserISF_HepMC_Tools/src/FaserTruthStrategy.h
@@ -0,0 +1,84 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// FaserTruthStrategy.h, (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#ifndef FASERISF_TOOLS_FASERTRUTHSTRATEGY_H
+#define FASERISF_TOOLS_FASERTRUTHSTRATEGY_H 1
+
+// stl includes
+#include <set>
+#include <vector>
+
+// Athena includes
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "FaserDetDescr/FaserRegion.h"
+
+// ISF includes
+#include "FaserISF_HepMC_Interfaces/IFaserTruthStrategy.h"
+
+namespace ISF {
+  typedef std::vector<int>              VertexTypesVector;
+  typedef std::set<int>                 VertexTypesSet;
+  typedef std::vector<int>              PDGCodesVector;
+  typedef std::set<int>                 PDGCodesSet;
+
+  /** @class FaserTruthStrategy
+
+      A multi-purpose implementation of an ISF TruthStrategy.
+  
+      @author Elmar.Ritsch -at- cern.ch
+     */
+  class FaserTruthStrategy final : public extends<AthAlgTool, IFaserTruthStrategy> {
+      
+    public: 
+     /** Constructor with parameters */
+     FaserTruthStrategy( const std::string& t, const std::string& n, const IInterface* p );
+
+     /** Destructor */
+     ~FaserTruthStrategy();
+
+     // Athena algtool's Hooks
+     virtual StatusCode  initialize() override;
+     virtual StatusCode  finalize() override;
+
+     /** true if the ITruthStrategy implementation applies to the given IFaserTruthIncident */
+     virtual bool pass( IFaserTruthIncident& incident) const override;
+
+     virtual bool appliesToRegion(unsigned short geoID) const override;
+	  private:
+     /** parent kinetic energy / transverse momentum cuts
+         (pT is stored as pT^2 which allows for faster comparisons) */
+    //  bool                                   m_useParentPt;         //!< use pT or Ekin cuts?
+    //  double                                 m_parentPt2;           //!< parent particle
+     double                                 m_parentEkin;          //!< parent particle
+
+     /** child particle kinetic energy / transverse momentum cuts
+         (pT is stored as pT^2 which allows for faster comparisons) */
+    //  bool                                   m_useChildPt;          //!< use pT or Ekin cuts?
+    //  double                                 m_childPt2;            //!< pT momentum cut
+     double                                 m_childEkin;           //!< Ekin cut
+     bool                                   m_allowChildrenOrParentPass; //!< pass cuts if parent did not
+
+     /** vertex type (physics code) checks */
+     VertexTypesVector                      m_vertexTypesVector;  //!< Python property
+     VertexTypesSet                         m_vertexTypes;        //!< optimized for search
+     bool                                   m_doVertexRangeCheck;
+     int                                    m_vertexTypeRangeLow;
+     int                                    m_vertexTypeRangeHigh;
+     unsigned                               m_vertexTypeRangeLength;
+
+     /** PDG code checks */
+     PDGCodesVector                         m_parentPdgCodesVector;  //!< Python property
+     PDGCodesSet                            m_parentPdgCodes;        //!< optimized for search
+
+    IntegerArrayProperty            m_regionListProperty;
+   }; 
+  
+}
+
+
+#endif //> !FASERISF_TOOLS_FASERTRUTHSTRATEGY_H
diff --git a/Simulation/ISF/ISF_HepMC/FaserISF_HepMC_Tools/src/components/FaserISF_HepMC_Tools_entries.cxx b/Simulation/ISF/ISF_HepMC/FaserISF_HepMC_Tools/src/components/FaserISF_HepMC_Tools_entries.cxx
new file mode 100644
index 00000000..9880bfbc
--- /dev/null
+++ b/Simulation/ISF/ISF_HepMC/FaserISF_HepMC_Tools/src/components/FaserISF_HepMC_Tools_entries.cxx
@@ -0,0 +1,7 @@
+#include "../FaserTruthStrategy.h"
+#include "../FaserGenParticleGenericFilter.h"
+#include "../FaserGenParticlePositionFilter.h"
+
+DECLARE_COMPONENT( ISF::FaserTruthStrategy )
+DECLARE_COMPONENT( ISF::FaserGenParticleGenericFilter )
+DECLARE_COMPONENT( ISF::FaserGenParticlePositionFilter )
\ No newline at end of file
diff --git a/Simulation/README.md b/Simulation/README.md
index 14718f6d..9ad2f25f 100644
--- a/Simulation/README.md
+++ b/Simulation/README.md
@@ -1,6 +1,6 @@
 To generate Calypso MC data from an installation (run) directory:
 
-1) edit the G4FaserApp/test/runG4.py file to setup the job
+1) edit the G4FaserAlg/test/runG4.py file to setup the job
 ....the default generator is particle-gun; it can also read EVNT files but note that the Veto is far away from (0,0,0) where most ATLAS generators put things by default
 ....read the comments carefully as a few other things have to be changed in the job options to switch between internal generator and generator data-file
 
diff --git a/Tracker/TrackerAlignTools/TrackerAlignGenTools/src/TrackerAlignDBTool.cxx b/Tracker/TrackerAlignTools/TrackerAlignGenTools/src/TrackerAlignDBTool.cxx
index f1f2fcde..aa8f049d 100644
--- a/Tracker/TrackerAlignTools/TrackerAlignGenTools/src/TrackerAlignDBTool.cxx
+++ b/Tracker/TrackerAlignTools/TrackerAlignGenTools/src/TrackerAlignDBTool.cxx
@@ -245,13 +245,13 @@ StatusCode TrackerAlignDBTool::createDB() const
         Amg::Transform3D globshift;
         globshift.setIdentity();
         // Tracker upstream
-        ident1 = m_sctid->wafer_id(-1, 0, 0, 0, 0);
+        ident1 = m_sctid->wafer_id(1, 0, 0, 0, 0);
         pat->add(ident1, Amg::EigenTransformToCLHEP(globshift));
         // Tracker central
-        ident1 = m_sctid->wafer_id(0, 0, 0, 0, 0);
+        ident1 = m_sctid->wafer_id(2, 0, 0, 0, 0);
         pat->add(ident1, Amg::EigenTransformToCLHEP(globshift));
         // Tracker downstream
-        ident1 = m_sctid->wafer_id(1, 0, 0, 0, 0);
+        ident1 = m_sctid->wafer_id(3, 0, 0, 0, 0);
         pat->add(ident1, Amg::EigenTransformToCLHEP(globshift));
     } 
     else
@@ -317,9 +317,9 @@ std::string TrackerAlignDBTool::dirkey(const int station,
   } else {
     if (level==2) result << "Planes";
     if (level==3) {
-        if (station == 1 ) result << "Downstream";
-        if (station == 0 ) result << "Central";
-        if (station ==-1 ) result << "Upstream";
+        if (station == 3 ) result << "Downstream";
+        if (station == 2 ) result << "Central";
+        if (station == 1 ) result << "Upstream";
         result << 1+layer;
     }
   }
diff --git a/Tracker/TrackerConditions/FaserSCT_ConditionsData/data/SCT_Conditions.py b/Tracker/TrackerConditions/FaserSCT_ConditionsData/data/SCT_Conditions.py
index 8b4e1fa5..2855d661 100644
--- a/Tracker/TrackerConditions/FaserSCT_ConditionsData/data/SCT_Conditions.py
+++ b/Tracker/TrackerConditions/FaserSCT_ConditionsData/data/SCT_Conditions.py
@@ -1,13 +1,21 @@
 #!/bin/env python
 
-sctChannels = ['1073741824 ', '1075838976 ', '1077936128 ', '1080033280 ', '1082130432 ', '1084227584 ', '1086324736 ', '1088421888 ', '1090519040 ', '1092616192 ', '1094713344 ', '1096810496 ', '1098907648 ', '1101004800 ', '1103101952 ', '1105199104 ', '1107296256 ', '1109393408 ', '1111490560 ', '1113587712 ', '1115684864 ', '1117782016 ', '1119879168 ', '1121976320 ', '1124073472 ', '1126170624 ', '1128267776 ', '1130364928 ', '1132462080 ', '1134559232 ', '1136656384 ', '1138753536 ', '1140850688 ', '1142947840 ', '1145044992 ', '1147142144 ', '1149239296 ', '1151336448 ', '1153433600 ', '1155530752 ', '1157627904 ', '1159725056 ', '1161822208 ', '1163919360 ', '1166016512 ', '1168113664 ', '1170210816 ', '1172307968 ', '1207959552 ', '1210056704 ', '1212153856 ', '1214251008 ', '1216348160 ', '1218445312 ', '1220542464 ', '1222639616 ', '1224736768 ', '1226833920 ', '1228931072 ', '1231028224 ', '1233125376 ', '1235222528 ', '1237319680 ', '1239416832 ', '1241513984 ', '1243611136 ', '1245708288 ', '1247805440 ', '1249902592 ', '1251999744 ', '1254096896 ', '1256194048 ', '1258291200 ', '1260388352 ', '1262485504 ', '1264582656 ', '1266679808 ', '1268776960 ', '1270874112 ', '1272971264 ', '1275068416 ', '1277165568 ', '1279262720 ', '1281359872 ', '1283457024 ', '1285554176 ', '1287651328 ', '1289748480 ', '1291845632 ', '1293942784 ', '1296039936 ', '1298137088 ', '1300234240 ', '1302331392 ', '1304428544 ', '1306525696 ', '1342177280 ', '1344274432 ', '1346371584 ', '1348468736 ', '1350565888 ', '1352663040 ', '1354760192 ', '1356857344 ', '1358954496 ', '1361051648 ', '1363148800 ', '1365245952 ', '1367343104 ', '1369440256 ', '1371537408 ', '1373634560 ', '1375731712 ', '1377828864 ', '1379926016 ', '1382023168 ', '1384120320 ', '1386217472 ', '1388314624 ', '1390411776 ', '1392508928 ', '1394606080 ', '1396703232 ', '1398800384 ', '1400897536 ', '1402994688 ', '1405091840 ', '1407188992 ', '1409286144 ', '1411383296 ', '1413480448 ', '1415577600 ', '1417674752 ', '1419771904 ', '1421869056 ', '1423966208 ', '1426063360 ', '1428160512 ', '1430257664 ', '1432354816 ', '1434451968 ', '1436549120 ', '1438646272 ', '1440743424 ']
+
+sctChannels = [
+       '2147483648', '2149580800', '2151677952', '2153775104', '2155872256', '2157969408', '2160066560', '2162163712', '2164260864', '2166358016', '2168455168', '2170552320', '2172649472', '2174746624', '2176843776', '2178940928', '2181038080', '2183135232', '2185232384', '2187329536',
+       '2189426688', '2191523840', '2193620992', '2195718144', '2197815296', '2199912448', '2202009600', '2204106752', '2206203904', '2208301056', '2210398208', '2212495360', '2214592512', '2216689664', '2218786816', '2220883968', '2222981120', '2225078272', '2227175424', '2229272576',
+       '2231369728', '2233466880', '2235564032', '2237661184', '2239758336', '2241855488', '2243952640', '2246049792', '2281701376', '2283798528', '2285895680', '2287992832', '2290089984', '2292187136', '2294284288', '2296381440', '2298478592', '2300575744', '2302672896', '2304770048',
+       '2306867200', '2308964352', '2311061504', '2313158656', '2315255808', '2317352960', '2319450112', '2321547264', '2323644416', '2325741568', '2327838720', '2329935872', '2332033024', '2334130176', '2336227328', '2338324480', '2340421632', '2342518784', '2344615936', '2346713088',
+       '2348810240', '2350907392', '2353004544', '2355101696', '2357198848', '2359296000', '2361393152', '2363490304', '2365587456', '2367684608', '2369781760', '2371878912', '2373976064', '2376073216', '2378170368', '2380267520', '2415919104', '2418016256', '2420113408', '2422210560',
+       '2424307712', '2426404864', '2428502016', '2430599168', '2432696320', '2434793472', '2436890624', '2438987776', '2441084928', '2443182080', '2445279232', '2447376384', '2449473536', '2451570688', '2453667840', '2455764992', '2457862144', '2459959296', '2462056448', '2464153600',
+       '2466250752', '2468347904', '2470445056', '2472542208', '2474639360', '2476736512', '2478833664', '2480930816', '2483027968', '2485125120', '2487222272', '2489319424', '2491416576', '2493513728', '2495610880', '2497708032', '2499805184', '2501902336', '2503999488', '2506096640',
+       '2508193792', '2510290944', '2512388096', '2514485248']
+
 
 description = '<timeStamp>run-lumi</timeStamp><addrHeader><address_header clid="1238547719" service_type="71" /></addrHeader><typeName>CondAttrListCollection</typeName>'
 
 descriptionDCS = '<timeStamp>time</timeStamp><addrHeader><address_header service_type="71" clid="1238547719" /></addrHeader><typeName>CondAttrListCollection</typeName><cache>600</cache>'
 
-# descriptionMagnet = '<timeStamp>time</timeStamp><addrHeader><address_header service_type="71" clid="1238547719" /></addrHeader><typeName>CondAttrListCollection</typeName><cache>600</cache><named/>'
-
 from PyCool import cool, coral
 
 dbSvc = cool.DatabaseSvcFactory.databaseService()
@@ -68,23 +76,6 @@ noiseFolder = db.createFolder('/SCT/DAQ/Calibration/ChipNoise', noiseFolderSpec,
 for channel in sctChannels:
     noiseFolder.storeObject( cool.ValidityKeyMin, cool.ValidityKeyMax, noiseRecord, int(channel) )
 
-# magnetSpec = cool.RecordSpecification()
-# magnetSpec.extend( 'value' , cool.StorageType.Float )
-# magnetSpec.extend( 'quality_invalid' , cool.StorageType.Bool )
-
-# magnetRecord = cool.Record(magnetSpec)
-# magnetRecord[ 'quality_invalid'] = 1
-
-# magnetFolderSpec = cool.FolderSpecification(magnetSpec)
-# magnetFolder = db.createFolder('/EXT/DCS/MAGNETS/SENSORDATA', magnetFolderSpec, descriptionMagnet, True)
-
-# magnetRecord[ 'value' ] = 7730.0
-# magnetFolder.storeObject( cool.ValidityKeyMin, cool.ValidityKeyMax, magnetRecord, 1)
-# magnetFolder.storeObject( cool.ValidityKeyMin, cool.ValidityKeyMax, magnetRecord, 2)
-# magnetRecord[ 'value' ] = 20400.0
-# magnetFolder.storeObject( cool.ValidityKeyMin, cool.ValidityKeyMax, magnetRecord, 3)
-# magnetFolder.storeObject( cool.ValidityKeyMin, cool.ValidityKeyMax, magnetRecord, 4)
-
 chanstatSpec = cool.RecordSpecification()
 chanstatSpec.extend( 'LVCHSTAT_RECV' , cool.StorageType.Int32 )
 chanstatSpec.extend( 'STATE'         , cool.StorageType.UInt32 )
diff --git a/Tracker/TrackerDetDescr/FaserSCT_GeoModel/src/SCT_DetectorFactory.cxx b/Tracker/TrackerDetDescr/FaserSCT_GeoModel/src/SCT_DetectorFactory.cxx
index b43e4b32..18f7c7c1 100644
--- a/Tracker/TrackerDetDescr/FaserSCT_GeoModel/src/SCT_DetectorFactory.cxx
+++ b/Tracker/TrackerDetDescr/FaserSCT_GeoModel/src/SCT_DetectorFactory.cxx
@@ -143,17 +143,17 @@ void SCT_DetectorFactory::create(GeoPhysVol *world)
   GeoTrf::Transform3D sctTransform = sctGeneral->partTransform("SCT");
   SCT_Barrel station("Station", m_detectorManager, m_geometryManager, m_materials);
 
-  std::vector<std::string> partNames {"StationA", "StationB", "StationC"};
-  for (int iStation = -1; iStation <= 1; iStation++)
+  std::vector<std::string> partNames {"Interface", "StationA", "StationB", "StationC"};
+  for (size_t iStation = 0; iStation < partNames.size(); iStation++)
   {
-    if (sctGeneral->partPresent(partNames[iStation+1]))
+    if (sctGeneral->partPresent(partNames[iStation]))
     {
       m_detectorManager->numerology().addBarrel(iStation);
       SCT_Identifier id{m_geometryManager->athenaComps()->getIdHelper()};
       id.setStation(iStation);
       tracker->add(new GeoNameTag("SCT"));
       tracker->add(new GeoIdentifierTag(iStation));
-      GeoAlignableTransform* stationTransform = new GeoAlignableTransform(sctTransform * sctGeneral->partTransform(partNames[iStation+1]));
+      GeoAlignableTransform* stationTransform = new GeoAlignableTransform(sctTransform * sctGeneral->partTransform(partNames[iStation]));
       tracker->add(stationTransform);
       GeoVPhysVol* stationPhys = station.build(id);
       tracker->add(stationPhys);
diff --git a/Tracker/TrackerDetDescr/TrackerIdDictFiles/data/IdDictTracker.xml b/Tracker/TrackerDetDescr/TrackerIdDictFiles/data/IdDictTracker.xml
index 06d99034..7f2bfd96 100644
--- a/Tracker/TrackerDetDescr/TrackerIdDictFiles/data/IdDictTracker.xml
+++ b/Tracker/TrackerDetDescr/TrackerIdDictFiles/data/IdDictTracker.xml
@@ -1,13 +1,15 @@
-<IdDictionary name="Tracker">
+<IdDictionary name="Tracker" version="Faser">
 
   <field name="part">
     <label name="SCT"        value="1" />
   </field>
 
+<!-- No interface detector in this version -->
+
   <field name="station" >
-    <label name="Upstream"   value="-1" />
-    <label name="Central"    value="0" />
-    <label name="Downstream" value="1" />
+    <label name="Upstream"   value="1" />
+    <label name="Central"    value="2" />
+    <label name="Downstream" value="3" />
   </field>
 
   <field name="layer" >
diff --git a/Tracker/TrackerDetDescr/TrackerIdDictFiles/data/IdDictTracker_Interface.xml b/Tracker/TrackerDetDescr/TrackerIdDictFiles/data/IdDictTracker_Interface.xml
new file mode 100644
index 00000000..278049eb
--- /dev/null
+++ b/Tracker/TrackerDetDescr/TrackerIdDictFiles/data/IdDictTracker_Interface.xml
@@ -0,0 +1,53 @@
+<IdDictionary name="Tracker" version="FaserNu">
+
+  <field name="part">
+    <label name="SCT"        value="1" />
+  </field>
+
+<!-- This file includes the Interface detector -->
+  <field name="station" >
+    <label name="Interface"  value="0" />
+    <label name="Upstream"   value="1" />
+    <label name="Central"    value="2" />
+    <label name="Downstream" value="3" />
+  </field>
+
+  <field name="layer" >
+    <label name="Upstream"   value="0" />
+    <label name="Central"    value="1" />
+    <label name="Downstream" value="2" />
+  </field>
+
+  <field name="phi_module">
+    <label name="Bottom"       value="0" /> 
+    <label name="LowerMiddle"  value="1" />
+    <label name="UpperMiddle"  value="2" />
+    <label name="Top"          value="3" />
+  </field>
+
+  <field name="eta_module">
+  <!-- facing downstream (hence "starboard" and "port")
+       x must increase right to left for a right-handed
+       coordinate system -->
+  <!-- numbers straddle zero for consistency with ATLAS -->       
+    <label name="Starboard"   value="-1" />
+    <label name="Port"        value="+1" />
+  </field>
+
+  <field name="side">
+  <!-- The "upper" side is the side with the pigtail -->
+    <label name="Upper"    value="0" />
+    <label name="Lower"    value="1" />
+  </field>
+
+  <region>
+    <range field="part"       value="SCT" />
+    <range field="station"    values="Interface Upstream Central Downstream" />
+    <range field="layer"      values="Upstream Central Downstream" />
+    <range field="phi_module" values="Bottom LowerMiddle UpperMiddle Top" wraparound="FALSE" />
+    <range field="eta_module" values="Starboard Port" wraparound="FALSE" />
+    <range field="side"       values="Upper Lower" />
+    <range field="strip"      minvalue="0" maxvalue="767" />
+  </region>
+
+</IdDictionary>
\ No newline at end of file
diff --git a/Tracker/TrackerDetDescr/TrackerReadoutGeometry/TrackerReadoutGeometry/SiNumerology.h b/Tracker/TrackerDetDescr/TrackerReadoutGeometry/TrackerReadoutGeometry/SiNumerology.h
index 90ee8ca9..f4aa9462 100755
--- a/Tracker/TrackerDetDescr/TrackerReadoutGeometry/TrackerReadoutGeometry/SiNumerology.h
+++ b/Tracker/TrackerDetDescr/TrackerReadoutGeometry/TrackerReadoutGeometry/SiNumerology.h
@@ -34,12 +34,12 @@ namespace TrackerDD {
       
       // Accessors:
       
-      /** Number of barrels. Normally 3. */
+      /** Number of barrels. Normally 4 if interface detector present, or 3 otherwise. */
       int numBarrels() const; 
 
       int numStations() const;
            
-      // /** Barrel/endcap identifier for each barrel. Normally barrelId(0) = -1 */
+      // /** Barrel/endcap identifier for each barrel. Normally barrelId(0) = 0 if interface detector present or 1 otherwise  */
       int barrelId(int index) const;
 
       int stationId(int index) const;
diff --git a/Tracker/TrackerG4/FaserSCT_G4_SD/CMakeLists.txt b/Tracker/TrackerG4/FaserSCT_G4_SD/CMakeLists.txt
index 25db44ba..c9334be6 100644
--- a/Tracker/TrackerG4/FaserSCT_G4_SD/CMakeLists.txt
+++ b/Tracker/TrackerG4/FaserSCT_G4_SD/CMakeLists.txt
@@ -11,7 +11,7 @@ atlas_depends_on_subdirs( PRIVATE
                           GaudiKernel
                           Tracker/TrackerSimEvent
                           Simulation/G4Atlas/G4AtlasTools
-                          Simulation/G4Sim/MCTruth
+                          Simulation/G4Sim/FaserMCTruth
                            )
 
 # External dependencies:
@@ -24,7 +24,7 @@ atlas_add_component( FaserSCT_G4_SD
                      src/*.cxx
                      src/components/*.cxx
                      INCLUDE_DIRS ${GEANT4_INCLUDE_DIRS} ${XERCESC_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS}
-                     LINK_LIBRARIES ${GEANT4_LIBRARIES} ${XERCESC_LIBRARIES} ${CLHEP_LIBRARIES} StoreGateLib SGtests GaudiKernel TrackerSimEvent G4AtlasToolsLib MCTruth )
+                     LINK_LIBRARIES ${GEANT4_LIBRARIES} ${XERCESC_LIBRARIES} ${CLHEP_LIBRARIES} StoreGateLib SGtests GaudiKernel TrackerSimEvent G4AtlasToolsLib FaserMCTruth )
 
 atlas_add_test( FaserSCT_G4_SDToolConfig_test
                 SCRIPT test/FaserSCT_G4_SDToolConfig_test.py
diff --git a/Tracker/TrackerG4/FaserSCT_G4_SD/python/FaserSCT_G4_SDToolConfig.py b/Tracker/TrackerG4/FaserSCT_G4_SD/python/FaserSCT_G4_SDToolConfig.py
index 7e93bcde..46002551 100644
--- a/Tracker/TrackerG4/FaserSCT_G4_SD/python/FaserSCT_G4_SDToolConfig.py
+++ b/Tracker/TrackerG4/FaserSCT_G4_SD/python/FaserSCT_G4_SDToolConfig.py
@@ -3,7 +3,6 @@
 from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator
 from ISF_Algorithms.collection_merger_helpersNew import CollectionMergerCfg
 
-# from VetoG4_SD.VetoG4_SDConf import VetoSensorSDTool
 from FaserSCT_G4_SD.FaserSCT_G4_SDConfig import getSctSensorSD
 
 def SctSensorSDCfg(ConfigFlags, name="SctSensorSD", **kwargs):
diff --git a/Tracker/TrackerG4/FaserSCT_G4_SD/src/FaserSctSensorSD.cxx b/Tracker/TrackerG4/FaserSCT_G4_SD/src/FaserSctSensorSD.cxx
index 94f93a21..193a8c48 100644
--- a/Tracker/TrackerG4/FaserSCT_G4_SD/src/FaserSctSensorSD.cxx
+++ b/Tracker/TrackerG4/FaserSCT_G4_SD/src/FaserSctSensorSD.cxx
@@ -12,7 +12,7 @@
 #include "FaserSctSensorSD.h"
 
 // athena includes
-#include "MCTruth/TrackHelper.h"
+#include "FaserMCTruth/FaserTrackHelper.h"
 
 // Geant4 includes
 #include "G4Step.hh"
@@ -55,7 +55,13 @@ G4bool FaserSctSensorSD::ProcessHits(G4Step* aStep, G4TouchableHistory* /*ROhist
   //
   // Get the Touchable History:
   //
-  const G4TouchableHistory *myTouch = dynamic_cast<const G4TouchableHistory*>(aStep->GetPreStepPoint()->GetTouchable());
+  const G4TouchableHistory* myTouch = dynamic_cast<const G4TouchableHistory*>(aStep->GetPreStepPoint()->GetTouchable());
+  // for (G4int level = 0; level <= myTouch->GetHistoryDepth(); level++)
+  // {
+  //   G4cout << "Tracker hit at level " << level << 
+  //     " in physical volume named " << myTouch->GetVolume(level)->GetName() << 
+  //     " with logical volume name " << myTouch->GetVolume(level)->GetLogicalVolume()->GetName() << G4endl;
+  // }
   //
   // Get the hit coordinates. Start and End Point
   //
@@ -97,7 +103,7 @@ G4bool FaserSctSensorSD::ProcessHits(G4Step* aStep, G4TouchableHistory* /*ROhist
   int sensor = 0;
   this->indexMethod(myTouch, station, plane, row, module, sensor);
   // get the HepMcParticleLink from the TrackHelper
-  TrackHelper trHelp(aStep->GetTrack());
+  FaserTrackHelper trHelp(aStep->GetTrack());
   m_HitColl->Emplace(lP1,
                      lP2,
                      edep,
diff --git a/Tracker/TrackerG4/FaserSCT_G4_SD/src/FaserSctSensorSDTool.cxx b/Tracker/TrackerG4/FaserSCT_G4_SD/src/FaserSctSensorSDTool.cxx
index 322784b6..a58ddf3e 100644
--- a/Tracker/TrackerG4/FaserSCT_G4_SD/src/FaserSctSensorSDTool.cxx
+++ b/Tracker/TrackerG4/FaserSCT_G4_SD/src/FaserSctSensorSDTool.cxx
@@ -2,7 +2,7 @@
   Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
 */
 
-// Veto Sensitive Detector Tool.
+// SCT Sensitive Detector Tool.
 //
 
 // class header
diff --git a/Tracker/TrackerSimEvent/src/FaserSiHitIdHelper.cxx b/Tracker/TrackerSimEvent/src/FaserSiHitIdHelper.cxx
index 6d3882dc..b0e4b84a 100644
--- a/Tracker/TrackerSimEvent/src/FaserSiHitIdHelper.cxx
+++ b/Tracker/TrackerSimEvent/src/FaserSiHitIdHelper.cxx
@@ -49,7 +49,7 @@ void FaserSiHitIdHelper::Initialize() {
     if (detStore->retrieve(pix, "FaserSCT_ID").isFailure()) { pix = 0; }
   }
 
-  InitializeField("Station", -1, 1);
+  InitializeField("Station", 1, 3);
   InitializeField("Plane", 0, 3);
   InitializeField("Row", 0, 4);
   InitializeField("Module", -1, 1);
diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackCollHandle_TruthTracks.cxx b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackCollHandle_TruthTracks.cxx
index 6fc90eb2..47ceeb84 100644
--- a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackCollHandle_TruthTracks.cxx
+++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackCollHandle_TruthTracks.cxx
@@ -479,18 +479,18 @@ bool TrackCollHandle_TruthTracks::load()
 //____________________________________________________________________
 bool TrackCollHandle_TruthTracks::cut(TrackHandleBase* handle)
 {
-  if (!TrackCollHandleBase::cut(handle))
-    return false;
+  // if (!TrackCollHandleBase::cut(handle))
+  //   return false;
 
-  if (m_d->cut_excludeNeutrals && handle->hasCharge() && handle->charge()==0.0)
-    return false;
+  // if (m_d->cut_excludeNeutrals && handle->hasCharge() && handle->charge()==0.0)
+  //   return false;
 
-  TrackHandle_TruthTrack * truthhandle = static_cast<TrackHandle_TruthTrack *>(handle);
-  if (m_d->cut_excludeBarcodeZero && truthhandle->hasBarCodeZero())
-    return false;
+  // TrackHandle_TruthTrack * truthhandle = static_cast<TrackHandle_TruthTrack *>(handle);
+  // if (m_d->cut_excludeBarcodeZero && truthhandle->hasBarCodeZero())
+  //   return false;
 
-  if (m_d->cut_fromIROnly && ! truthhandle->hasVertexAtIR(2.8*CLHEP::cm*2.8*CLHEP::cm,50*CLHEP::cm))
-    return false;
+  // if (m_d->cut_fromIROnly && ! truthhandle->hasVertexAtIR(2.8*CLHEP::cm*2.8*CLHEP::cm,50*CLHEP::cm))
+  //   return false;
 
   return true;
 }
diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackSystemController.cxx b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackSystemController.cxx
index 52301b7d..8483f4a0 100644
--- a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackSystemController.cxx
+++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/TrackSystemController.cxx
@@ -477,9 +477,10 @@ TrackSystemController::TrackSystemController(IVP1System * sys)
   
   // Since TrkVolumesSvc isn't working anymore, hardcode values. (Remove when we move to new extrapolator)
 
-  double hardCodedMaxZ {3500.0};
-  double hardCodedMinZ {-2500.0};
-    m_d->calorimeterEntryLayer       = new Trk::Volume(new Amg::Transform3D(Amg::Translation3D(0.0, 0.0, (hardCodedMaxZ + hardCodedMinZ)/2)), new Trk::CuboidVolumeBounds(300.0, 300.0, (hardCodedMaxZ - hardCodedMinZ)/2));
+  // double hardCodedMaxZ {3500.0};
+  // double hardCodedMinZ {-2500.0};
+  //  m_d->calorimeterEntryLayer       = new Trk::Volume(new Amg::Transform3D(Amg::Translation3D(0.0, 0.0, (hardCodedMaxZ + hardCodedMinZ)/2)), new Trk::CuboidVolumeBounds(300.0, 300.0, (hardCodedMaxZ - hardCodedMinZ)/2));
+  m_d->calorimeterEntryLayer = new Trk::Volume(0, new Trk::CylinderVolumeBounds(500.0, 3500.0));
   // m_d->calorimeterEntryLayer      = new Trk::Volume(0, new Trk::CylinderVolumeBounds(1100.0, 3200.0));
   // m_d->muonSpectrometerEntryLayer = new Trk::Volume(0, new Trk::CylinderVolumeBounds(4250.0, 6779.0));
   // m_d->muonSpectrometerExitLayer  = new Trk::Volume(0, new Trk::CylinderVolumeBounds(15000.0, 21000.0)); // FIXME! Put in correct values. EJWM
@@ -1617,9 +1618,9 @@ Trk::ITrackFitter * TrackSystemController::trackFitter() const
 
 const Trk::Volume * TrackSystemController::extrapolateToThisVolume() const
 {
-  if (m_d->ui_extrap.comboBox_extendAllTracksToHere->currentText()=="Calorimeter")
+  // if (m_d->ui_extrap.comboBox_extendAllTracksToHere->currentText()=="Calorimeter")
     return m_d->calorimeterEntryLayer;
-  return 0;
+  // return 0;
 }
 
 //____________________________________________________________________
diff --git a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/vp1trackcontrollerform.ui b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/vp1trackcontrollerform.ui
index 4a729ebe..c6aea2cd 100644
--- a/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/vp1trackcontrollerform.ui
+++ b/graphics/VTI12/VTI12Systems/VTI12TrackSystems/src/vp1trackcontrollerform.ui
@@ -32,15 +32,20 @@
         </property>
         <item row="0" column="0" >
          <widget class="QPushButton" name="pushButton_settings_cuts" >
+          <property name="enabled">
+            <bool>false</bool>
+          </property>
           <property name="toolTip" >
-           <string>Configure track cuts on quantities such as eta, phi and momentum</string>
+           <string>(DISABLED) Configure track cuts on quantities such as eta, phi and momentum</string>
           </property>
           <property name="text" >
-           <string>Cuts</string>
+           <string>Cuts disabled</string>
           </property>
+          <!--
           <property name="checkable" >
            <bool>true</bool>
           </property>
+          -->
          </widget>
         </item>
         <item row="0" column="1" >
diff --git a/version.txt b/version.txt
new file mode 100644
index 00000000..f7fbce29
--- /dev/null
+++ b/version.txt
@@ -0,0 +1 @@
+22.0.10
-- 
GitLab