From 1184571e2727e844c14d91001b7d3425bba21d48 Mon Sep 17 00:00:00 2001
From: Markus Frank <Markus.Frank@cern.ch>
Date: Mon, 18 Jul 2022 17:44:13 +0200
Subject: [PATCH] Implement fast simulation shower modelling. Simplify GFlash
 to use the same sensitive actions as fast simulation

---
 DDG4/include/DDG4/DDG4Dict.h                  |   4 +-
 DDG4/include/DDG4/Geant4Data.h                |  10 +-
 DDG4/include/DDG4/Geant4FastSimHandler.h      | 118 +++++++++
 DDG4/include/DDG4/Geant4FastSimShowerModel.h  | 171 +++++++++++++
 .../DDG4/Geant4FastSimShowerModel.inl.h       |  88 +++++++
 DDG4/include/DDG4/Geant4FastSimSpot.h         | 132 ++++++++++
 ...GFlashSpotHandler.h => Geant4HitHandler.h} |  99 ++------
 DDG4/include/DDG4/Geant4ReadoutVolumeFilter.h |   6 +-
 DDG4/include/DDG4/Geant4SensDetAction.h       |  86 ++++---
 DDG4/include/DDG4/Geant4SensDetAction.inl     |  39 ++-
 DDG4/include/DDG4/Geant4StepHandler.h         |  86 ++-----
 DDG4/include/DDG4/Geant4TestActions.h         |  12 +-
 DDG4/include/DDG4/Geant4UIManager.h           |   4 +-
 DDG4/plugins/Geant4EscapeCounter.cpp          |   6 +-
 DDG4/plugins/Geant4FastSimShowerModel.cpp     |  22 ++
 DDG4/plugins/Geant4GFlashShowerModel.cpp      |  10 +-
 DDG4/plugins/Geant4P1ShowerModel.cpp          | 210 ++++++++++++++++
 DDG4/plugins/Geant4SDActions.cpp              | 135 +++++-----
 DDG4/plugins/Geant4SensDet.cpp                |  44 +++-
 DDG4/plugins/Geant4SensDetFilters.cpp         |  22 +-
 DDG4/plugins/Geant4TrackerWeightedSD.cpp      |  12 +-
 DDG4/src/Geant4Data.cpp                       |  53 ++--
 DDG4/src/Geant4FastSimShowerModel.cpp         | 230 ++++++++++++++++++
 ...shSpotHandler.cpp => Geant4HitHandler.cpp} |  35 ++-
 DDG4/src/Geant4ReadoutVolumeFilter.cpp        |   8 +-
 DDG4/src/Geant4SensDetAction.cpp              |  50 ++--
 DDG4/src/Geant4StepHandler.cpp                |  51 ----
 DDG4/src/Geant4TestActions.cpp                |   2 +-
 DDG4/src/Geant4UIManager.cpp                  |   9 +
 examples/ClientTests/CMakeLists.txt           |   9 +
 examples/ClientTests/scripts/SiliconBlock.py  |  19 +-
 .../scripts/SiliconBlockFastSim.py            | 134 ++++++++++
 .../ClientTests/scripts/SiliconBlockGFlash.py |  21 +-
 examples/DDG4/scripts/TestProperties.py       |   6 +-
 examples/DDG4_MySensDet/CMakeLists.txt        |   1 +
 .../DDG4_MySensDet/scripts/MyTrackerSD_sim.py |  23 +-
 .../DDG4_MySensDet/src/MyTrackerSDAction.cpp  |   2 +-
 37 files changed, 1522 insertions(+), 447 deletions(-)
 create mode 100644 DDG4/include/DDG4/Geant4FastSimHandler.h
 create mode 100644 DDG4/include/DDG4/Geant4FastSimShowerModel.h
 create mode 100644 DDG4/include/DDG4/Geant4FastSimShowerModel.inl.h
 create mode 100644 DDG4/include/DDG4/Geant4FastSimSpot.h
 rename DDG4/include/DDG4/{Geant4GFlashSpotHandler.h => Geant4HitHandler.h} (58%)
 create mode 100644 DDG4/plugins/Geant4FastSimShowerModel.cpp
 create mode 100644 DDG4/plugins/Geant4P1ShowerModel.cpp
 create mode 100644 DDG4/src/Geant4FastSimShowerModel.cpp
 rename DDG4/src/{Geant4GFlashSpotHandler.cpp => Geant4HitHandler.cpp} (59%)
 create mode 100644 examples/ClientTests/scripts/SiliconBlockFastSim.py

diff --git a/DDG4/include/DDG4/DDG4Dict.h b/DDG4/include/DDG4/DDG4Dict.h
index 073f1239a..124bc0705 100644
--- a/DDG4/include/DDG4/DDG4Dict.h
+++ b/DDG4/include/DDG4/DDG4Dict.h
@@ -139,6 +139,8 @@ namespace dd4hep {
     inline  Geant4HitData::~Geant4HitData()  {    }
     /// Extract the MC contribution for a given hit from the step information
     inline Geant4HitData::Contribution Geant4HitData::extractContribution(const G4Step*) { return Contribution(); }
+    /// Extract the MC contribution for a given hit from the spot information
+    inline Geant4HitData::Contribution Geant4HitData::extractContribution(const Geant4FastSimSpot*) { return Contribution(); }
     /// Default constructor
     inline Geant4Tracker::Hit::Hit() : length(0), energyDeposit(0e0)  {    }
     /// Initializing constructor
@@ -152,7 +154,7 @@ namespace dd4hep {
     /// Store Geant4 point and step information into tracker hit structure.
     inline Geant4Tracker::Hit& Geant4Tracker::Hit::storePoint(const G4Step*, const G4StepPoint*)  { return *this;}
     /// Store Geant4 spot information into tracker hit structure.
-    inline Geant4Tracker::Hit& Geant4Tracker::Hit::storePoint(const G4GFlashSpot*)  { return *this;}    
+    inline Geant4Tracker::Hit& Geant4Tracker::Hit::storePoint(const Geant4FastSimSpot*)  { return *this;}    
     /// Default constructor
     inline Geant4Calorimeter::Hit::Hit() : energyDeposit(0e0)  {    }
     /// Initializing constructor
diff --git a/DDG4/include/DDG4/Geant4Data.h b/DDG4/include/DDG4/Geant4Data.h
index 5a5e6a5e0..f2d53e14c 100644
--- a/DDG4/include/DDG4/Geant4Data.h
+++ b/DDG4/include/DDG4/Geant4Data.h
@@ -25,7 +25,6 @@
 // Forward declarations
 class G4Step;
 class G4StepPoint;
-class G4GFlashSpot;
 
 /// Namespace for the AIDA detector description toolkit
 namespace dd4hep {
@@ -37,6 +36,9 @@ namespace dd4hep {
   /// Namespace for the Geant4 based simulation part of the AIDA detector description toolkit
   namespace sim {
 
+    // Forward declarations
+    class Geant4FastSimSpot;
+
     /// Simple run description structure. Used in the default I/O mechanism.
     /**
      * Example class to store the run related information.
@@ -209,8 +211,8 @@ namespace dd4hep {
       static Contribution extractContribution(const G4Step* step);
       /// Extract the MC contribution for a given hit from the step information with BirksLaw option
       static Contribution extractContribution(const G4Step* step, bool ApplyBirksLaw);
-      /// Extract the MC contribution for a given hit from the GFlash spot information
-      static Contribution extractContribution(const G4GFlashSpot* spot);
+      /// Extract the MC contribution for a given hit from the GFlash/FastSim spot information
+      static Contribution extractContribution(const Geant4FastSimSpot* spot);
     };
 
     /// Helper class to define structures used by the generic DDG4 tracker sensitive detector
@@ -264,7 +266,7 @@ namespace dd4hep {
         /// Store Geant4 point and step information into tracker hit structure.
         Hit& storePoint(const G4Step* step, const G4StepPoint* point);
 	/// Store Geant4 spot information into tracker hit structure.
-	Hit& storePoint(const G4GFlashSpot* spot);
+	Hit& storePoint(const Geant4FastSimSpot* spot);
       };
     };
 
diff --git a/DDG4/include/DDG4/Geant4FastSimHandler.h b/DDG4/include/DDG4/Geant4FastSimHandler.h
new file mode 100644
index 000000000..dc63d7ff9
--- /dev/null
+++ b/DDG4/include/DDG4/Geant4FastSimHandler.h
@@ -0,0 +1,118 @@
+//==========================================================================
+//  AIDA Detector description implementation 
+//--------------------------------------------------------------------------
+// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
+// All rights reserved.
+//
+// For the licensing terms see $DD4hepINSTALL/LICENSE.
+// For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
+//
+// Author     : M.Frank
+//
+//==========================================================================
+#ifndef DDG4_GEANT4FASTSIMHANDLER_H
+#define DDG4_GEANT4FASTSIMHANDLER_H
+
+// Framework include files
+#include <DDG4/Geant4HitHandler.h>
+#include <DDG4/Geant4FastSimSpot.h>
+
+// Geant4 include files
+#include <G4VTouchable.hh>
+#include <G4VSensitiveDetector.hh>
+
+/// Namespace for the AIDA detector description toolkit
+namespace dd4hep {
+
+  /// Namespace for the Geant4 based simulation part of the AIDA detector description toolkit
+  namespace sim {
+
+    // Forward declarations;
+    class Geant4FastSimHandler;
+
+    /// Helper class to ease the extraction of information from a G4FastSimSpot object.
+    /**
+     *
+     * Helper/utility class to easily access Geant4 gflashspot/fast simulation information.
+     * Born by lazyness: Avoid typing millions of statements!
+     *
+     *  \author  M.Frank
+     *  \version 1.0
+     *  \ingroup DD4HEP_SIMULATION
+     */
+    class Geant4FastSimHandler  : public Geant4HitHandler  {
+    public:
+      const Geant4FastSimSpot* spot;
+
+      /// Inhibit default constructor
+      Geant4FastSimHandler() = delete;
+      /// Initializing constructor
+      Geant4FastSimHandler(const Geant4FastSimSpot* sp)
+	: Geant4HitHandler(sp->primary, sp->touchable), spot(sp) 
+	{
+	}
+      /// No copy constructor
+      Geant4FastSimHandler(const Geant4FastSimHandler& copy) = delete;
+      /// No move constructor
+      Geant4FastSimHandler(Geant4FastSimHandler&& copy) = delete;
+      /// Assignment operator inhibited. Should not be copied
+      Geant4FastSimHandler& operator=(const Geant4FastSimHandler& copy) = delete;
+      /// Move operator inhibited. Should not be copied
+      Geant4FastSimHandler& operator=(Geant4FastSimHandler&& copy) = delete;
+      /// Returns total energy deposit
+      double energy() const  {
+	return spot->hit->GetEnergy();
+      }
+      /// Return track momentum in DD4hep notation
+      Momentum momentum() const {
+        const G4ThreeVector& p = track->GetMomentum();
+        return Momentum(p.x(), p.y(), p.z());
+      }
+      /// Returns the pre-gflashspot position
+      Position avgPosition() const {
+        const G4ThreeVector p = spot->hit->GetPosition();
+        return Position(p.x(), p.y(), p.z());
+      }
+      /// Returns the post-step position as a G4ThreeVector
+      G4ThreeVector avgPositionG4() const {
+        return spot->hit->GetPosition();
+      }
+      /// Direction calculated from the post- and pre-position ofthe gflashspot
+      Position direction()  const  {
+        const G4ThreeVector p = track->GetMomentumDirection();
+        return Position(p.x(), p.y(), p.z());
+      }
+      /// Returns the track momentum as a G4ThreeVector
+      G4ThreeVector momentumG4() const {
+	return track->GetMomentum();
+      }
+      /// Access the enery deposit of the energy spot
+      double deposit() const  {
+        return spot->hit->GetEnergy();
+      }
+      G4VPhysicalVolume* volume() const {
+	return touchable()->GetVolume();
+      }
+      G4LogicalVolume* logvol() const {
+        return volume()->GetLogicalVolume();
+      }
+      G4VSolid* solid() const {
+        return touchable()->GetSolid();
+      }
+      G4VSensitiveDetector* sd()  const {
+        G4LogicalVolume* lv = logvol();
+        return lv ? lv->GetSensitiveDetector() : 0;
+      }
+      const char* sdName(const char* undefined = "") const {
+        G4VSensitiveDetector* s = sd();
+        return s ? s->GetName().c_str() : undefined;
+      }
+      bool isSensitive() const {
+	G4LogicalVolume* lv = logvol();
+        return lv ? (0 != lv->GetSensitiveDetector()) : false;
+      }
+    };
+
+  }    // End namespace sim
+}      // End namespace dd4hep
+#endif // DDG4_GEANT4FASTSIMSPOTHANDLER_H
diff --git a/DDG4/include/DDG4/Geant4FastSimShowerModel.h b/DDG4/include/DDG4/Geant4FastSimShowerModel.h
new file mode 100644
index 000000000..2089b4fad
--- /dev/null
+++ b/DDG4/include/DDG4/Geant4FastSimShowerModel.h
@@ -0,0 +1,171 @@
+//==========================================================================
+//  AIDA Detector description implementation
+//--------------------------------------------------------------------------
+// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
+// All rights reserved.
+//
+// For the licensing terms see $DD4hepINSTALL/LICENSE.
+// For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
+//
+// Author     : M.Frank
+//
+//==========================================================================
+#ifndef DDG4_GEANT4FASTSIMSHOWERMODEL_H
+#define DDG4_GEANT4FASTSIMSHOWERMODEL_H
+
+// Framework include files
+#include <DDG4/Geant4DetectorConstruction.h>
+
+// Geant4 include files
+#include <G4FastSimulationPhysics.hh>
+
+// C/C++ include files
+#include <set>
+#include <vector>
+#include <memory>
+
+/// Forward declarations
+class G4FastStep;
+class G4FastTrack;
+class G4ParticleDefinition;
+class G4VFastSimulationModel;
+
+/// Namespace for the AIDA detector description toolkit
+namespace dd4hep  {
+
+  /// Namespace for the Geant4 based simulation part of the AIDA detector description toolkit
+  namespace sim  {
+
+    /// Forard declarations
+    class Geant4ShowerModelWrapper;
+    
+    /// Geant4 wrapper for the Geant4 fast simulation shower model
+    /**
+     *  Geant4 wrapper for the Geant4 fast simulation shower model
+     *
+     *  \author  M.Frank
+     *  \version 1.0
+     *  \ingroup DD4HEP_SIMULATION
+     */
+    class Geant4FastSimShowerModel : public Geant4DetectorConstruction    {
+    protected:
+      // typedef std::vector<std::pair<std::string, double> > ParticleConfig;
+      typedef std::map<const G4ParticleDefinition*, double> ParticleCut;
+      typedef std::map<std::string, std::string> ParticleConfig;
+      typedef std::unique_ptr<Geant4ShowerModelWrapper> Wrapper;
+  
+      /// Property: Region name to which this parametrization should be applied
+      std::string    m_regionName     { "Region-name-not-specified"};
+      /// Property: Particle names for which this parametrization is applicable
+      std::vector<std::string> m_applicablePartNames  { };
+      /// Property: Parametrisation control: Enable/disable fast simulation
+      bool           m_enable         { false };
+      /// Property: Defines step lenght
+      double         m_stepX0         { 0.1 };
+      /// Property: Set minimum kinetic energy to trigger parametrisation
+      ParticleConfig m_eMin           { };
+      /// Property: Set maximum kinetic energy to trigger parametrisation
+      ParticleConfig m_eMax           { };
+      /// Property: Set maximum kinetic energy for particles to be killed
+      ParticleConfig m_eKill          { };
+      /// Property: Set minmal kinetic energy for particles to trigger the model
+      ParticleConfig m_eTriggerNames  { };
+
+      /// Particle definitions for which this parametrization is applicable
+      std::set<const G4ParticleDefinition*> m_applicableParticles  { };
+      /// Particle cut to trigger model simulation indexed by G4ParticleDefinition
+      ParticleCut    m_eTriggerCut    { };
+      /// Reference to the G4 fast simulation model
+      G4VFastSimulationModel* m_model { nullptr };
+      /// Reference to the shower model
+      Wrapper        m_wrapper        { };
+
+    protected:
+      /// Define standard assignments and constructors
+      DDG4_DEFINE_ACTION_CONSTRUCTORS(Geant4FastSimShowerModel);
+
+      /// Get parametrization material
+      G4Material* getMaterial(const std::string& name)   const;
+      /// Access particle definition from string
+      G4ParticleDefinition* getParticleDefinition(const std::string& name)   const;
+      /// Access the region from the detector description by name
+      G4Region* getRegion(const std::string& nam)   const;
+      /// Add shower model to region's fast simulation manager
+      void addShowerModel(G4Region* region);
+      /// Kill primary particle when creating the shower
+      void killParticle(G4FastStep& step, double deposit, double step_length = 0e0);
+
+    public:
+      /// Standard constructor
+      Geant4FastSimShowerModel(Geant4Context* context, const std::string& nam);
+
+      /// Default destructor
+      virtual ~Geant4FastSimShowerModel();
+
+      /// Geometry construction callback. Called at "Construct()"
+      virtual void constructGeo(Geant4DetectorConstructionContext* ctxt);
+      /// Electromagnetic field construction callback. Called at "ConstructSDandField()"
+      virtual void constructField(Geant4DetectorConstructionContext* ctxt);
+      /// Sensitive detector construction callback. Called at "ConstructSDandField()"
+      virtual void constructSensitives(Geant4DetectorConstructionContext* ctxt);
+
+      /// User callback to determine if the model is applicable for the particle type
+      virtual bool check_applicability(const G4ParticleDefinition& particle);
+      /// User callback to determine if the shower creation should be triggered
+      virtual bool check_trigger(const G4FastTrack& track);
+      /// User callback to model the particle/energy shower
+      virtual void modelShower(const G4FastTrack& track, G4FastStep& step);
+    };
+
+
+    /// Geant4 wrapper for the Geant4 fast simulation shower model
+    /**
+     *  Geant4 wrapper for the Geant4 fast simulation shower model
+     *
+     *  \author  M.Frank
+     *  \version 1.0
+     *  \ingroup DD4HEP_SIMULATION
+     */
+    template <typename CONCRETE_MODEL>
+    class Geant4FSShowerModel : public Geant4FastSimShowerModel    {
+
+    public:
+      /// Local parameter buffer to specialize caches, properties etc.
+      CONCRETE_MODEL locals;
+
+    public:
+      /// Standard constructor
+      Geant4FSShowerModel(Geant4Context* context, const std::string& nam);
+
+      /// Default destructor
+      virtual ~Geant4FSShowerModel();
+
+      /// Declare optional properties from embedded structure
+      void initialize();
+
+      /// Geometry construction callback. Called at "Construct()"
+      virtual void constructGeo(Geant4DetectorConstructionContext* ctxt)  override;
+
+      /// Electromagnetic field construction callback. Called at "ConstructSDandField()"
+      virtual void constructField(Geant4DetectorConstructionContext* ctxt)  override;
+
+      /// Sensitive detector construction callback. Called at "ConstructSDandField()"
+      virtual void constructSensitives(Geant4DetectorConstructionContext* ctxt)  override;
+
+      /// User callback to determine if the model is applicable for the particle type
+      /** Default implementation checks if the particle is registered in 'ApplicableParticles'
+       */
+      virtual bool check_applicability(const G4ParticleDefinition& particle)  override;
+
+      /// User callback to determine if the shower creation should be triggered
+      /** Default implementation checks if for all particles registered in 'Etrigger'
+       *  the kinetic energy is bigger than the value.
+       */
+      virtual bool check_trigger(const G4FastTrack& track)  override;
+
+      /// User callback to model the particle/energy shower
+      virtual void modelShower(const G4FastTrack& track, G4FastStep& step)  override;
+    };
+  }     /* End namespace sim   */
+}       /* End namespace dd4hep */
+#endif  /* DDG4_GEANT4FASTSIMSHOWERMODEL_H  */
diff --git a/DDG4/include/DDG4/Geant4FastSimShowerModel.inl.h b/DDG4/include/DDG4/Geant4FastSimShowerModel.inl.h
new file mode 100644
index 000000000..cb461c210
--- /dev/null
+++ b/DDG4/include/DDG4/Geant4FastSimShowerModel.inl.h
@@ -0,0 +1,88 @@
+//==========================================================================
+//  AIDA Detector description implementation
+//--------------------------------------------------------------------------
+// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
+// All rights reserved.
+//
+// For the licensing terms see $DD4hepINSTALL/LICENSE.
+// For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
+//
+// Author     : M.Frank
+//
+//==========================================================================
+#ifndef DDG4_GEANT4FASTSIMSHOWERMODEL_INL_H
+#define DDG4_GEANT4FASTSIMSHOWERMODEL_INL_H
+
+// Framework include files
+#include <DDG4/Geant4FastSimShowerModel.h>
+
+// Geant4 include files
+
+// C/C++ include files
+#include <vector>
+#include <memory>
+
+/// Forward declarations
+
+/// Namespace for the AIDA detector description toolkit
+namespace dd4hep  {
+
+  /// Namespace for the Geant4 based simulation part of the AIDA detector description toolkit
+  namespace sim  {
+
+    /// Standard constructor
+    template <typename CONCRETE_MODEL> 
+    Geant4FSShowerModel<CONCRETE_MODEL>::Geant4FSShowerModel(Geant4Context* context, const std::string& nam)
+      : Geant4FastSimShowerModel(context, nam)
+    {
+      this->initialize();
+    }
+    
+    /// Default destructor
+    template <typename CONCRETE_MODEL> 
+    Geant4FSShowerModel<CONCRETE_MODEL>::~Geant4FSShowerModel()   {
+    }
+
+    /// Declare optional properties from embedded structure
+    template <typename CONCRETE_MODEL> 
+    void Geant4FSShowerModel<CONCRETE_MODEL>::initialize()     {
+    }
+
+    /// Geometry construction callback. Called at "Construct()"
+    template <typename CONCRETE_MODEL> 
+    void Geant4FSShowerModel<CONCRETE_MODEL>::constructGeo(Geant4DetectorConstructionContext* ctxt)   {
+      this->Geant4FastSimShowerModel::constructGeo(ctxt);
+    }
+    
+    /// Electromagnetic field construction callback. Called at "ConstructSDandField()"
+    template <typename CONCRETE_MODEL> 
+    void Geant4FSShowerModel<CONCRETE_MODEL>::constructField(Geant4DetectorConstructionContext* ctxt)   {
+      this->Geant4FastSimShowerModel::constructField(ctxt);
+    }
+
+    /// Sensitive detector construction callback. Called at "ConstructSDandField()"
+    template <typename CONCRETE_MODEL> 
+    void Geant4FSShowerModel<CONCRETE_MODEL>::constructSensitives(Geant4DetectorConstructionContext* ctxt)   {
+      this->Geant4FastSimShowerModel::constructSensitives(ctxt);
+    }
+
+    /// User callback to determine if the model is applicable for the particle type
+    template <typename CONCRETE_MODEL> 
+    bool Geant4FSShowerModel<CONCRETE_MODEL>::check_applicability(const G4ParticleDefinition& particle)   {
+      return this->Geant4FastSimShowerModel::check_applicability(particle);
+    }
+
+    /// User callback to determine if the shower creation should be triggered
+    template <typename CONCRETE_MODEL> 
+    bool Geant4FSShowerModel<CONCRETE_MODEL>::check_trigger(const G4FastTrack& track)   {
+      return this->Geant4FastSimShowerModel::check_trigger(track);
+    }
+
+    /// User callback to model the particle/energy shower
+    template <typename CONCRETE_MODEL> 
+    void Geant4FSShowerModel<CONCRETE_MODEL>::modelShower(const G4FastTrack& track, G4FastStep& step)   {
+      return this->Geant4FastSimShowerModel::modelShower(track, step);
+    }
+  }     /* End namespace sim   */
+}       /* End namespace dd4hep */
+#endif  // DDG4_GEANT4FASTSIMSHOWERMODEL_INL_H
diff --git a/DDG4/include/DDG4/Geant4FastSimSpot.h b/DDG4/include/DDG4/Geant4FastSimSpot.h
new file mode 100644
index 000000000..ba3add0fa
--- /dev/null
+++ b/DDG4/include/DDG4/Geant4FastSimSpot.h
@@ -0,0 +1,132 @@
+//==========================================================================
+//  AIDA Detector description implementation 
+//--------------------------------------------------------------------------
+// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
+// All rights reserved.
+//
+// For the licensing terms see $DD4hepINSTALL/LICENSE.
+// For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
+//
+// Author     : M.Frank
+//
+//==========================================================================
+#ifndef DDG4_GEANT4FASTSIMSPOT_H
+#define DDG4_GEANT4FASTSIMSPOT_H
+
+// Framework include files
+#include <DDG4/Defs.h>
+
+// Geant4 include files
+#include <G4Track.hh>
+#include <G4FastHit.hh>
+#include <G4FastTrack.hh>
+#include <G4ThreeVector.hh>
+#include <G4TouchableHandle.hh>
+
+/// Namespace for the AIDA detector description toolkit
+namespace dd4hep {
+
+  /// Namespace for the Geant4 based simulation part of the AIDA detector description toolkit
+  namespace sim {
+
+    /// Spot definition for fast simulation and GFlash
+    /**
+     *  \author  M.Frank
+     *  \version 1.0
+     *  \ingroup DD4HEP_SIMULATION
+     */
+    class Geant4FastSimSpot   {
+    public:
+      /// Default constructor disabled
+      Geant4FastSimSpot() = delete;
+      /// Initializing constructor
+      Geant4FastSimSpot(const G4FastHit* h, const G4FastTrack* trk);
+      /// Initializing constructor
+      Geant4FastSimSpot(const G4FastHit* h, const G4FastTrack* trk, G4VTouchable* t);
+      /// Default destructor
+      ~Geant4FastSimSpot() = default;
+
+      /// Spot's hit position
+      G4ThreeVector hitPosition() const    { return hit->GetPosition();          }
+      /// Energy deposit of the spot
+      double        energy() const         { return hit->GetEnergy();            }
+      /// Access the physical volume of the hit
+      G4VPhysicalVolume* volume() const    { return touchable->GetVolume();      }
+
+      /// Primary track position
+      G4ThreeVector trackPosition() const  { return primary->GetPosition();      }
+      /// Primary track kinetic energy
+      double kineticEnergy() const         { return primary->GetKineticEnergy(); }
+      /// Primary track particle definition
+      const G4ParticleDefinition* trackDefinition() const 
+      { return primary->GetParticleDefinition();                                 }
+      /// Particle's local direction in the region's envelope solid
+      G4ThreeVector particleLocalDirection()  const
+      { return track->GetPrimaryTrackLocalDirection();                           }
+      /// Particle's local momentum in the region's envelope solid
+      G4ThreeVector particleLocalMomentum()  const
+      { return track->GetPrimaryTrackLocalMomentum();                            }
+      /// Particle's local position in the region's envelope solid
+      G4ThreeVector particleLocalPosition()  const
+      { return track->GetPrimaryTrackLocalPosition();                            }
+
+      /// Distance to exit point from the region's envelope solid
+      double distanceToOut()   const;
+      /// Particle's global direction in the region's envelope solid
+      G4ThreeVector particleDirection()  const;
+      /// Particle's global momentum in the region's envelope solid
+      G4ThreeVector particleMomentum()  const;
+      /// Particle's global position in the region's envelope solid
+      G4ThreeVector particlePosition()  const;
+      
+  public:
+      const G4FastHit*   hit        { nullptr };
+      const G4FastTrack* track      { nullptr };
+      const G4Track*     primary    { nullptr };
+      G4VTouchable*      touchable  { nullptr };
+    };
+
+    /// Initializing constructor
+    inline Geant4FastSimSpot::Geant4FastSimSpot(const G4FastHit* h,
+						const G4FastTrack* trk,
+						G4VTouchable* t)
+      : hit(h), track(trk), primary(trk->GetPrimaryTrack()), touchable(t)
+    {
+    }
+
+    /// Initializing constructor
+    inline Geant4FastSimSpot::Geant4FastSimSpot(const G4FastHit* h,
+						const G4FastTrack* trk)
+      : hit(h), track(trk), primary(trk->GetPrimaryTrack())
+    {
+    }
+
+    /// Particle's global momentum in the region's envelope solid
+    inline G4ThreeVector Geant4FastSimSpot::particleMomentum()  const    {
+      auto mom = track->GetPrimaryTrackLocalMomentum();
+      return track->GetInverseAffineTransformation()->TransformPoint(mom);
+    }
+
+    /// Particle's global direction in the region's envelope solid
+    inline G4ThreeVector Geant4FastSimSpot::particleDirection()  const    {
+      auto dir = track->GetPrimaryTrackLocalDirection();
+      return track->GetInverseAffineTransformation()->TransformPoint(dir);
+    }
+
+    /// Particle's global position in the region's envelope solid
+    inline G4ThreeVector Geant4FastSimSpot::particlePosition()  const    {
+      auto pos = track->GetPrimaryTrackLocalPosition();
+      return track->GetInverseAffineTransformation()->TransformPoint(pos);
+    }
+
+    /// Distance to exit point from the region's envelope solid
+    inline double Geant4FastSimSpot::distanceToOut()   const     {
+      auto pos = track->GetPrimaryTrackLocalPosition();
+      auto dir = track->GetPrimaryTrackLocalDirection();
+      return track->GetEnvelopeSolid()->DistanceToOut(pos, dir);
+    }
+
+
+  }    // End namespace sim
+}      // End namespace dd4hep
+#endif // DDG4_GEANT4FASTSIMSPOT_H
diff --git a/DDG4/include/DDG4/Geant4GFlashSpotHandler.h b/DDG4/include/DDG4/Geant4HitHandler.h
similarity index 58%
rename from DDG4/include/DDG4/Geant4GFlashSpotHandler.h
rename to DDG4/include/DDG4/Geant4HitHandler.h
index 548ae201d..23bccaa86 100644
--- a/DDG4/include/DDG4/Geant4GFlashSpotHandler.h
+++ b/DDG4/include/DDG4/Geant4HitHandler.h
@@ -10,16 +10,13 @@
 // Author     : M.Frank
 //
 //==========================================================================
-#ifndef DDG4_GEANT4GFLASHSPOTHANDLER_H
-#define DDG4_GEANT4GFLASHSPOTHANDLER_H
+#ifndef DDG4_GEANT4HITHANDLER_H
+#define DDG4_GEANT4HITHANDLER_H
 
 // Framework include files
 #include "DDG4/Defs.h"
 
 // Geant4 include files
-#include "G4GFlashSpot.hh"
-#include "G4VTouchable.hh"
-#include "G4VSensitiveDetector.hh"
 #include "G4EmSaturation.hh"
 #include "G4Version.hh"
 
@@ -30,76 +27,47 @@ namespace dd4hep {
   namespace sim {
 
     // Forward declarations;
-    class Geant4GFlashSpotHandler;
+    class Geant4HitHandler;
 
-    /// Helper class to ease the extraction of information from a G4GFlashSpot object.
+    /// Helper class to ease the extraction of information from a G4Hit object.
     /**
      *
-     * Helper/utility class to easily access Geant4 gflashspot information.
+     * Helper/utility class to easily access Geant4 hit information.
      * Born by lazyness: Avoid typing millions of statements!
      *
      *  \author  M.Frank
      *  \version 1.0
      *  \ingroup DD4HEP_SIMULATION
      */
-    class Geant4GFlashSpotHandler {
+    class Geant4HitHandler {
     public:
-      const G4GFlashSpot* gflashspot;
-      const G4FastTrack*  fast_track;
-      const G4Track*      track;
+      const G4Track* track;
+      const G4VTouchable* touchable_ptr;
       /// Inhibit default constructor
-      Geant4GFlashSpotHandler() = delete;
+      Geant4HitHandler() = delete;
       /// Initializing constructor
-      Geant4GFlashSpotHandler(const G4GFlashSpot* s) : gflashspot(s) {
-        fast_track = gflashspot->GetOriginatorTrack();
-	track      = fast_track->GetPrimaryTrack();
+      Geant4HitHandler(const G4Track* t, const G4VTouchable* h)
+	: track(t), touchable_ptr(h)
+      {
       }
       /// No copy constructor
-      Geant4GFlashSpotHandler(const Geant4GFlashSpotHandler& copy) = delete;
+      Geant4HitHandler(const Geant4HitHandler& copy) = delete;
       /// No move constructor
-      Geant4GFlashSpotHandler(Geant4GFlashSpotHandler&& copy) = delete;
+      Geant4HitHandler(Geant4HitHandler&& copy) = delete;
       /// Assignment operator inhibited. Should not be copied
-      Geant4GFlashSpotHandler& operator=(const Geant4GFlashSpotHandler& copy) = delete;
+      Geant4HitHandler& operator=(const Geant4HitHandler& copy) = delete;
       /// Move operator inhibited. Should not be copied
-      Geant4GFlashSpotHandler& operator=(Geant4GFlashSpotHandler&& copy) = delete;
+      Geant4HitHandler& operator=(Geant4HitHandler&& copy) = delete;
       
+      const G4VTouchable* touchable() const {
+        return touchable_ptr;
+      }
       G4ParticleDefinition* trackDef() const {
         return track->GetDefinition();
       }
       int trkPdgID() const {
         return track->GetDefinition()->GetPDGEncoding();
       }
-      /// Returns total energy deposit
-      double energy() const  {
-	return gflashspot->GetEnergySpot()->GetEnergy();
-      }
-      /// Returns the pre-gflashspot position
-      Position position() const {
-        const G4ThreeVector p = gflashspot->GetEnergySpot()->GetPosition();
-        return Position(p.x(), p.y(), p.z());
-      }
-      /// Direction calculated from the post- and pre-position ofthe gflashspot
-      Position direction()  const  {
-        const G4ThreeVector p = track->GetMomentumDirection();
-        return Position(p.x(), p.y(), p.z());
-      }
-      /// Return track momentum in DD4hep notation
-      Momentum momentum() const {
-        const G4ThreeVector& p = track->GetMomentum();
-        return Momentum(p.x(), p.y(), p.z());
-      }
-      /// Returns the post-step position as a G4ThreeVector
-      G4ThreeVector positionG4() const {
-        return gflashspot->GetEnergySpot()->GetPosition();
-      }
-      /// Returns the track momentum as a G4ThreeVector
-      G4ThreeVector momentumG4() const {
-        return track->GetMomentum();
-      }
-      /// Access the enery deposit of the energy spot
-      double deposit() const  {
-        return gflashspot->GetEnergySpot()->GetEnergy();
-      }
       /// Access the G4 track ID
       int trkID() const  {
         return track->GetTrackID();
@@ -126,30 +94,17 @@ namespace dd4hep {
       const G4VProcess* trkProcess()  const  {
         return track->GetCreatorProcess();
       }
-      const G4VTouchable* touchable() const {
-        return gflashspot->GetTouchableHandle().operator->();
-      }
-      G4VPhysicalVolume* volume() const {
-	return touchable()->GetVolume();
-      }
-      G4LogicalVolume* logvol() const {
-        return volume()->GetLogicalVolume();
-      }
-      G4VSolid* solid() const {
-        return touchable()->GetSolid();
-      }
-      G4VSensitiveDetector* sd()  const {
-        G4LogicalVolume* lv = logvol();
-        return lv ? lv->GetSensitiveDetector() : 0;
-      }
-      const char* sdName(const char* undefined = "") const {
-        G4VSensitiveDetector* s = sd();
-        return s ? s->GetName().c_str() : undefined;
+      Momentum trkMom() const {
+        const G4ThreeVector& p = track->GetMomentum();
+        return Momentum(p.x(), p.y(), p.z());
       }
-      bool isSensitive() const {
-	G4LogicalVolume* lv = logvol();
+      bool isSensitive(const G4LogicalVolume* lv) const {
         return lv ? (0 != lv->GetSensitiveDetector()) : false;
       }
+      bool isSensitive(const G4VPhysicalVolume* pv) const {
+        return pv ? isSensitive(pv->GetLogicalVolume()) : false;
+      }
+
       /// Coordinate transformation to global coordinates.
       /** Note: Positions are in units of MM! */
       Position localToGlobal(const Position& local)  const;
diff --git a/DDG4/include/DDG4/Geant4ReadoutVolumeFilter.h b/DDG4/include/DDG4/Geant4ReadoutVolumeFilter.h
index cd68443dc..5e5477819 100644
--- a/DDG4/include/DDG4/Geant4ReadoutVolumeFilter.h
+++ b/DDG4/include/DDG4/Geant4ReadoutVolumeFilter.h
@@ -48,9 +48,9 @@ namespace dd4hep {
       /// Default destructor
       virtual ~Geant4ReadoutVolumeFilter();
       /// Filter action. Return true if hits should be processed
-      virtual bool operator()(const G4Step* step) const;
-      /// GFLASH interface: Filter action. Return true if hits should be processed.
-      virtual bool operator()(const G4GFlashSpot* step) const;
+      virtual bool operator()(const G4Step* step) const  override;
+      /// GFLASH/FastSim interface: Filter action. Return true if hits should be processed.
+      virtual bool operator()(const Geant4FastSimSpot* step) const  override;
     };
   }    // End namespace sim
 }      // End namespace dd4hep
diff --git a/DDG4/include/DDG4/Geant4SensDetAction.h b/DDG4/include/DDG4/Geant4SensDetAction.h
index d514867bf..83942db58 100644
--- a/DDG4/include/DDG4/Geant4SensDetAction.h
+++ b/DDG4/include/DDG4/Geant4SensDetAction.h
@@ -16,8 +16,16 @@
 // Framework include files
 #include "DD4hep/Detector.h"
 #include "DDG4/Geant4Action.h"
+//#include "DDG4/Geant4FastSimSpot.h"
 #include "DDG4/Geant4HitCollection.h"
 
+// Geant4 include files
+//#include <G4Track.hh>
+//#include <G4FastHit.hh>
+//#include <G4FastTrack.hh>
+#include <G4ThreeVector.hh>
+//#include <G4TouchableHandle.hh>
+
 // C/C++ include files
 #include <vector>
 
@@ -25,7 +33,7 @@
 class G4HCofThisEvent;
 class G4Step;
 class G4Event;
-class G4GFlashSpot;
+class G4VTouchable;
 class G4TouchableHistory;
 class G4VHitsCollection;
 class G4VReadOutGeometry;
@@ -42,9 +50,10 @@ namespace dd4hep {
   namespace sim {
 
     // Forward declarations
+    class Geant4Sensitive;
+    class Geant4FastSimSpot;
     class Geant4StepHandler;
     class Geant4HitCollection;
-    class Geant4Sensitive;
     class Geant4SensDetActionSequence;
     class Geant4SensDetSequences;
 
@@ -97,13 +106,15 @@ namespace dd4hep {
       Geant4Filter(Geant4Context* context, const std::string& name);
       /// Standard destructor
       virtual ~Geant4Filter();
+
       /// Filter action. Return true if hits should be processed. Default returns true
       virtual bool operator()(const G4Step* step) const;
-      /// GFLASH interface: Filter action. Return true if hits should be processed.
+
+      /// GFLASH/FastSim interface: Filter action. Return true if hits should be processed.
       /** The default implementation throws an exception that the 
-       *  GFLASH interface is not implemented.
+       *  GFLASH / FastSim interface is not implemented.
        */
-      virtual bool operator()(const G4GFlashSpot* step) const;
+      virtual bool operator()(const Geant4FastSimSpot* spot) const;
     };
 
     /// The base class for Geant4 sensitive detector actions implemented by users
@@ -227,10 +238,10 @@ namespace dd4hep {
        */
       bool accept(const G4Step* step) const;
 
-      /// GFLASH interface: Callback before hit processing starts. Invoke all filters.
+      /// GFLASH/FastSim interface: Callback before hit processing starts. Invoke all filters.
       /** Return false if any filter returns false
        */
-      bool accept(const G4GFlashSpot* step) const;
+      bool accept(const Geant4FastSimSpot* step) const;
 
       /// Initialize the usage of a single hit collection. Returns the collection ID
       template <typename TYPE> size_t defineCollection(const std::string& coll_name);
@@ -256,15 +267,6 @@ namespace dd4hep {
       /// G4VSensitiveDetector interface: Method invoked at the end of each event.
       virtual void end(G4HCofThisEvent* hce);
 
-      /// G4VSensitiveDetector interface: Method for generating hit(s) using the information of G4Step object.
-      virtual bool process(G4Step* step, G4TouchableHistory* history);
-
-      /// Separate GFLASH interface: Method for generating hit(s) using the information of the G4GFlashSpot object.
-      /** The default implementation throws an exception that the 
-       *  GFLASH interface is not implemented.
-       */
-      virtual bool processGFlash(G4GFlashSpot* spot, G4TouchableHistory* history);
-
       /// G4VSensitiveDetector interface: Method invoked if the event was aborted.
       /** Hits collections created but not being set to G4HCofThisEvent
        *  at the event should be deleted.
@@ -279,11 +281,11 @@ namespace dd4hep {
        */
       long long int volumeID(const G4Step* step);
 
-      /// Returns the volumeID of the sensitive volume corresponding to the GFlash spot
+      /// Returns the volumeID of the sensitive volume corresponding to the G4VTouchable
       /** Combining the VolIDS of the complete geometry path (Geant4TouchableHistory)
        * from the current sensitive volume to the world volume
        */
-      long long int volumeID(const G4GFlashSpot* spot);
+      long long int volumeID(const G4VTouchable* touchable);
 
       /// Returns the cellID of the sensitive volume corresponding to the step
       /** The CellID is the VolumeID + the local coordinates of the sensitive area.
@@ -292,12 +294,21 @@ namespace dd4hep {
        */
       long long int cellID(const G4Step* step);
 
-      /// Returns the cellID of the sensitive volume corresponding to the GFlash spot
+      /// Returns the cellID of the sensitive volume corresponding to the G4VTouchable
       /** The CellID is the VolumeID + the local coordinates of the sensitive area.
        *  Calculated by combining the VolIDS of the complete geometry path (Geant4TouchableHistory)
        *  from the current sensitive volume to the world volume
        */
-      long long int cellID(const G4GFlashSpot* spot);
+      long long int cellID(const G4VTouchable* touchable, const G4ThreeVector& global);
+
+      /// G4VSensitiveDetector interface: Method for generating hit(s) using the information of G4Step object.
+      virtual bool process(const G4Step* step, G4TouchableHistory* history);
+
+      /// GFLASH/FastSim interface: Method for generating hit(s) using the information of the fast simulation spot object.
+      /** The default implementation throws an exception that the 
+       *  GFLASH/FastSim interface is not implemented.
+       */
+      virtual bool processFastSim(const Geant4FastSimSpot* spot, G4TouchableHistory* history);
     };
 
     /// The sequencer to host Geant4 sensitive actions called if particles interact with sensitive elements
@@ -415,14 +426,8 @@ namespace dd4hep {
       /// Callback before hit processing starts. Invoke all filters.
       bool accept(const G4Step* step) const;
 
-      /// GFLASH interface: Callback before hit processing starts. Invoke all filters.
-      bool accept(const G4GFlashSpot* step) const;
-
-      /// G4VSensitiveDetector interface: Method for generating hit(s) using the information of G4Step object.
-      virtual bool process(G4Step* step, G4TouchableHistory* history);
-
-      /// Separate GFLASH interface: Method for generating hit(s) using the information of the G4GFlashSpot object.
-      virtual bool processGFlash(G4GFlashSpot* spot, G4TouchableHistory* history);
+      /// GFLASH/FastSim interface: Callback before hit processing starts. Invoke all filters.
+      bool accept(const Geant4FastSimSpot* step) const;
 
       /// G4VSensitiveDetector interface: Method invoked at the begining of each event.
       /** The hits collection(s) created by this sensitive detector must
@@ -440,6 +445,12 @@ namespace dd4hep {
        *  will be deleted automatically.
        */
       virtual void clear();
+
+      /// G4VSensitiveDetector interface: Method for generating hit(s) using the information of G4Step object.
+      virtual bool process(const G4Step* step, G4TouchableHistory* history);
+
+      /// GFLASH/FastSim interface: Method for generating hit(s) using the information of the fast simulation spot object.
+      virtual bool processFastSim(const Geant4FastSimSpot* spot, G4TouchableHistory* history);
     };
 
     /// Geant4SensDetSequences: class to access groups of sensitive actions
@@ -560,20 +571,21 @@ namespace dd4hep {
       size_t defineReadoutCollection(const std::string collection_name);
 
       /// Initialization overload for specialization
-      virtual void initialize();
+      virtual void initialize()  final;
       /// Finalization overload for specialization
-      virtual void finalize();
+      virtual void finalize()  final;
       /// G4VSensitiveDetector interface: Method invoked at the begining of each event.
-      virtual void begin(G4HCofThisEvent* hce);
+      virtual void begin(G4HCofThisEvent* hce)  final;
       /// G4VSensitiveDetector interface: Method invoked at the end of each event.
-      virtual void end(G4HCofThisEvent* hce);
+      virtual void end(G4HCofThisEvent* hce)  final;
+      /// G4VSensitiveDetector interface: Method invoked if the event was aborted.
+      virtual void clear(G4HCofThisEvent* hce)  final;
+
       /// G4VSensitiveDetector interface: Method for generating hit(s) using the G4Step object.
-      virtual bool process(G4Step* step,G4TouchableHistory* history);
-      /// Separate GFLASH interface: Method for generating hit(s) using the information of the G4GFlashSpot object.
-      virtual bool processGFlash(G4GFlashSpot* spot, G4TouchableHistory* history);
+      virtual bool process(const G4Step* step,G4TouchableHistory* history)  final;
 
-      /// G4VSensitiveDetector interface: Method invoked if the event was aborted.
-      virtual void clear(G4HCofThisEvent* hce);
+      /// GFLASH/FastSim interface: Method for generating hit(s) using the information of the fast simulation spot object.
+      virtual bool processFastSim(const Geant4FastSimSpot* spot, G4TouchableHistory* history)  final;
     };
 
   }    // End namespace sim
diff --git a/DDG4/include/DDG4/Geant4SensDetAction.inl b/DDG4/include/DDG4/Geant4SensDetAction.inl
index 69d852f3f..0d60d4037 100644
--- a/DDG4/include/DDG4/Geant4SensDetAction.inl
+++ b/DDG4/include/DDG4/Geant4SensDetAction.inl
@@ -47,22 +47,22 @@ namespace dd4hep {
     }
 
     /// Initialization overload for specialization
-    template <typename T> void Geant4SensitiveAction<T>::initialize()    {
+    template <typename T> void Geant4SensitiveAction<T>::initialize()   {
     }
 
     /// Finalization overload for specialization
-    template <typename T> void Geant4SensitiveAction<T>::finalize()    {
+    template <typename T> void Geant4SensitiveAction<T>::finalize()   {
     }
 
     /// Access the readout object. Note: if m_readoutName is set, the m_readout != m_sensitive.readout()
-    template <typename T> Readout Geant4SensitiveAction<T>::readout()     {
-      if ( !m_readoutName.empty() && m_sensitive.readout() == m_readout )   {
+    template <typename T> Readout Geant4SensitiveAction<T>::readout()    {
+      if ( !m_readoutName.empty() && m_sensitive.readout() == m_readout )  {
         m_readout = detectorDescription().readout(m_readoutName);
-        if ( !m_readout.isValid() )   {
+        if ( !m_readout.isValid() )  {
           except("+++ Failed to access parallel readout '%s'",m_sensitive.name());
         }
         m_segmentation = m_readout.segmentation();
-        if ( !m_segmentation.isValid() )   {
+        if ( !m_segmentation.isValid() )  {
           except("+++ Failed to access segmentation for readout '%s'",m_readout.name());
         }
       }
@@ -79,23 +79,13 @@ namespace dd4hep {
       Geant4Sensitive::end(hce);
     }
 
-    /// G4VSensitiveDetector interface: Method for generating hit(s) using the G4Step object.
-    template <typename T> bool Geant4SensitiveAction<T>::process(G4Step* step,G4TouchableHistory* history)  {
-      return Geant4Sensitive::process(step,history);
-    }
-    
-    /// Separate GFLASH interface: Method for generating hit(s) using the information of the G4GFlashSpot object.
-    template <typename T> bool Geant4SensitiveAction<T>::processGFlash(G4GFlashSpot* spot, G4TouchableHistory* history)   {
-      return Geant4Sensitive::processGFlash(spot,history);
-    }
-
     /// G4VSensitiveDetector interface: Method invoked if the event was aborted.
     template <typename T> void Geant4SensitiveAction<T>::clear(G4HCofThisEvent* hce)  {
       Geant4Sensitive::clear(hce);
     }
 
     /// Define collections created by this sensitivie action object
-    template <typename T> void Geant4SensitiveAction<T>::defineCollections()   {
+    template <typename T> void Geant4SensitiveAction<T>::defineCollections()  {
     }
 
     /// Define readout specific hit collection. matching name must be present in readout structure
@@ -103,7 +93,7 @@ namespace dd4hep {
     size_t Geant4SensitiveAction<T>::defineReadoutCollection(const std::string match_name)  {
       auto ro = readout();
       for(const auto& c : ro->hits )  {
-        if ( c.name == match_name )   {
+        if ( c.name == match_name )  {
           size_t coll_id = defineCollection<HIT>(match_name);
           Geant4Filter* filter = new Geant4ReadoutVolumeFilter(context(),name()+"_"+c.name,ro,c.name);
           adopt_front(filter);
@@ -117,14 +107,23 @@ namespace dd4hep {
 
     /// Define readout specific hit collection with volume ID filtering
     template <typename T> template <typename HIT> 
-    size_t Geant4SensitiveAction<T>::declareReadoutFilteredCollection()
-    {
+    size_t Geant4SensitiveAction<T>::declareReadoutFilteredCollection()   {
       if ( m_collectionName.empty() )  {
         return defineCollection<HIT>(readout().name());
       }
       return defineReadoutCollection<HIT>(m_collectionName);
     }
 
+    /// G4VSensitiveDetector interface: Method for generating hit(s) using the G4Step object.
+    template <typename T> bool Geant4SensitiveAction<T>::process(const G4Step* step,G4TouchableHistory* history)  {
+      return Geant4Sensitive::process(step, history);
+    }
+    
+    /// GFlash/Fast Simulation interface: Method for generating hit(s) using the information from fast simulation
+    template <typename T> bool Geant4SensitiveAction<T>::processFastSim(const Geant4FastSimSpot* spot, G4TouchableHistory* history)  {
+      return Geant4Sensitive::processFastSim(spot, history);
+    }
+
     // Forward declarations
     typedef Geant4HitData::Contribution HitContribution;
 
diff --git a/DDG4/include/DDG4/Geant4StepHandler.h b/DDG4/include/DDG4/Geant4StepHandler.h
index 3005001a6..27d0ab957 100644
--- a/DDG4/include/DDG4/Geant4StepHandler.h
+++ b/DDG4/include/DDG4/Geant4StepHandler.h
@@ -14,7 +14,7 @@
 #define DDG4_GEANT4STEPHANDLER_H
 
 // Framework include files
-#include "DDG4/Defs.h"
+#include <DDG4/Geant4HitHandler.h>
 
 // Geant4 include files
 #include "G4Step.hh"
@@ -43,20 +43,21 @@ namespace dd4hep {
      *  \version 1.0
      *  \ingroup DD4HEP_SIMULATION
      */
-    class Geant4StepHandler {
+    class Geant4StepHandler : public Geant4HitHandler  {
     public:
       const G4Step* step;
-      G4StepPoint* pre;
-      G4StepPoint* post;
-      G4Track* track;
+      G4StepPoint*  pre;
+      G4StepPoint*  post;
       bool applyBirksLaw;
       /// Inhibit default constructor
       Geant4StepHandler() = delete;
       /// Initializing constructor
-      Geant4StepHandler(const G4Step* s) : step(s) {
+      Geant4StepHandler(const G4Step* s)
+	: Geant4HitHandler(s->GetTrack(), (s->GetPreStepPoint()->GetTouchableHandle())()),
+	step(s)
+      {
         pre = s->GetPreStepPoint();
         post = s->GetPostStepPoint();
-        track = s->GetTrack();
         applyBirksLaw = false;
       }
       /// No copy constructor
@@ -68,12 +69,6 @@ namespace dd4hep {
       /// Move operator inhibited. Should not be copied
       Geant4StepHandler& operator=(Geant4StepHandler&& copy) = delete;
       
-      G4ParticleDefinition* trackDef() const {
-        return track->GetDefinition();
-      }
-      int trkPdgID() const {
-        return track->GetDefinition()->GetPDGEncoding();
-      }
       /// Returns the step status (argument) in form of a string
       static const char* stepStatus(G4StepStatus status);
       /// Returns the pre-step status in form of a string
@@ -106,6 +101,13 @@ namespace dd4hep {
         return post->GetPosition();
       }
       /// Average position vector of the step.
+      G4ThreeVector avgPositionG4() const  {
+        const G4ThreeVector& p1 = pre->GetPosition();
+        const G4ThreeVector& p2 = post->GetPosition();
+        G4ThreeVector r = 0.5*(p2+p1);
+        return r;
+      }
+      /// Average position vector of the step.
       Position avgPosition() const  {
         const G4ThreeVector& p1 = pre->GetPosition();
         const G4ThreeVector& p2 = post->GetPosition();
@@ -132,40 +134,12 @@ namespace dd4hep {
         const G4ThreeVector& p = post->GetMomentum();
         return Momentum(p.x(), p.y(), p.z());
       }
-      Momentum trkMom() const {
-        const G4ThreeVector& p = track->GetMomentum();
-        return Momentum(p.x(), p.y(), p.z());
-      }
       double deposit() const  {
         return step->GetTotalEnergyDeposit();
       }
       double stepLength() const  {
         return step->GetStepLength();
       }
-      int trkID() const  {
-        return track->GetTrackID();
-      }
-      int parentID() const  {
-        return track->GetParentID();
-      }
-      double trkTime() const  {
-        return track->GetGlobalTime();
-      }
-      double trkEnergy() const  {
-        return track->GetTotalEnergy();
-      }
-      double trkKineEnergy() const  {
-        return track->GetKineticEnergy();
-      }
-      int trkStatus()  const  {
-        return track->GetTrackStatus();
-      }
-      bool trkAlive() const  {
-        return track->GetTrackStatus() == fAlive;
-      }
-      const G4VProcess* trkProcess()  const  {
-        return track->GetCreatorProcess();
-      }
       const G4VTouchable* preTouchable() const {
         return pre->GetTouchable();
       }
@@ -197,14 +171,8 @@ namespace dd4hep {
         G4VSensitiveDetector* s = sd(p);
         return s ? s->GetName().c_str() : undefined;
       }
-      bool isSensitive(const G4LogicalVolume* lv) const {
-        return lv ? (0 != lv->GetSensitiveDetector()) : false;
-      }
-      bool isSensitive(const G4VPhysicalVolume* pv) const {
-        return pv ? isSensitive(pv->GetLogicalVolume()) : false;
-      }
       bool isSensitive(const G4StepPoint* point) const {
-        return point ? isSensitive(volume(point)) : false;
+        return point ? this->Geant4HitHandler::isSensitive(volume(point)) : false;
       }
       G4VPhysicalVolume* preVolume() const {
         return volume(pre);
@@ -224,28 +192,6 @@ namespace dd4hep {
       bool lastInVolume() const  {
         return step->IsLastStepInVolume();
       }
-      /// Coordinate transformation to global coordinates.
-      /** Note: Positions are in units of MM! */
-      Position localToGlobal(const Position& local)  const;
-      /// Coordinate transformation to global coordinates.
-      /** Note: DDSegmentation points are units in CM! Conversion done inside! */
-      Position localToGlobal(const DDSegmentation::Vector3D& local)  const;
-      /// Coordinate transformation to global coordinates in MM
-      Position localToGlobal(const G4ThreeVector& local)  const;
-      /// Coordinate transformation to global coordinates in MM
-      Position localToGlobal(double x, double y, double z)  const;
-
-      /// Coordinate transformation to local coordinates
-      Position globalToLocal(double x, double y, double z)  const;
-      /// Coordinate transformation to local coordinates
-      Position globalToLocal(const Position& global)  const;
-      /// Coordinate transformation to local coordinates
-      Position globalToLocal(const G4ThreeVector& global)  const;
-      /// Coordinate transformation to local coordinates
-      G4ThreeVector globalToLocalG4(double x, double y, double z)  const;
-      /// Coordinate transformation to local coordinates with G4 objects
-      G4ThreeVector globalToLocalG4(const G4ThreeVector& loc)  const;
-
       /// Apply BirksLaw
       double birkAttenuation() const;
       /// Set applyBirksLaw to ture
diff --git a/DDG4/include/DDG4/Geant4TestActions.h b/DDG4/include/DDG4/Geant4TestActions.h
index 77b848aa6..9320e4abc 100644
--- a/DDG4/include/DDG4/Geant4TestActions.h
+++ b/DDG4/include/DDG4/Geant4TestActions.h
@@ -127,9 +127,9 @@ namespace dd4hep {
         /// Default destructor
         virtual ~Geant4TestTrackAction();
         /// Begin-of-tracking callback
-        virtual void begin(const G4Track*);
+        virtual void begin(const G4Track*)  override;
         /// End-of-tracking callback
-        virtual void end(const G4Track*);
+        virtual void end(const G4Track*)  override;
       };
 
       /// Example stepping action doing nothing, but print
@@ -145,7 +145,7 @@ namespace dd4hep {
         /// Default destructor
         virtual ~Geant4TestStepAction();
         /// User stepping callback
-        void operator()(const G4Step*, G4SteppingManager*);
+        void operator()(const G4Step*, G4SteppingManager*)  override;
       };
 
       /// Example sensitve detector action doing nothing, but print
@@ -163,11 +163,11 @@ namespace dd4hep {
         /// Default destructor
         virtual ~Geant4TestSensitive();
         /// Begin-of-tracking callback
-        virtual void begin(G4HCofThisEvent*);
+        virtual void begin(G4HCofThisEvent*)  override;
         /// End-of-tracking callback
-        virtual void end(G4HCofThisEvent*);
+        virtual void end(G4HCofThisEvent*)  override;
         /// Method for generating hit(s) using the information of G4Step object.
-        virtual bool process(G4Step*, G4TouchableHistory*);
+        virtual bool process(const G4Step*, G4TouchableHistory*)  override;
       };
     }   // End namespace Test
   }    // End namespace sim
diff --git a/DDG4/include/DDG4/Geant4UIManager.h b/DDG4/include/DDG4/Geant4UIManager.h
index a5dab7eca..50d2bda57 100644
--- a/DDG4/include/DDG4/Geant4UIManager.h
+++ b/DDG4/include/DDG4/Geant4UIManager.h
@@ -91,7 +91,9 @@ namespace dd4hep {
       void stop();
       /// Force exiting this process without calling atexit handlers
       void forceExit();
-     /// Run UI
+      /// Regularly exiting this process without calling atexit handlers
+      void regularExit();
+	/// Run UI
       virtual void operator()(void* param);
     };
 
diff --git a/DDG4/plugins/Geant4EscapeCounter.cpp b/DDG4/plugins/Geant4EscapeCounter.cpp
index 411c86e6f..80bc3e78f 100644
--- a/DDG4/plugins/Geant4EscapeCounter.cpp
+++ b/DDG4/plugins/Geant4EscapeCounter.cpp
@@ -43,7 +43,7 @@ namespace dd4hep {
       /// Default destructor
       virtual ~Geant4EscapeCounter();
       /// G4VSensitiveDetector interface: Method for generating hit(s) using the information of G4Step object.
-      virtual bool process(G4Step* step, G4TouchableHistory* history)  override;
+      virtual bool process(const G4Step* step, G4TouchableHistory* history)  override;
     };
 
   }    // End namespace sim
@@ -96,7 +96,7 @@ Geant4EscapeCounter::~Geant4EscapeCounter() {
 }
 
 /// G4VSensitiveDetector interface: Method for generating hit(s) using the information of G4Step object.
-bool Geant4EscapeCounter::process(G4Step* step, G4TouchableHistory* /* history */)   {
+bool Geant4EscapeCounter::process(const G4Step* step, G4TouchableHistory* /* history */)   {
   Geant4StepHandler  h(step);
   Geant4TrackHandler th(h.track);
   Geant4TouchableHandler handler(step);
@@ -116,7 +116,7 @@ bool Geant4EscapeCounter::process(G4Step* step, G4TouchableHistory* /* history *
         h.trkID(),h.trkEnergy()/CLHEP::MeV,th.name().c_str(),
         th.creatorName().c_str(),hdlr_path.c_str());
   // Kill track, so that it does no longer participate in the propagation
-  h.track->SetTrackStatus(fStopAndKill);
+  step->GetTrack()->SetTrackStatus(fStopAndKill);
   return true;
 }
 
diff --git a/DDG4/plugins/Geant4FastSimShowerModel.cpp b/DDG4/plugins/Geant4FastSimShowerModel.cpp
new file mode 100644
index 000000000..d676f63bb
--- /dev/null
+++ b/DDG4/plugins/Geant4FastSimShowerModel.cpp
@@ -0,0 +1,22 @@
+//==========================================================================
+//  AIDA Detector description implementation
+//--------------------------------------------------------------------------
+// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
+// All rights reserved.
+//
+// For the licensing terms see $DD4hepINSTALL/LICENSE.
+// For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
+//
+// Author     : M.Frank
+//
+//==========================================================================
+
+// Framework include files
+#include <DDG4/Geant4FastSimShowerModel.h>
+
+using namespace dd4hep;
+using namespace dd4hep::sim;
+
+#include <DDG4/Factories.h>
+DECLARE_GEANT4ACTION(Geant4FastSimShowerModel)
+
diff --git a/DDG4/plugins/Geant4GFlashShowerModel.cpp b/DDG4/plugins/Geant4GFlashShowerModel.cpp
index 8cef358ce..2ec874852 100644
--- a/DDG4/plugins/Geant4GFlashShowerModel.cpp
+++ b/DDG4/plugins/Geant4GFlashShowerModel.cpp
@@ -10,8 +10,8 @@
 // Author     : M.Frank
 //
 //==========================================================================
-#ifndef DDG4_GEANT4GFLASHACTION_H
-#define DDG4_GEANT4GFLASHACTION_H
+#ifndef DDG4_GEANT4GFLASHSHOWERMODEL_H
+#define DDG4_GEANT4GFLASHSHOWERMODEL_H
 
 // Framework include files
 #include <DDG4/Geant4FastSimShowerModel.h>
@@ -32,8 +32,6 @@ namespace dd4hep  {
   /// Namespace for the Geant4 based simulation part of the AIDA detector description toolkit
   namespace sim  {
     
-    class Geant4InputAction;
-
     /// Geant4 wrapper for the GFlash shower model
     /**
      *  Geant4 wrapper for the GFlash shower model
@@ -92,7 +90,7 @@ namespace dd4hep  {
     };
   }     /* End namespace sim   */
 }       /* End namespace dd4hep */
-#endif // DDG4_GEANT4GFLASHACTION_H
+#endif // DDG4_GEANT4GFLASHSHOWERMODEL_H
 
 //==========================================================================
 //  AIDA Detector description implementation
@@ -109,6 +107,8 @@ namespace dd4hep  {
 
 // Framework include files
 // #include <DDG4/Geant4GFlashShowerModel.h>
+#include <DD4hep/Detector.h>
+#include <DDG4/Geant4Action.h>
 #include <DDG4/Geant4Kernel.h>
 #include <DDG4/Geant4Mapping.h>
 
diff --git a/DDG4/plugins/Geant4P1ShowerModel.cpp b/DDG4/plugins/Geant4P1ShowerModel.cpp
new file mode 100644
index 000000000..e8125fec2
--- /dev/null
+++ b/DDG4/plugins/Geant4P1ShowerModel.cpp
@@ -0,0 +1,210 @@
+//==========================================================================
+//  AIDA Detector description implementation
+//--------------------------------------------------------------------------
+// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
+// All rights reserved.
+//
+// For the licensing terms see $DD4hepINSTALL/LICENSE.
+// For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
+//
+// Author     : M.Frank
+//
+//==========================================================================
+//
+// Please note:
+//
+// These shower parametrizations come direct from the Geant4 example:
+// <geant4-source-dir>/examples/extended/parameterisations/Par01
+//
+// From the README:
+// 	      o Par01EMShowerModel which provides a crude
+//		parameterisation for e+/e-/gamma. This model
+//		is bound to the EM calorimeter.
+//
+//	      o Par01PionShowerModel: an even more crude
+//		parameterisation for pi+/pi-. This model
+//		is bound to a ghost volume.
+//
+//==========================================================================
+
+// Framework include files
+#include <DDG4/Geant4FastSimShowerModel.inl.h>
+#include <DDG4/Geant4FastSimSpot.h>
+
+// Geant4 include files
+#include "G4Gamma.hh"
+#include "Randomize.hh"
+#include "G4SystemOfUnits.hh"
+#include "G4FastSimHitMaker.hh"
+
+// C/C++ include files
+
+/// Namespace for the AIDA detector description toolkit
+namespace dd4hep  {
+
+  /// Namespace for the Geant4 based simulation part of the AIDA detector description toolkit
+  namespace sim  {
+
+    ///===================================================================================================
+    ///
+    ///  Par01 electromagnetic shower model (e+, e-)
+    ///
+    ///===================================================================================================
+
+    /// Configuration structure for the fast simulation shower model Geant4FSShowerModel<par01_em_model>
+    class par01_em_model  {
+    public:
+      G4FastSimHitMaker hitMaker          { };
+      std::string       materialName      { };
+      G4Material*       material          { nullptr };
+      double            criticalEnergyRef { 800*MeV };
+      double            criticalEnergy    { 800*MeV };
+    };
+    
+    /// Declare optional properties from embedded structure
+    template <> 
+    void Geant4FSShowerModel<par01_em_model>::initialize()     {
+      declareProperty("Material",       this->locals.materialName);
+      declareProperty("CriticalEnergy", this->locals.criticalEnergyRef);
+      this->m_applicablePartNames.emplace_back("e+");
+      this->m_applicablePartNames.emplace_back("e-");
+    }
+
+    /// Sensitive detector construction callback. Called at "ConstructSDandField()"
+    template <>
+    void Geant4FSShowerModel<par01_em_model>::constructSensitives(Geant4DetectorConstructionContext* ctxt)   {
+      locals.material       = this->getMaterial(this->locals.materialName);
+      locals.criticalEnergy = this->locals.criticalEnergyRef * (this->locals.material->GetZ() + 1.2);
+      this->Geant4FastSimShowerModel::constructSensitives(ctxt);
+    }
+
+    /// User callback to model the particle/energy shower
+    template <> 
+    void Geant4FSShowerModel<par01_em_model>::modelShower(const G4FastTrack& track, G4FastStep& step)   {
+      auto* primary = track.GetPrimaryTrack();
+      // Kill the parameterised particle:
+      this->killParticle(step, primary->GetKineticEnergy(), 0e0);
+      //-----------------------------------------------------
+      // split into "energy spots" energy according to the shower shape:
+      // See Par01EMShowerModel::Explode(track);
+      //-----------------------------------------------------
+      G4FastHit hit;
+      Geant4FastSimSpot spot(&hit, &track);
+
+      // Reduced quantities:   -- critical energy in material:
+      G4double Ec      = this->locals.criticalEnergy;
+      G4double Energy  = spot.kineticEnergy();
+      G4double y       = Energy/Ec;
+      // compute value of parameter "a" of longitudinal profile, b assumed = 0.5
+      G4double b = 0.5, C = -0.5;
+      if (spot.trackDefinition() == G4Gamma::GammaDefinition()) C = 0.5;
+      G4double tmax    = 1.0 * (std::log(y) + C);
+      G4double a       = 1.0 + b*tmax;
+      // radiation length
+      G4double X0      = this->locals.material->GetRadlen();
+      // Moliere radius:
+      G4double Es      = 21*MeV;
+      G4double Rm      = X0*Es/Ec;
+      // We shoot 100 spots of energy:
+      G4int    nSpots  = 100;
+      G4double deposit = Energy/double(nSpots);
+
+      // axis of the shower, in global reference frame:
+      G4ThreeVector xShower, yShower, zShower;
+      zShower = spot.particleLocalDirection();
+      xShower = zShower.orthogonal();
+      yShower = zShower.cross(xShower);
+      // starting point of the shower:
+      G4ThreeVector sShower = spot.particleLocalPosition();
+      for (int i = 0; i < nSpots; i++)    {
+	// Longitudinal profile: -- shoot z according to Gamma distribution:
+	G4double bt  = G4RandGamma::shoot(a,1.0);
+	G4double t   = bt/b;                       // t : reduced quantity = z/X0:
+	G4double z   = t*X0;
+	// transverse profile: we set 90% of energy in one Rm, the rest between 1 and 3.5 Rm:
+	G4double xr  = G4UniformRand();
+	G4double phi = G4UniformRand()*twopi;
+	G4double r;
+	if (xr < 0.9) r = xr/0.9*Rm;
+	else r = ((xr - 0.9)/0.1*2.5 + 1.0)*Rm;
+	// build the position:
+	G4ThreeVector position = sShower + z*zShower + r*std::cos(phi)*xShower + r*std::sin(phi)*yShower;
+	/// Process spot and call sensitive detector
+	hit.SetPosition(position);
+	hit.SetEnergy(deposit);
+	this->locals.hitMaker.make(hit, track);
+      }
+    }
+
+    ///===================================================================================================
+    ///
+    ///  Par01 Pion shower model (pi+, pi-)
+    ///
+    ///===================================================================================================
+    
+    /// Configuration structure for the fast simulation shower model Geant4FSShowerModel<par01_pion_model>
+    class par01_pion_model  {
+    public:
+      G4FastSimHitMaker hitMaker { };
+    };
+    
+    /// Declare optional properties from embedded structure
+    template <> 
+    void Geant4FSShowerModel<par01_pion_model>::initialize()     {
+      this->m_applicablePartNames.emplace_back("pi+");
+      this->m_applicablePartNames.emplace_back("pi-");
+    }
+
+    /// User callback to determine if the shower creation should be triggered
+    template <> 
+    bool Geant4FSShowerModel<par01_pion_model>::check_trigger(const G4FastTrack& /* track */)   {
+      return true;
+    }
+
+    /// User callback to model the particle/energy shower
+    template <> 
+    void Geant4FSShowerModel<par01_pion_model>::modelShower(const G4FastTrack& track, G4FastStep& step)   {
+      auto* primary = track.GetPrimaryTrack();
+      // Kill the parameterised particle:
+      this->killParticle(step, primary->GetKineticEnergy(), 0e0);
+
+      //-----------------------------------------------------
+      // Non-physical shower generated: exp along z and transverse.
+      //-----------------------------------------------------
+      // center of the shower, we put at the middle of the ghost:
+      G4ThreeVector pos = track.GetPrimaryTrackLocalPosition();
+      G4ThreeVector dir = track.GetPrimaryTrackLocalDirection();
+      G4double      distOut = track.GetEnvelopeSolid()->DistanceToOut(pos, dir);
+      G4ThreeVector showerCenter = pos + (distOut/2.)*dir;
+
+      showerCenter = track.GetInverseAffineTransformation()->TransformPoint(showerCenter);
+
+      // axis of the shower, in global reference frame:
+      G4ThreeVector zShower = primary->GetMomentumDirection();
+      G4ThreeVector xShower = zShower.orthogonal();
+      G4ThreeVector yShower = zShower.cross(xShower);
+
+      // shoot the energy spots:
+      G4double      Energy  = primary->GetKineticEnergy();
+      G4int         nSpot   = 50;
+      G4double      deposit = Energy/double(nSpot);
+
+      for (int i = 0; i < nSpot; i++)  {
+	double z   = G4RandGauss::shoot(0,20*cm);
+	double r   = G4RandGauss::shoot(0,10*cm);
+	double phi = G4UniformRand()*twopi;
+	G4ThreeVector position = showerCenter + z*zShower + r*std::cos(phi)*xShower + r*std::sin(phi)*yShower;
+	/// Process spot and call sensitive detector
+	G4FastHit hit(position, deposit);
+	this->locals.hitMaker.make(hit, track);
+      }
+    }
+
+    typedef Geant4FSShowerModel<par01_em_model>   Geant4Par01EMShowerModel;
+    typedef Geant4FSShowerModel<par01_pion_model> Geant4Par01PionShowerModel;
+  }
+}
+
+#include <DDG4/Factories.h>
+DECLARE_GEANT4ACTION_NS(dd4hep::sim,Geant4Par01EMShowerModel)
+DECLARE_GEANT4ACTION_NS(dd4hep::sim,Geant4Par01PionShowerModel)
diff --git a/DDG4/plugins/Geant4SDActions.cpp b/DDG4/plugins/Geant4SDActions.cpp
index f4951a86e..b87c0cd21 100644
--- a/DDG4/plugins/Geant4SDActions.cpp
+++ b/DDG4/plugins/Geant4SDActions.cpp
@@ -13,7 +13,7 @@
 
 // Framework include files
 #include "DDG4/Geant4SensDetAction.inl"
-#include "DDG4/Geant4GFlashSpotHandler.h"
+#include "DDG4/Geant4FastSimHandler.h"
 #include "DDG4/Geant4EventAction.h"
 #include "G4OpticalPhoton.hh"
 #include "G4VProcess.hh"
@@ -46,17 +46,17 @@ namespace dd4hep {
       m_collectionID = -1;
     }
 
-    /// Method for generating hit(s) using the information of G4Step object.
+    /// G4VSensitiveDetector interface: Method for generating hit(s) using the information of G4Step object.
     template <> bool
-    Geant4SensitiveAction<Geant4VoidSensitive>::process(G4Step*             /* step */,
+    Geant4SensitiveAction<Geant4VoidSensitive>::process(const G4Step*       /* step */,
 							G4TouchableHistory* /* hist */) {
       return true;
     }
     
-    /// Method for generating hit(s) using the information of G4Step object.
+    /// GFLASH/FastSim interface: Method for generating hit(s) using the information of G4Step object.
     template <> bool
-    Geant4SensitiveAction<Geant4VoidSensitive>::processGFlash(G4GFlashSpot*       /* spot */,
-							      G4TouchableHistory* /* hist */) {
+    Geant4SensitiveAction<Geant4VoidSensitive>::processFastSim(const Geant4FastSimSpot* /* spot */,
+							       G4TouchableHistory*      /* hist */) {
       return true;
     }
     typedef Geant4SensitiveAction<Geant4VoidSensitive> Geant4VoidSensitiveAction;
@@ -80,7 +80,7 @@ namespace dd4hep {
 
     /// Method for generating hit(s) using the information of G4Step object.
     template <> bool
-    Geant4SensitiveAction<Geant4Tracker>::process(G4Step* step,G4TouchableHistory* /* hist */) {
+    Geant4SensitiveAction<Geant4Tracker>::process(const G4Step* step,G4TouchableHistory* /* hist */) {
       typedef Geant4Tracker::Hit Hit;
       Geant4StepHandler h(step);
       Position prePos    = h.prePos();
@@ -104,7 +104,7 @@ namespace dd4hep {
       collection(m_collectionID)->add(hit);
       mark(h.track);
       if ( 0 == hit->cellID )  {
-        hit->cellID      = volumeID( step ) ;
+        hit->cellID      = volumeID(step);
         except("+++ Invalid CELL ID for hit!");
       }
       print("Hit with deposit:%f  Pos:%f %f %f ID=%016X",
@@ -115,23 +115,23 @@ namespace dd4hep {
       return true;
     }
     
-    /// Method for generating hit(s) using the information of G4Step object.
+    /// GFlash/FastSim interface: Method for generating hit(s) using the information of Geant4FastSimSpot object.
     template <> bool
-    Geant4SensitiveAction<Geant4Tracker>::processGFlash(G4GFlashSpot*          spot,
-							G4TouchableHistory* /* hist */)
+    Geant4SensitiveAction<Geant4Tracker>::processFastSim(const Geant4FastSimSpot* spot,
+							 G4TouchableHistory* /* hist */)
     {
       typedef Geant4Tracker::Hit Hit;
-      Geant4GFlashSpotHandler h(spot);
+      Geant4FastSimHandler h(spot);
       Hit* hit = new Hit(h.trkID(), h.trkPdgID(), h.deposit(), h.track->GetGlobalTime());
-      hit->cellID        = cellID(spot);
+      hit->cellID        = cellID(h.touchable(), h.avgPositionG4());
       hit->energyDeposit = h.deposit();
-      hit->position      = h.position();
+      hit->position      = h.avgPosition();
       hit->momentum      = h.momentum();
       hit->length        = 0e0;
       collection(m_collectionID)->add(hit);
       mark(h.track);
       if ( 0 == hit->cellID )  {
-        hit->cellID      = volumeID( spot ) ;
+        hit->cellID      = volumeID(h.touchable());
         except("+++ Invalid CELL ID for hit!");
       }
       print("Hit with deposit:%f  Pos:%f %f %f ID=%016X",
@@ -140,6 +140,7 @@ namespace dd4hep {
       print("    Geant4 path:%s",handler.path().c_str());
       return true;
     }
+
     typedef Geant4SensitiveAction<Geant4Tracker> Geant4TrackerAction;
 
     // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@@ -162,7 +163,7 @@ namespace dd4hep {
 
     /// Method for generating hit(s) using the information of G4Step object.
     template <> bool
-    Geant4SensitiveAction<Geant4Calorimeter>::process(G4Step* step,G4TouchableHistory*) {
+    Geant4SensitiveAction<Geant4Calorimeter>::process(const G4Step* step,G4TouchableHistory*) {
       typedef Geant4Calorimeter::Hit Hit;
       Geant4StepHandler    h(step);
       HitContribution      contrib = Hit::extractContribution(step);
@@ -209,24 +210,24 @@ namespace dd4hep {
       mark(h.track);
       return true;
     }
-    /// Method for generating hit(s) using the information of the G4GFlashSpot object.
+    /// GFlash/FastSim interface: Method for generating hit(s) using the information of Geant4FastSimSpot object.
     template <> bool
-    Geant4SensitiveAction<Geant4Calorimeter>::processGFlash(G4GFlashSpot* spot,
-							    G4TouchableHistory* /*hist*/ )
+    Geant4SensitiveAction<Geant4Calorimeter>::processFastSim(const Geant4FastSimSpot* spot,
+							     G4TouchableHistory* /* hist */)
     {
       typedef Geant4Calorimeter::Hit Hit;
-      Geant4GFlashSpotHandler h(spot);
-      HitContribution         contrib = Hit::extractContribution(spot);
-      Geant4HitCollection*    coll    = collection(m_collectionID);
+      Geant4FastSimHandler h(spot);
+      HitContribution      contrib = Hit::extractContribution(spot);
+      Geant4HitCollection* coll    = collection(m_collectionID);
       VolumeID cell = 0;
       
       try {
-        cell = cellID(spot);
+        cell = cellID(h.touchable(), h.avgPositionG4());
       } catch(std::runtime_error &e) {
         std::stringstream out;
         out << std::setprecision(20) << std::scientific;
         out << "ERROR: " << e.what()  << std::endl;
-        out << "Position: (" << std::setw(24) << h.positionG4() << ") " << std::endl;
+        out << "Position: (" << std::setw(24) << h.avgPositionG4() << ") " << std::endl;
         out << "Momentum: (" << std::setw(24) << h.momentumG4() << ") " << std::endl;
         std::cout << out.str();
         return true;
@@ -243,7 +244,7 @@ namespace dd4hep {
                 c_name(),contrib.deposit,pos.X,pos.Y,pos.Z,handler.path().c_str(),
                 coll->GetName().c_str());
         if ( 0 == hit->cellID )  { // for debugging only!
-          hit->cellID = cellID(spot);
+          hit->cellID = cellID(h.touchable(), h.avgPositionG4());
           except("+++ Invalid CELL ID for hit!");
         }
       }
@@ -252,6 +253,7 @@ namespace dd4hep {
       mark(h.track);
       return true;
     }
+
     typedef Geant4SensitiveAction<Geant4Calorimeter> Geant4CalorimeterAction;
 
     // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@@ -279,7 +281,7 @@ namespace dd4hep {
     }
     /// Method for generating hit(s) using the information of G4Step object.
     template <> bool
-    Geant4SensitiveAction<Geant4OpticalCalorimeter>::process(G4Step* step,G4TouchableHistory*) {
+    Geant4SensitiveAction<Geant4OpticalCalorimeter>::process(const G4Step* step,G4TouchableHistory*) {
       G4Track * track =  step->GetTrack();
       // check that particle is optical photon:
       if( track->GetDefinition() != G4OpticalPhoton::OpticalPhotonDefinition() )  {
@@ -312,13 +314,14 @@ namespace dd4hep {
         return true;
       }
     }
-    /// Method for generating hit(s) using the information of the G4GFlashSpot object.
+
+    /// GFlash/FastSim interface: Method for generating hit(s) using the information of Geant4FastSimSpot object.
     template <> bool
-    Geant4SensitiveAction<Geant4OpticalCalorimeter>::processGFlash(G4GFlashSpot* spot,
-								   G4TouchableHistory* /*hist*/ )
+    Geant4SensitiveAction<Geant4OpticalCalorimeter>::processFastSim(const Geant4FastSimSpot* spot,
+								    G4TouchableHistory* /* hist */)
     {
       typedef Geant4Calorimeter::Hit Hit;
-      Geant4GFlashSpotHandler h(spot);
+      Geant4FastSimHandler   h(spot);
       const G4Track* track = h.track;
       if( track->GetDefinition() != G4OpticalPhoton::OpticalPhotonDefinition() )  {
         return false;
@@ -329,14 +332,14 @@ namespace dd4hep {
       else {
         Geant4HitCollection* coll = collection(m_collectionID);
         HitContribution   contrib = Hit::extractContribution(spot);
-        Position          pos     = h.position();
+        Position          pos     = h.avgPosition();
         Hit* hit = coll->find<Hit>(PositionCompare<Hit,Position>(pos));
         if ( !hit ) {
           hit = new Hit(pos);
-          hit->cellID = volumeID(spot);
+          hit->cellID = volumeID(h.touchable());
           coll->add(hit);
           if ( 0 == hit->cellID )  {
-            hit->cellID = volumeID(spot);
+            hit->cellID = volumeID(h.touchable());
             except("+++ Invalid CELL ID for hit!");
           }
         }
@@ -374,7 +377,7 @@ namespace dd4hep {
     }
     /// Method for generating hit(s) using the information of G4Step object.
     template <> bool
-    Geant4SensitiveAction<Geant4ScintillatorCalorimeter>::process(G4Step* step,G4TouchableHistory*) {
+    Geant4SensitiveAction<Geant4ScintillatorCalorimeter>::process(const G4Step* step,G4TouchableHistory*) {
       typedef Geant4Calorimeter::Hit Hit;
       Geant4StepHandler    h(step);
       HitContribution      contrib = Hit::extractContribution(step,true);
@@ -417,24 +420,25 @@ namespace dd4hep {
       mark(h.track);
       return true;
     }
-    /// Method for generating hit(s) using the information of the G4GFlashSpot object.
+
+    /// GFlash/FastSim interface: Method for generating hit(s) using the information of Geant4FastSimSpot object.
     template <> bool
-    Geant4SensitiveAction<Geant4ScintillatorCalorimeter>::processGFlash(G4GFlashSpot* spot,
-									G4TouchableHistory* /*hist*/ )
+    Geant4SensitiveAction<Geant4ScintillatorCalorimeter>::processFastSim(const Geant4FastSimSpot* spot,
+									 G4TouchableHistory* /* hist */)
     {
       typedef Geant4Calorimeter::Hit Hit;
-      Geant4GFlashSpotHandler h(spot);
+      Geant4FastSimHandler h(spot);
       HitContribution         contrib = Hit::extractContribution(spot);
       Geant4HitCollection*    coll    = collection(m_collectionID);
       VolumeID cell = 0;
       
       try {
-        cell = cellID(spot);
+        cell = cellID(h.touchable(), h.avgPositionG4());
       } catch(std::runtime_error &e) {
         std::stringstream out;
         out << std::setprecision(20) << std::scientific;
         out << "ERROR: " << e.what()  << std::endl;
-        out << "Position: (" << std::setw(24) << h.positionG4() << ") " << std::endl;
+        out << "Position: (" << std::setw(24) << h.avgPositionG4() << ") " << std::endl;
         out << "Momentum: (" << std::setw(24) << h.momentumG4() << ") " << std::endl;
         std::cout << out.str();
         return true;
@@ -450,7 +454,7 @@ namespace dd4hep {
         printM2("CREATE hit with deposit:%e MeV  Pos:%8.2f %8.2f %8.2f  %s",
                 contrib.deposit,pos.X,pos.Y,pos.Z,handler.path().c_str());
         if ( 0 == hit->cellID )  { // for debugging only!
-          hit->cellID = cellID(spot);
+          hit->cellID = cellID(h.touchable(), h.avgPositionG4());
           except("+++ Invalid CELL ID for hit!");
         }
       }
@@ -459,6 +463,7 @@ namespace dd4hep {
       mark(h.track);
       return true;
     }
+
     typedef Geant4SensitiveAction<Geant4ScintillatorCalorimeter> Geant4ScintillatorCalorimeterAction;
 
     /**
@@ -508,41 +513,40 @@ namespace dd4hep {
         combined = 0;
         cell = 0;
       }
-      void start(G4Step* step, G4StepPoint* point)   {
+      void start(const G4Step* step, const G4StepPoint* point)   {
         pre.storePoint(step,point);
 	start_collecting(step->GetTrack());
 	firstSpotVolume = step->GetPreStepPoint()->GetTouchableHandle()->GetVolume();
       }
-      void start(G4GFlashSpot* spot)   {
-	const G4Track* track = spot->GetOriginatorTrack()->GetPrimaryTrack();
+      void start(const Geant4FastSimSpot* spot)   {
         pre.storePoint(spot);
-	start_collecting(track);
-	firstSpotVolume = spot->GetTouchableHandle()->GetVolume();
+	start_collecting(spot->primary);
+	firstSpotVolume = spot->volume();
       }
 
       /// Update energy and track information during hit info accumulation
-      template <typename T> inline void update_collected_hit(const T* step)    {
+      void update_collected_hit(const G4VTouchable* h, G4ThreeVector&& global)    {
         pre.truth.deposit += post.truth.deposit;
         mean_pos.SetX(mean_pos.x()+post.position.x()*post.truth.deposit);
         mean_pos.SetY(mean_pos.y()+post.position.y()*post.truth.deposit);
         mean_pos.SetZ(mean_pos.z()+post.position.z()*post.truth.deposit);
         mean_time += post.truth.time*post.truth.deposit;
         if ( 0 == cell )   {
-          cell = sensitive->cellID(step);
+          cell = sensitive->cellID(h, global);
           if ( 0 == cell )  {
-            cell = sensitive->volumeID(step) ;
+            cell = sensitive->volumeID(h) ;
             sensitive->except("+++ Invalid CELL ID for hit!");
           }
         }
         ++combined;
       }
-      void update(G4Step* step) {
-        post.storePoint(step,step->GetPostStepPoint());
-	update_collected_hit(step);
+      void update(const Geant4StepHandler& h) {
+        post.storePoint(h.step, h.post);
+	update_collected_hit(h.preTouchable(), std::move(h.avgPositionG4())); // Compute cellID
       }
-      void update(G4GFlashSpot* spot)   {
-        post.storePoint(spot);
-	update_collected_hit(spot);
+      void update(const Geant4FastSimHandler& h)   {
+        post.storePoint(h.spot);
+	update_collected_hit(h.touchable(), std::move(h.avgPositionG4()));       // Compute cellID
       }
 
       /// Clear collected information and restart for new hit
@@ -589,7 +593,7 @@ namespace dd4hep {
 
 
       /// Method for generating hit(s) using the information of G4Step object.
-      G4bool process(G4Step* step, G4TouchableHistory* ) {
+      G4bool process(const G4Step* step, G4TouchableHistory* ) {
         Geant4StepHandler h(step);
 
 	// std::cout << " process called - pre pos: " << h.prePos() << " post pos " << h.postPos() 
@@ -607,7 +611,7 @@ namespace dd4hep {
           start(step, h.pre);
         }
         /// ....update .....
-        update(step);
+        update(h);
 
         if ( prePV != postPV ) {
           void* postSD = h.sd(h.post);
@@ -625,9 +629,9 @@ namespace dd4hep {
         return true;
       }
 
-      /// Method for generating hit(s) using the information of G4Step object.
-      G4bool process(G4GFlashSpot* spot, G4TouchableHistory* ) {
-	Geant4GFlashSpotHandler h(spot);
+      /// Method for generating hit(s) using the information of fast simulation spot object.
+      G4bool process(const Geant4FastSimSpot* spot, G4TouchableHistory* ) {
+	Geant4FastSimHandler h(spot);
         G4VPhysicalVolume*   prePV = firstSpotVolume, *postPV = h.volume();
         Geant4HitCollection* coll  = sensitive->collection(0);
         /// If we are handling a new track, then store the content of the previous one.
@@ -639,7 +643,7 @@ namespace dd4hep {
           start(spot);
         }
         /// ....update .....
-        update(spot);
+        update(h);
 
         if ( firstSpotVolume && prePV != postPV )   {
           void* postSD = h.sd();
@@ -691,17 +695,18 @@ namespace dd4hep {
 
     /// Method for generating hit(s) using the information of G4Step object.
     template <> G4bool
-    Geant4SensitiveAction<TrackerCombine>::process(G4Step* step, G4TouchableHistory* history) {
+    Geant4SensitiveAction<TrackerCombine>::process(const G4Step* step, G4TouchableHistory* history) {
       return m_userData.process(step, history);
     }
-    /// Method for generating hit(s) using the information of the G4GFlashSpot object.
+
+    /// GFlash/FastSim interface: Method for generating hit(s) using the information of Geant4FastSimSpot object.
     template <> bool
-    Geant4SensitiveAction<TrackerCombine>::processGFlash(G4GFlashSpot* spot,G4TouchableHistory* history) {
+    Geant4SensitiveAction<TrackerCombine>::processFastSim(const Geant4FastSimSpot* spot,
+							  G4TouchableHistory*      history)    {
       return m_userData.process(spot, history);
     }
 
     typedef Geant4SensitiveAction<TrackerCombine>  Geant4TrackerCombineAction;
-
     typedef Geant4TrackerAction                    Geant4SimpleTrackerAction;
     typedef Geant4CalorimeterAction                Geant4SimpleCalorimeterAction;
     typedef Geant4OpticalCalorimeterAction         Geant4SimpleOpticalCalorimeterAction;
diff --git a/DDG4/plugins/Geant4SensDet.cpp b/DDG4/plugins/Geant4SensDet.cpp
index 4e8a9221b..5009b9601 100644
--- a/DDG4/plugins/Geant4SensDet.cpp
+++ b/DDG4/plugins/Geant4SensDet.cpp
@@ -18,12 +18,15 @@
 
 #include <DDG4/Geant4Kernel.h>
 #include <DDG4/Geant4Context.h>
+#include <DDG4/Geant4FastSimSpot.h>
 #include <DDG4/Geant4HitCollection.h>
 #include <DDG4/Geant4SensDetAction.h>
 
 // Geant4 include files
+#include <G4TouchableHistory.hh>
 #include <G4VSensitiveDetector.hh>
 #include <G4VGFlashSensitiveDetector.hh>
+#include <G4VFastSimSensitiveDetector.hh>
 #include <G4Event.hh>
 #include <G4Run.hh>
 
@@ -67,6 +70,7 @@ namespace dd4hep {
      */
     class Geant4SensDet : virtual public G4VSensitiveDetector,
 			  virtual public G4VGFlashSensitiveDetector,
+			  virtual public G4VFastSimSensitiveDetector,
                           virtual public G4VSDFilter,
                           virtual public Geant4ActionSD,
                           virtual public RefCountedSequence<Geant4SensDetActionSequence>
@@ -79,6 +83,7 @@ namespace dd4hep {
       Geant4SensDet(const std::string& nam, Detector& description)
         : G4VSensitiveDetector(nam),
 	  G4VGFlashSensitiveDetector(),
+	  G4VFastSimSensitiveDetector(),
 	  G4VSDFilter(nam),
           Geant4Action(0,nam),
 	  Geant4ActionSD(nam),
@@ -98,44 +103,59 @@ namespace dd4hep {
       /// Destructor
       virtual ~Geant4SensDet() = default;
       /// Overload to avoid ambiguity between G4VSensitiveDetector and G4VSDFilter
-      inline G4String GetName() const  
+      inline G4String GetName() const
       {  return this->G4VSensitiveDetector::SensitiveDetectorName;      }
       /// G4VSensitiveDetector internals: Access to the detector path name
-      virtual std::string path()  const  override
+      virtual std::string path()  const  override  final
       {  return this->G4VSensitiveDetector::GetPathName();              }
       /// G4VSensitiveDetector internals: Access to the detector path name
-      virtual std::string fullPath()  const  override
+      virtual std::string fullPath()  const  override  final
       {  return this->G4VSensitiveDetector::GetFullPathName();          }
       /// Is the detector active?
       virtual bool isActive() const  override
       {  return this->G4VSensitiveDetector::isActive();                 }
       /// This is a utility method which returns the hits collection ID
-      virtual G4int GetCollectionID(G4int i)  override
+      virtual G4int GetCollectionID(G4int i)  override  final
       {  return this->G4VSensitiveDetector::GetCollectionID(i);         }
       /// Access to the readout geometry of the sensitive detector
       virtual G4VReadOutGeometry* readoutGeometry() const  override
       {  return this->G4VSensitiveDetector::GetROgeometry();            }
       /// Access to the Detector sensitive detector handle
-      virtual SensitiveDetector sensitiveDetector() const  override
+      virtual SensitiveDetector sensitiveDetector() const  override  final
       {  return m_sensitive;                                            }
       /// Access to the sensitive type of the detector
-      virtual const std::string& sensitiveType() const  override
+      virtual const std::string& sensitiveType() const  override  final
       {  return m_sequence->sensitiveType();                            }
       /// Callback if the sequence should be accepted or filtered off
-      virtual G4bool Accept(const G4Step* step) const  override
+      virtual G4bool Accept(const G4Step* step) const  override  final
       {  return m_sequence->accept(step);                               }
       /// Method invoked at the begining of each event.
-      virtual void Initialize(G4HCofThisEvent* hce)  override
+      virtual void Initialize(G4HCofThisEvent* hce)  override  final
       {  m_sequence->begin(hce);                                        }
       /// Method invoked at the end of each event.
-      virtual void EndOfEvent(G4HCofThisEvent* hce)  override
+      virtual void EndOfEvent(G4HCofThisEvent* hce)  override  final
       {  m_sequence->end(hce);                                          }
       /// Method for generating hit(s) using the information of G4Step object.
-      virtual G4bool ProcessHits(G4Step* step, G4TouchableHistory* hist) override
+      virtual G4bool ProcessHits(G4Step* step,
+				 G4TouchableHistory* hist)   override  final
       {  return m_sequence->process(step,hist);                         }
       /// GFLASH interface
-      virtual G4bool ProcessHits(G4GFlashSpot* spot, G4TouchableHistory* hist) override
-      {  return m_sequence->processGFlash(spot,hist);                   }
+      virtual G4bool ProcessHits(G4GFlashSpot* sp,
+				 G4TouchableHistory* hist)   override final
+      {
+	const GFlashEnergySpot* esp = sp->GetEnergySpot();
+	G4FastHit         hit(esp->GetPosition(), esp->GetEnergy());
+	Geant4FastSimSpot spot(&hit, sp->GetOriginatorTrack(), (sp->GetTouchableHandle())());
+	return m_sequence->processFastSim(&spot, hist);
+      }
+      /// Geant4 Fast simulation interface
+      virtual G4bool ProcessHits(const G4FastHit* hit,
+				 const G4FastTrack* track,
+				 G4TouchableHistory* hist)   override final
+      {
+	Geant4FastSimSpot spot(hit, track, hist);
+	return m_sequence->processFastSim(&spot, hist);
+      }
       /// G4VSensitiveDetector interface: Method invoked if the event was aborted.
       virtual void clear()  override
       {  m_sequence->clear();                                           }
diff --git a/DDG4/plugins/Geant4SensDetFilters.cpp b/DDG4/plugins/Geant4SensDetFilters.cpp
index 07b30699a..96bf2b7b4 100644
--- a/DDG4/plugins/Geant4SensDetFilters.cpp
+++ b/DDG4/plugins/Geant4SensDetFilters.cpp
@@ -16,7 +16,7 @@
 
 /// Geant4 include files
 #include "G4GFlashSpot.hh"
-
+#include "G4FastHit.hh"
 
 /// Forward declarations
 class G4ParticleDefinition;
@@ -58,6 +58,10 @@ namespace dd4hep {
       const G4Track* getTrack(const G4GFlashSpot* spot)   const   {
 	return spot->GetOriginatorTrack()->GetPrimaryTrack();
       }
+      /// Access originator track from G4 fast track
+      const G4Track* getTrack(const G4FastTrack* fast)   const   {
+	return fast->GetPrimaryTrack();
+      }
     };
 
     /// Geant4 sensitive detector filter implementing a particle rejector
@@ -79,6 +83,10 @@ namespace dd4hep {
       virtual bool operator()(const G4GFlashSpot* spot) const  final   {
 	return !isSameType(getTrack(spot));
       }
+      /// Fast Simulation interface: Filter action. Return true if hits should be processed.
+      virtual bool operator()(const G4FastHit*, const G4FastTrack* track) const  final  {
+	return !isSameType(getTrack(track));
+      }
     };
 
     /// Geant4 sensitive detector filter implementing a particle selector
@@ -100,6 +108,10 @@ namespace dd4hep {
       virtual bool operator()(const G4GFlashSpot* spot) const  final   {
 	return isSameType(getTrack(spot));
       }
+      /// Fast Simulation interface: Filter action. Return true if hits should be processed.
+      virtual bool operator()(const G4FastHit*, const G4FastTrack* track) const  final {
+	return isSameType(getTrack(track));
+      }
     };
 
     /// Geant4 sensitive detector filter implementing a Geantino rejector
@@ -121,6 +133,10 @@ namespace dd4hep {
       virtual bool operator()(const G4GFlashSpot* spot) const  final   {
 	return !isGeantino(getTrack(spot));
       }
+      /// Fast Simulation interface: Filter action. Return true if hits should be processed.
+      virtual bool operator()(const G4FastHit*, const G4FastTrack* track) const  final  {
+	return !isGeantino(getTrack(track));
+      }
     };
 
     /// Geant4 sensitive detector filter implementing an energy cut.
@@ -145,6 +161,10 @@ namespace dd4hep {
       virtual bool operator()(const G4GFlashSpot* spot) const  final  {
 	return spot->GetEnergySpot()->GetEnergy() > m_energyCut;
       }
+      /// Fast Simulation interface: Filter action. Return true if hits should be processed.
+      virtual bool operator()(const G4FastHit* hit, const G4FastTrack*) const  final  {
+	return hit->GetEnergy() > m_energyCut;
+      }
     };
   }
 }
diff --git a/DDG4/plugins/Geant4TrackerWeightedSD.cpp b/DDG4/plugins/Geant4TrackerWeightedSD.cpp
index 8ee19a474..058dc097d 100644
--- a/DDG4/plugins/Geant4TrackerWeightedSD.cpp
+++ b/DDG4/plugins/Geant4TrackerWeightedSD.cpp
@@ -428,8 +428,8 @@ namespace dd4hep {
       }
 
       /// GFLash processing callback
-      G4bool process(G4GFlashSpot* , G4TouchableHistory* ) {
-        sensitive->except("GFlash action is not implemented for SD: %s", sensitive->c_name());
+      G4bool process(const Geant4FastSimSpot* , G4TouchableHistory* ) {
+        sensitive->except("GFlash/FastSim action is not implemented for SD: %s", sensitive->c_name());
         return false;
       }
     };
@@ -464,9 +464,15 @@ namespace dd4hep {
 
     /// Method for generating hit(s) using the information of G4Step object.
     template <> G4bool
-    Geant4SensitiveAction<TrackerWeighted>::process(G4Step* step, G4TouchableHistory* history) {
+    Geant4SensitiveAction<TrackerWeighted>::process(const G4Step* step, G4TouchableHistory* history) {
       return m_userData.process(step, history);
     }
+
+    /// Method for generating hit(s) using the information of the Geant4FastSimSpot object.
+    template <> bool
+    Geant4SensitiveAction<TrackerWeighted>::processFastSim(const Geant4FastSimSpot* spot, G4TouchableHistory* history) {
+      return m_userData.process(spot, history);
+    }
     typedef Geant4SensitiveAction<TrackerWeighted>  Geant4TrackerWeightedAction;
   }
 }
diff --git a/DDG4/src/Geant4Data.cpp b/DDG4/src/Geant4Data.cpp
index aa828acf9..0760c94e5 100644
--- a/DDG4/src/Geant4Data.cpp
+++ b/DDG4/src/Geant4Data.cpp
@@ -12,16 +12,17 @@
 //==========================================================================
 
 // Framework include files
-#include "DD4hep/Printout.h"
-#include "DD4hep/InstanceCount.h"
-#include "DDG4/Geant4Data.h"
-#include "DDG4/Geant4StepHandler.h"
-#include "DDG4/Geant4GFlashSpotHandler.h"
+#include <DD4hep/Printout.h>
+#include <DD4hep/InstanceCount.h>
+
+#include <DDG4/Geant4Data.h>
+#include <DDG4/Geant4StepHandler.h>
+#include <DDG4/Geant4FastSimHandler.h>
 
 // Geant4 include files
-#include "G4Step.hh"
-#include "G4Allocator.hh"
-#include "G4OpticalPhoton.hh"
+#include <G4Step.hh>
+#include <G4Allocator.hh>
+#include <G4OpticalPhoton.hh>
 
 using namespace std;
 using namespace dd4hep;
@@ -91,11 +92,11 @@ Geant4HitData::Contribution Geant4HitData::extractContribution(const G4Step* ste
   return contrib;
 }
 
-/// Extract the MC contribution for a given hit from the GFlash spot information
-Geant4HitData::Contribution Geant4HitData::extractContribution(const G4GFlashSpot* spot) {
-  Geant4GFlashSpotHandler h(spot);
-  G4ThreeVector           p = h.positionG4();
-  double                  position[3] = {p.x(), p.y(), p.z()};
+/// Extract the MC contribution for a given hit from the fast simulation spot information
+Geant4HitData::Contribution Geant4HitData::extractContribution(const Geant4FastSimSpot* spot) {
+  Geant4FastSimHandler h(spot);
+  G4ThreeVector        p = h.avgPositionG4();
+  double               position[3] = {p.x(), p.y(), p.z()};
   return Contribution(h.trkID(),h.trkPdgID(),h.energy(),h.trkTime(),0e0,position);
 }
 
@@ -153,21 +154,19 @@ Geant4Tracker::Hit& Geant4Tracker::Hit::storePoint(const G4Step* step, const G4S
 }
 
 /// Store Geant4 spot information into tracker hit structure.
-Geant4Tracker::Hit& Geant4Tracker::Hit::storePoint(const G4GFlashSpot* spot)   {
-  const GFlashEnergySpot* espot = spot->GetEnergySpot();
-  const G4FastTrack*   ftrk = spot->GetOriginatorTrack();
-  const G4Track* trk  = ftrk->GetPrimaryTrack();
-  G4ThreeVector  pos  = spot->GetPosition();
+Geant4Tracker::Hit& Geant4Tracker::Hit::storePoint(const Geant4FastSimSpot* spot)   {
+  const G4Track* trk  = spot->primary;
+  G4ThreeVector  pos  = spot->hitPosition();
   G4ThreeVector  mom  = trk->GetMomentum().unit();
-  double         dep  = espot->GetEnergy();
-  truth.trackID = trk->GetTrackID();
-  truth.pdgID   = trk->GetDefinition()->GetPDGEncoding();
-  truth.deposit = dep;
-  truth.time    = trk->GetGlobalTime();
-  energyDeposit = dep;
-  position.SetXYZ(pos.x(), pos.y(), pos.z());
-  momentum.SetXYZ(mom.x()*dep, mom.y()*dep, mom.z()*dep);
-  length = 0;
+  double         dep  = spot->hit->GetEnergy();
+  this->truth.deposit = dep;
+  this->truth.trackID = trk->GetTrackID();
+  this->truth.time    = trk->GetGlobalTime();
+  this->truth.pdgID   = trk->GetDefinition()->GetPDGEncoding();
+  this->energyDeposit = dep;
+  this->position.SetXYZ(pos.x(), pos.y(), pos.z());
+  this->momentum.SetXYZ(mom.x()*dep, mom.y()*dep, mom.z()*dep);
+  this->length = 0;
   return *this;
 }
 
diff --git a/DDG4/src/Geant4FastSimShowerModel.cpp b/DDG4/src/Geant4FastSimShowerModel.cpp
new file mode 100644
index 000000000..9aa4edf3e
--- /dev/null
+++ b/DDG4/src/Geant4FastSimShowerModel.cpp
@@ -0,0 +1,230 @@
+//==========================================================================
+//  AIDA Detector description implementation
+//--------------------------------------------------------------------------
+// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
+// All rights reserved.
+//
+// For the licensing terms see $DD4hepINSTALL/LICENSE.
+// For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
+//
+// Author     : M.Frank
+//
+//==========================================================================
+
+// Framework include files
+#include <DDG4/Geant4FastSimShowerModel.h>
+#include <DDG4/Geant4Mapping.h>
+#include <DDG4/Geant4Kernel.h>
+
+// Geant4 include files
+#include <G4FastSimulationManager.hh>
+#include <G4VFastSimulationModel.hh>
+#include <G4TouchableHandle.hh>
+#include <G4ParticleTable.hh>
+#include <G4FastStep.hh>
+
+// C/C++ include files
+#include <sstream>
+
+using namespace dd4hep;
+using namespace dd4hep::sim;
+
+/// Namespace for the AIDA detector description toolkit
+namespace dd4hep  {
+
+  /// Namespace for the Geant4 based simulation part of the AIDA detector description toolkit
+  namespace sim  {
+
+    /// Forward declaratons
+    class Geant4FastSimShowerModel;
+    
+    /// Geant4 wrapper for the Geant4 fast simulation shower model
+    /**
+     *  Geant4 wrapper for the Geant4 fast simulation shower model
+     *
+     *  \author  M.Frank
+     *  \version 1.0
+     *  \ingroup DD4HEP_SIMULATION
+     */
+    class Geant4ShowerModelWrapper : public G4VFastSimulationModel  {
+      /// Reference to the model wrapper
+      Geant4FastSimShowerModel* m_model { nullptr };
+
+    public:
+      /// Initializing constructor
+      Geant4ShowerModelWrapper(Geant4FastSimShowerModel* model);
+      /// Default destructor
+      virtual ~Geant4ShowerModelWrapper() = default;
+      /// User callback to determine if the model is applicable for the particle type
+      virtual G4bool IsApplicable(const G4ParticleDefinition& particle)  override;
+      /// User callback to determine if the shower creation should be triggered
+      virtual G4bool ModelTrigger(const G4FastTrack& track)  override;
+      /// User callback to model the particle/energy shower
+      virtual void DoIt(const G4FastTrack& track, G4FastStep& step)  override;
+    };
+    
+  }
+}
+
+/// Initializing constructor
+Geant4ShowerModelWrapper::Geant4ShowerModelWrapper(Geant4FastSimShowerModel* model)
+  : G4VFastSimulationModel(model->name()), m_model(model)
+{
+}
+
+/// User callback to determine if the model is applicable for the particle type
+G4bool Geant4ShowerModelWrapper::IsApplicable(const G4ParticleDefinition& particle)    {
+  return this->m_model->check_applicability(particle);
+}
+
+/// User callback to determine if the shower creation should be triggered
+G4bool Geant4ShowerModelWrapper::ModelTrigger(const G4FastTrack& track)   {
+  return this->m_model->check_trigger(track);
+}
+
+/// User callback to model the particle/energy shower
+void Geant4ShowerModelWrapper::DoIt(const G4FastTrack& track, G4FastStep& step)   {
+  this->m_model->modelShower(track, step);
+}
+
+/// Standard constructor
+Geant4FastSimShowerModel::Geant4FastSimShowerModel(Geant4Context* ctxt, const std::string& nam)
+  : Geant4DetectorConstruction(ctxt, nam)
+{
+  this->declareProperty("RegionName",          this->m_regionName);
+  this->declareProperty("ApplicableParticles", this->m_applicablePartNames);
+  this->declareProperty("Enable",              this->m_enable);
+  this->declareProperty("StepLength",          this->m_stepX0);
+  this->declareProperty("Emin",                this->m_eMin);
+  this->declareProperty("Emax",                this->m_eMax);
+  this->declareProperty("Ekill",               this->m_eKill);
+  this->declareProperty("Etrigger",            this->m_eTriggerNames);
+  this->m_wrapper.reset(new Geant4ShowerModelWrapper(this));
+}
+
+/// Default destructor
+Geant4FastSimShowerModel::~Geant4FastSimShowerModel()    {
+  detail::deletePtr(m_model);
+  m_wrapper.reset();
+}
+
+/// Access particle definition from string
+G4ParticleDefinition* Geant4FastSimShowerModel::getParticleDefinition(const std::string& particle)  const  {
+  G4ParticleTable* pt = G4ParticleTable::GetParticleTable();
+  G4ParticleDefinition* def = pt->FindParticle(particle);
+  if ( def ) return def;
+  except("Failed to access Geant4 particle definition: %s", particle.c_str());
+  return nullptr;
+}
+
+G4Material* Geant4FastSimShowerModel::getMaterial(const std::string& mat_name)   const   {
+  auto& kernel = this->context()->kernel();
+  Geant4GeometryInfo& mapping = Geant4Mapping::instance().data();
+  Material material = kernel.detectorDescription().material(mat_name);
+  if ( material.isValid() )   {
+    auto mat_iter = mapping.g4Materials.find(material);
+    if ( mat_iter != mapping.g4Materials.end() )   {
+      return (*mat_iter).second;
+    }
+  }
+  except("Failed to access shower parametrization material: %s", mat_name.c_str());
+  return nullptr;
+}
+
+/// Access the region from the detector description by name
+G4Region* Geant4FastSimShowerModel::getRegion(const std::string& nam)   const   {
+  auto& kernel = this->context()->kernel();
+  Geant4GeometryInfo& mapping = Geant4Mapping::instance().data();
+  Region rg = kernel.detectorDescription().region(nam);
+  if ( !rg.isValid() )   {
+    except("Failed to access the region %s from the detector description.", nam.c_str());
+  }
+  auto region_iter = mapping.g4Regions.find(rg);
+  if ( region_iter == mapping.g4Regions.end() )    {
+    except("Failed to locate G4Region: %s from the Geant4 mapping.", nam.c_str());
+  }
+  G4Region* region = (*region_iter).second;
+  if ( region )   {
+  }
+  return region;
+}
+
+/// Add shower model to region's fast simulation manager
+void Geant4FastSimShowerModel::addShowerModel(G4Region* region)     {
+  if ( !region )     {
+    except("Geant4FastSimShowerModel::addShowerModel: Invalid G4Region reference!");
+  }
+  // Retrieves the Fast Simulation Manage and add the model
+  G4FastSimulationManager* fastsimManager = region->GetFastSimulationManager();
+  if ( !fastsimManager )   {
+    fastsimManager = new G4FastSimulationManager(region, true);
+  }
+  // add this model to the Fast Simulation Manager.
+  if ( m_model )
+    fastsimManager->AddFastSimulationModel(m_model);
+  else if ( m_wrapper )
+    fastsimManager->AddFastSimulationModel(m_wrapper.get());
+  else
+    except("Geant4FastSimShowerModel::addShowerModel: Invalid shower model reference!");
+}
+
+/// Geometry construction callback. Called at "Construct()"
+void Geant4FastSimShowerModel::constructGeo(Geant4DetectorConstructionContext* /* ctxt */)    {
+  this->m_applicableParticles.clear();
+  for(const std::string& p : m_applicablePartNames)   {
+    G4ParticleDefinition* def = (p=="*") ? nullptr : this->getParticleDefinition(p);
+    this->m_applicableParticles.emplace(def);
+  }
+}
+
+/// Electromagnetic field construction callback. Called at "ConstructSDandField()"
+void Geant4FastSimShowerModel::constructField(Geant4DetectorConstructionContext* /* ctxt */)   {
+}
+
+/// Sensitive detector construction callback. Called at "ConstructSDandField()"
+void Geant4FastSimShowerModel::constructSensitives(Geant4DetectorConstructionContext* /* ctxt */)    {
+  G4Region* region = this->getRegion(this->m_regionName);
+  for(const auto& prop : this->m_eTriggerNames)    {
+    G4ParticleDefinition* def = this->getParticleDefinition(prop.first);
+    double val = dd4hep::_toDouble(prop.second) * dd4hep::GeV/CLHEP::GeV;
+    this->m_eTriggerCut.emplace(def, val);
+    this->info("Set Energy(ModelTrigger) [%-16s] = %8.4f GeV", prop.first.c_str(), val);
+  }
+  this->m_model = nullptr;
+  this->addShowerModel(region);
+}
+
+/// Kill primary particle when creating the shower
+void Geant4FastSimShowerModel::killParticle(G4FastStep& step, double deposit, double step_length)   {
+  step.KillPrimaryTrack();
+  step.ProposePrimaryTrackPathLength(step_length);
+  step.ProposeTotalEnergyDeposited(deposit);
+}
+
+/// User callback to determine if the model is applicable for the particle type
+bool Geant4FastSimShowerModel::check_applicability(const G4ParticleDefinition& particle)   {
+  return
+    this->m_enable && 
+    this->m_applicableParticles.find(&particle) != this->m_applicableParticles.end();
+}
+
+/// User callback to determine if the shower creation should be triggered
+bool Geant4FastSimShowerModel::check_trigger(const G4FastTrack& track)    {
+  auto* prim = track.GetPrimaryTrack();
+  auto* def  = prim->GetParticleDefinition();
+  auto  iter = this->m_eTriggerCut.find(def);
+  if ( iter != this->m_eTriggerCut.end() )  {
+    return (*iter).second < prim->GetKineticEnergy();
+  }
+  iter = this->m_eTriggerCut.find(nullptr);
+  if ( iter != this->m_eTriggerCut.end() )  {
+    return (*iter).second < prim->GetKineticEnergy();
+  }
+  return false;
+}
+
+/// User callback to model the particle/energy shower
+void Geant4FastSimShowerModel::modelShower(const G4FastTrack& /* track */, G4FastStep& /* step */)    {
+  except("Method %s::modelShower(const G4FastTrack& track, G4FastStep& step) "
+	 "is not implemented. User implementation mandatory.", this->name().c_str());
+}
diff --git a/DDG4/src/Geant4GFlashSpotHandler.cpp b/DDG4/src/Geant4HitHandler.cpp
similarity index 59%
rename from DDG4/src/Geant4GFlashSpotHandler.cpp
rename to DDG4/src/Geant4HitHandler.cpp
index 04c8b6fa7..4cac25dd4 100644
--- a/DDG4/src/Geant4GFlashSpotHandler.cpp
+++ b/DDG4/src/Geant4HitHandler.cpp
@@ -12,62 +12,61 @@
 //==========================================================================
 
 // Framework include files
-#include "DDG4/Geant4GFlashSpotHandler.h"
-#include "DDSegmentation/Segmentation.h"
-#include "DD4hep/DD4hepUnits.h"
-#include "CLHEP/Units/SystemOfUnits.h"
+#include <DDG4/Geant4HitHandler.h>
+#include <DD4hep/DD4hepUnits.h>
+#include <CLHEP/Units/SystemOfUnits.h>
+
+// Geant4 include files
+#include <G4NavigationHistory.hh>
 
-namespace units = dd4hep;
 using namespace dd4hep;
 using namespace dd4hep::sim;
 
 /// Coordinate transformation to global coordinate.
-Position Geant4GFlashSpotHandler::localToGlobal(const DDSegmentation::Vector3D& local)  const   {
+Position Geant4HitHandler::localToGlobal(const DDSegmentation::Vector3D& local)  const   {
   return localToGlobal(G4ThreeVector(local.X / dd4hep::mm,local.Y / dd4hep::mm,local.Z / dd4hep::mm));
 }
 
 /// Coordinate transformation to global coordinates.
-Position Geant4GFlashSpotHandler::localToGlobal(const Position& local)  const   {
+Position Geant4HitHandler::localToGlobal(const Position& local)  const   {
   return localToGlobal(G4ThreeVector(local.X(),local.Y(),local.Z()));
 }
 
 /// Coordinate transformation to global coordinates
-Position Geant4GFlashSpotHandler::localToGlobal(double x, double y, double z)  const    {
+Position Geant4HitHandler::localToGlobal(double x, double y, double z)  const    {
   return localToGlobal(G4ThreeVector(x,y,z));
 }
 
 /// Coordinate transformation to global coordinates
-Position Geant4GFlashSpotHandler::localToGlobal(const G4ThreeVector& loc)  const    {
-  G4TouchableHandle t = gflashspot->GetTouchableHandle();
-  G4ThreeVector p = t->GetHistory()->GetTopTransform().Inverse().TransformPoint(loc);
+Position Geant4HitHandler::localToGlobal(const G4ThreeVector& loc)  const    {
+  G4ThreeVector p = touchable_ptr->GetHistory()->GetTopTransform().Inverse().TransformPoint(loc);
   return Position(p.x(),p.y(),p.z());
 }
 
 /// Coordinate transformation to local coordinates
-Position Geant4GFlashSpotHandler::globalToLocal(double x, double y, double z)  const    {
+Position Geant4HitHandler::globalToLocal(double x, double y, double z)  const    {
   G4ThreeVector p = globalToLocalG4(G4ThreeVector(x,y,z));
   return Position(p.x(),p.y(),p.z());
 }
 
 /// Coordinate transformation to local coordinates
-Position Geant4GFlashSpotHandler::globalToLocal(const Position& global)  const    {
+Position Geant4HitHandler::globalToLocal(const Position& global)  const    {
   G4ThreeVector p = globalToLocalG4(G4ThreeVector(global.X(),global.Y(),global.Z()));
   return Position(p.x(),p.y(),p.z());
 }
 
 /// Coordinate transformation to local coordinates
-Position Geant4GFlashSpotHandler::globalToLocal(const G4ThreeVector& global)  const    {
+Position Geant4HitHandler::globalToLocal(const G4ThreeVector& global)  const    {
   G4ThreeVector p = globalToLocalG4(global);
   return Position(p.x(),p.y(),p.z());
 }
 
 /// Coordinate transformation to local coordinates
-G4ThreeVector Geant4GFlashSpotHandler::globalToLocalG4(double x, double y, double z)  const    {
+G4ThreeVector Geant4HitHandler::globalToLocalG4(double x, double y, double z)  const    {
   return globalToLocalG4(G4ThreeVector(x,y,z));
 }
 
 /// Coordinate transformation to local coordinates
-G4ThreeVector Geant4GFlashSpotHandler::globalToLocalG4(const G4ThreeVector& global)  const    {
-  G4TouchableHandle t = gflashspot->GetTouchableHandle();
-  return t->GetHistory()->GetTopTransform().TransformPoint(global);
+G4ThreeVector Geant4HitHandler::globalToLocalG4(const G4ThreeVector& global)  const    {
+  return touchable_ptr->GetHistory()->GetTopTransform().TransformPoint(global);
 }
diff --git a/DDG4/src/Geant4ReadoutVolumeFilter.cpp b/DDG4/src/Geant4ReadoutVolumeFilter.cpp
index 9b8816fda..856df933f 100644
--- a/DDG4/src/Geant4ReadoutVolumeFilter.cpp
+++ b/DDG4/src/Geant4ReadoutVolumeFilter.cpp
@@ -18,7 +18,7 @@
 #include "DDG4/Geant4Mapping.h"
 #include "DDG4/Geant4StepHandler.h"
 #include "DDG4/Geant4VolumeManager.h"
-#include "DDG4/Geant4GFlashSpotHandler.h"
+#include "DDG4/Geant4FastSimHandler.h"
 #include "DDG4/Geant4ReadoutVolumeFilter.h"
 
 using namespace dd4hep::sim;
@@ -59,9 +59,9 @@ bool Geant4ReadoutVolumeFilter::operator()(const G4Step* step) const    {
   return false;
 }
 
-/// Filter action. Return true if hits should be processed
-bool Geant4ReadoutVolumeFilter::operator()(const G4GFlashSpot* spot) const    {
-  Geant4GFlashSpotHandler spotH(spot);
+/// GFLASH/FastSim interface: Filter action. Return true if hits should be processed
+bool Geant4ReadoutVolumeFilter::operator()(const Geant4FastSimSpot* spot) const    {
+  Geant4FastSimHandler spotH(spot);
   Geant4VolumeManager volMgr = Geant4Mapping::instance().volumeManager();
   VolumeID id  = volMgr.volumeID(spotH.touchable());
   long64   key = m_key->value(id);
diff --git a/DDG4/src/Geant4SensDetAction.cpp b/DDG4/src/Geant4SensDetAction.cpp
index 634cd266f..42d56fb12 100644
--- a/DDG4/src/Geant4SensDetAction.cpp
+++ b/DDG4/src/Geant4SensDetAction.cpp
@@ -21,7 +21,6 @@
 #include "DDG4/Geant4SensDetAction.h"
 #include "DDG4/Geant4VolumeManager.h"
 #include "DDG4/Geant4MonteCarloTruth.h"
-#include "DDG4/Geant4GFlashSpotHandler.h"
 
 // Geant4 include files
 #include <G4Step.hh>
@@ -92,8 +91,8 @@ bool Geant4Filter::operator()(const G4Step*) const {
 }
 
 /// Filter action. Return true if hits should be processed
-bool Geant4Filter::operator()(const G4GFlashSpot*) const {
-  except("The filter action %s does not support the GFLASH interface for Geant4.", c_name());
+bool Geant4Filter::operator()(const Geant4FastSimSpot*) const {
+  except("The filter action %s does not support the GFLASH/FastSim interface for Geant4.", c_name());
   return false;
 }
 
@@ -158,9 +157,9 @@ bool Geant4Sensitive::accept(const G4Step* step) const {
   return result;
 }
 
-/// GFLASH interface: Callback before hit processing starts. Invoke all filters.
-bool Geant4Sensitive::accept(const G4GFlashSpot* spot) const {
-  bool (Geant4Filter::*filter)(const G4GFlashSpot*) const = &Geant4Filter::operator();
+/// GFLASH/FastSim interface: Callback before hit processing starts. Invoke all filters.
+bool Geant4Sensitive::accept(const Geant4FastSimSpot* spot) const {
+  bool (Geant4Filter::*filter)(const Geant4FastSimSpot*) const = &Geant4Filter::operator();
   bool result = m_filters.filter(filter, spot);
   return result;
 }
@@ -218,13 +217,13 @@ void Geant4Sensitive::end(G4HCofThisEvent* /* HCE */) {
 }
 
 /// G4VSensitiveDetector interface: Method for generating hit(s) using the information of G4Step object.
-bool Geant4Sensitive::process(G4Step* /* step */, G4TouchableHistory* /* history */) {
+bool Geant4Sensitive::process(const G4Step* /* step */, G4TouchableHistory* /* history */) {
   return false;
 }
 
-/// Separate GFLASH interface: Method for generating hit(s) using the information of the G4GFlashSpot object.
-bool Geant4Sensitive::processGFlash(G4GFlashSpot* /* spot */, G4TouchableHistory* /* history */) {
-  except("The sensitive action %s does not support the GFLASH interface for Geant4.", c_name());
+/// GFLASH/FastSim interface: Method for generating hit(s) using the information of the Geant4FastSimSpot object.
+bool Geant4Sensitive::processFastSim(const Geant4FastSimSpot* /* spot */, G4TouchableHistory* /* history */) {
+  except("The sensitive action %s does not support the GFLASH/FastSim interface for Geant4.", c_name());
   return false;
 }
 
@@ -252,11 +251,10 @@ long long int Geant4Sensitive::volumeID(const G4Step* step) {
   return id;
 }
 
-/// Returns the volumeID of the sensitive volume corresponding to the GFlash spot
-long long int Geant4Sensitive::volumeID(const G4GFlashSpot* spot) {
-  Geant4GFlashSpotHandler h(spot);
+/// Returns the volumeID of the sensitive volume corresponding to the touchable history
+long long int Geant4Sensitive::volumeID(const G4VTouchable* touchable) {
   Geant4VolumeManager volMgr = Geant4Mapping::instance().volumeManager();
-  VolumeID id = volMgr.volumeID(h.touchable());
+  VolumeID id = volMgr.volumeID(touchable);
   return id;
 }
 
@@ -266,7 +264,7 @@ long long int Geant4Sensitive::cellID(const G4Step* step) {
   Geant4VolumeManager volMgr = Geant4Mapping::instance().volumeManager();
   VolumeID volID = volMgr.volumeID(h.preTouchable());
   if ( m_segmentation.isValid() )  {
-    G4ThreeVector global = 0.5 * ( h.prePosG4()+h.postPosG4());
+    G4ThreeVector global = 0.5 * (h.prePosG4()+h.postPosG4());
     G4ThreeVector local  = h.preTouchable()->GetHistory()->GetTopTransform().TransformPoint(global);
     Position loc(local.x()*MM_2_CM, local.y()*MM_2_CM, local.z()*MM_2_CM);
     Position glob(global.x()*MM_2_CM, global.y()*MM_2_CM, global.z()*MM_2_CM);
@@ -276,14 +274,12 @@ long long int Geant4Sensitive::cellID(const G4Step* step) {
   return volID;
 }
 
-/// Returns the cellID(volumeID+local coordinate encoding) of the sensitive volume corresponding to the GFlash spot
-long long int Geant4Sensitive::cellID(const G4GFlashSpot* spot) {
-  Geant4GFlashSpotHandler h(spot);
+/// Returns the cellID(volumeID+local coordinate encoding) of the sensitive volume corresponding to the touchable history
+long long int Geant4Sensitive::cellID(const G4VTouchable* touchable, const G4ThreeVector& global) {
   Geant4VolumeManager volMgr = Geant4Mapping::instance().volumeManager();
-  VolumeID volID = volMgr.volumeID(h.touchable());
+  VolumeID volID = volMgr.volumeID(touchable);
   if ( m_segmentation.isValid() )  {
-    G4ThreeVector global = h.positionG4();
-    G4ThreeVector local  = h.touchable()->GetHistory()->GetTopTransform().TransformPoint(global);
+    G4ThreeVector local  = touchable->GetHistory()->GetTopTransform().TransformPoint(global);
     Position loc (local.x()*MM_2_CM, local.y()*MM_2_CM, local.z()*MM_2_CM);
     Position glob(global.x()*MM_2_CM, global.y()*MM_2_CM, global.z()*MM_2_CM);
     VolumeID cID = m_segmentation.cellID(loc,glob,volID);
@@ -405,14 +401,14 @@ bool Geant4SensDetActionSequence::accept(const G4Step* step) const {
 }
 
 /// Callback before hit processing starts. Invoke all filters.
-bool Geant4SensDetActionSequence::accept(const G4GFlashSpot* spot) const {
-  bool (Geant4Filter::*filter)(const G4GFlashSpot*) const = &Geant4Filter::operator();
+bool Geant4SensDetActionSequence::accept(const Geant4FastSimSpot* spot) const {
+  bool (Geant4Filter::*filter)(const Geant4FastSimSpot*) const = &Geant4Filter::operator();
   bool result = m_filters.filter(filter, spot);
   return result;
 }
 
 /// G4VSensitiveDetector interface: Method for generating hit(s) using the information of G4Step object.
-bool Geant4SensDetActionSequence::process(G4Step* step, G4TouchableHistory* history) {
+bool Geant4SensDetActionSequence::process(const G4Step* step, G4TouchableHistory* history) {
   bool result = false;
   for (Geant4Sensitive* sensitive : m_actors)  {
     if ( sensitive->accept(step) )
@@ -422,12 +418,12 @@ bool Geant4SensDetActionSequence::process(G4Step* step, G4TouchableHistory* hist
   return result;
 }
 
-/// Separate GFLASH interface: Method for generating hit(s) using the information of the G4GFlashSpot object.
-bool Geant4SensDetActionSequence::processGFlash(G4GFlashSpot* spot, G4TouchableHistory* history)  {
+/// GFLASH/FastSim interface: Method for generating hit(s) using the information of the Geant4FastSimSpot object.
+bool Geant4SensDetActionSequence::processFastSim(const Geant4FastSimSpot* spot, G4TouchableHistory* history)  {
   bool result = false;
   for (Geant4Sensitive* sensitive : m_actors)  {
     if ( sensitive->accept(spot) )
-      result |= sensitive->processGFlash(spot, history);
+      result |= sensitive->processFastSim(spot, history);
   }
   m_process(spot, history);
   return result;
diff --git a/DDG4/src/Geant4StepHandler.cpp b/DDG4/src/Geant4StepHandler.cpp
index 35c6ceae3..ad3385e94 100644
--- a/DDG4/src/Geant4StepHandler.cpp
+++ b/DDG4/src/Geant4StepHandler.cpp
@@ -65,57 +65,6 @@ const char* Geant4StepHandler::postStepStatus() const {
   return stepStatus(post ? post->GetStepStatus() : fUndefined);
 }
 
-/// Coordinate transformation to global coordinate.
-Position Geant4StepHandler::localToGlobal(const DDSegmentation::Vector3D& local)  const   {
-  return localToGlobal(G4ThreeVector(local.X / dd4hep::mm,local.Y / dd4hep::mm,local.Z / dd4hep::mm));
-}
-
-/// Coordinate transformation to global coordinates.
-Position Geant4StepHandler::localToGlobal(const Position& local)  const   {
-  return localToGlobal(G4ThreeVector(local.X(),local.Y(),local.Z()));
-}
-
-/// Coordinate transformation to global coordinates
-Position Geant4StepHandler::localToGlobal(double x, double y, double z)  const    {
-  return localToGlobal(G4ThreeVector(x,y,z));
-}
-
-/// Coordinate transformation to global coordinates
-Position Geant4StepHandler::localToGlobal(const G4ThreeVector& loc)  const    {
-  G4TouchableHandle t = step->GetPreStepPoint()->GetTouchableHandle();
-  G4ThreeVector p = t->GetHistory()->GetTopTransform().Inverse().TransformPoint(loc);
-  return Position(p.x(),p.y(),p.z());
-}
-
-/// Coordinate transformation to local coordinates
-Position Geant4StepHandler::globalToLocal(double x, double y, double z)  const    {
-  G4ThreeVector p = globalToLocalG4(G4ThreeVector(x,y,z));
-  return Position(p.x(),p.y(),p.z());
-}
-
-/// Coordinate transformation to local coordinates
-Position Geant4StepHandler::globalToLocal(const Position& global)  const    {
-  G4ThreeVector p = globalToLocalG4(G4ThreeVector(global.X(),global.Y(),global.Z()));
-  return Position(p.x(),p.y(),p.z());
-}
-
-/// Coordinate transformation to local coordinates
-Position Geant4StepHandler::globalToLocal(const G4ThreeVector& global)  const    {
-  G4ThreeVector p = globalToLocalG4(global);
-  return Position(p.x(),p.y(),p.z());
-}
-
-/// Coordinate transformation to local coordinates
-G4ThreeVector Geant4StepHandler::globalToLocalG4(double x, double y, double z)  const    {
-  return globalToLocalG4(G4ThreeVector(x,y,z));
-}
-
-/// Coordinate transformation to local coordinates
-G4ThreeVector Geant4StepHandler::globalToLocalG4(const G4ThreeVector& global)  const    {
-  G4TouchableHandle t = step->GetPreStepPoint()->GetTouchableHandle();
-  return t->GetHistory()->GetTopTransform().TransformPoint(global);
-}
-
 /// Apply BirksLaw
 double Geant4StepHandler::birkAttenuation() const    {
 #if G4VERSION_NUMBER >= 1001
diff --git a/DDG4/src/Geant4TestActions.cpp b/DDG4/src/Geant4TestActions.cpp
index fdee04f5a..c752033de 100644
--- a/DDG4/src/Geant4TestActions.cpp
+++ b/DDG4/src/Geant4TestActions.cpp
@@ -215,7 +215,7 @@ void Geant4TestSensitive::end(G4HCofThisEvent* hce) {
 }
 
 /// Method for generating hit(s) using the information of G4Step object.
-bool Geant4TestSensitive::process(G4Step* step, G4TouchableHistory*) {
+bool Geant4TestSensitive::process(const G4Step* step, G4TouchableHistory*) {
   Geant4HitCollection* c = collection(m_collectionID);
   PRINT("%s> calling process(track=%d, dE=%f, dT=%f len=%f, First,last in Vol=(%c,%c), coll=%s Context: run=%p evt=%p)",
         m_type.c_str(), step->GetTrack()->GetTrackID(),
diff --git a/DDG4/src/Geant4UIManager.cpp b/DDG4/src/Geant4UIManager.cpp
index 07ccc9af3..307c561c8 100644
--- a/DDG4/src/Geant4UIManager.cpp
+++ b/DDG4/src/Geant4UIManager.cpp
@@ -62,6 +62,8 @@ Geant4UIManager::~Geant4UIManager()   {
 void Geant4UIManager::installCommandMessenger()   {
   m_control->addCall("exit", "Force exiting this process",
                      Callback(this).make(&Geant4UIManager::forceExit),0);
+  m_control->addCall("terminate", "Regular exit this process",
+                     Callback(this).make(&Geant4UIManager::regularExit),0);
 }
 
 /// Force exiting this process without calling atexit handlers
@@ -69,6 +71,13 @@ void Geant4UIManager::forceExit()   {
   std::_Exit(0);
 }
 
+/// Regularly exiting this process without calling atexit handlers
+void Geant4UIManager::regularExit()   {
+  printout(INFO,"Geant4UIManager","++ End of processing requested.");
+  this->context()->kernel().terminate();
+  this->forceExit();
+}
+
 /// Start visualization
 G4VisManager* Geant4UIManager::startVis()  {
   // Initialize visualization
diff --git a/examples/ClientTests/CMakeLists.txt b/examples/ClientTests/CMakeLists.txt
index 4a4cc8408..3b124df17 100644
--- a/examples/ClientTests/CMakeLists.txt
+++ b/examples/ClientTests/CMakeLists.txt
@@ -429,5 +429,14 @@ if (DD4HEP_USE_GEANT4)
       REGEX_PASS NONE
       REGEX_FAIL "Exception;EXCEPTION;ERROR;Error" )
   endforeach(script)
+  #
+  # Geant4 full simulation checks of multi-collection/segmentation detectors
+  foreach(script SiliconBlockGFlash SiliconBlockFastSim )
+    dd4hep_add_test_reg( ClientTests_sim_${script}_LONGTEST
+      COMMAND    "${CMAKE_INSTALL_PREFIX}/bin/run_test_ClientTests.sh"
+      EXEC_ARGS  ${Python_EXECUTABLE} ${ClientTestsEx_INSTALL}/scripts/${script}.py -batch -events 2
+      REGEX_PASS "Event 1 Begin event action. Access event related information"
+      REGEX_FAIL "Exception;EXCEPTION;ERROR;Error" )
+  endforeach(script)
 
 endif(DD4HEP_USE_GEANT4)
diff --git a/examples/ClientTests/scripts/SiliconBlock.py b/examples/ClientTests/scripts/SiliconBlock.py
index 987a5139c..0f33699d5 100644
--- a/examples/ClientTests/scripts/SiliconBlock.py
+++ b/examples/ClientTests/scripts/SiliconBlock.py
@@ -30,6 +30,17 @@ from g4units import GeV, MeV, m
 
 
 def run():
+  nevts = -1
+  macro = None
+  batch = False
+  for i in range(len(sys.argv)):
+    if sys.argv[i] == '-batch':
+      batch = True
+    elif sys.argv[i] == '-events':
+      nevts = int(sys.argv[i+1])
+    elif sys.argv[i] == '-macro':
+      macro = sys.argv[i+1]
+
   kernel = DDG4.Kernel()
   install_dir = os.environ['DD4hepExamplesINSTALL']
   kernel.loadGeometry(str("file:" + install_dir + "/examples/ClientTests/compact/SiliconBlock.xml"))
@@ -38,10 +49,12 @@ def run():
   geant4 = DDG4.Geant4(kernel, tracker='Geant4TrackerCombineAction')
   geant4.printDetectors()
   # Configure UI
-  if len(sys.argv) > 1:
-    geant4.setupCshUI(macro=sys.argv[1])
+  if macro:
+    ui = geant4.setupCshUI(macro=macro)
   else:
-    geant4.setupCshUI()
+    ui = geant4.setupCshUI()
+  if batch:
+    ui.Commands = ['/run/beamOn '+str(nevts), '/ddg4/UI/terminate']
 
   # Configure field
   geant4.setupTrackingField(prt=True)
diff --git a/examples/ClientTests/scripts/SiliconBlockFastSim.py b/examples/ClientTests/scripts/SiliconBlockFastSim.py
new file mode 100644
index 000000000..642911150
--- /dev/null
+++ b/examples/ClientTests/scripts/SiliconBlockFastSim.py
@@ -0,0 +1,134 @@
+# ==========================================================================
+#  AIDA Detector description implementation
+# --------------------------------------------------------------------------
+# Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
+# All rights reserved.
+#
+# For the licensing terms see $DD4hepINSTALL/LICENSE.
+# For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
+#
+# ==========================================================================
+#
+#
+from __future__ import absolute_import, unicode_literals
+import os
+import sys
+import time
+import DDG4
+from DDG4 import OutputLevel as Output
+from g4units import GeV, MeV, m
+#
+#
+"""
+
+   dd4hep simulation example setup using the python configuration
+
+   NOTE:
+   If you get to the command prompt, you must not forget to enable GFlash!
+   By default Geant4 does not enable it. Hence:
+   Idle>  /GFlash/flag 1
+
+   @author  M.Frank
+   @version 1.0
+
+"""
+
+
+def run():
+  nevts = -1
+  macro = None
+  batch = False
+  for i in range(len(sys.argv)):
+    if sys.argv[i] == '-batch':
+      batch = True
+    elif sys.argv[i] == '-events':
+      nevts = int(sys.argv[i+1])
+    elif sys.argv[i] == '-macro':
+      macro = sys.argv[i+1]
+
+  kernel = DDG4.Kernel()
+  install_dir = os.environ['DD4hepExamplesINSTALL']
+  kernel.loadGeometry(str("file:" + install_dir + "/examples/ClientTests/compact/SiliconBlock.xml"))
+
+  DDG4.importConstants(kernel.detectorDescription(), debug=False)
+  geant4 = DDG4.Geant4(kernel, tracker='Geant4TrackerAction', calo='Geant4CalorimeterAction')
+  geant4.printDetectors()
+  # Configure UI
+  if macro:
+    ui = geant4.setupCshUI(macro=macro)
+  else:
+    ui = geant4.setupCshUI()
+  if batch:
+    ui.Commands = ['/run/beamOn '+str(nevts), '/ddg4/UI/terminate']
+
+  # Configure field
+  geant4.setupTrackingField(prt=True)
+  # Configure Event actions
+  prt = DDG4.EventAction(kernel, 'Geant4ParticlePrint/ParticlePrint')
+  prt.OutputLevel = Output.DEBUG
+  kernel.eventAction().adopt(prt)
+
+  generator_output_level = prt.OutputLevel
+
+  # Configure G4 geometry setup
+  seq, act = geant4.addDetectorConstruction('Geant4DetectorGeometryConstruction/ConstructGeo')
+  act.DebugMaterials = True
+  act.DebugElements = False
+  act.DebugVolumes = True
+  act.DebugShapes = True
+
+  # Apply sensitive detectors
+  sensitives = DDG4.DetectorConstruction(kernel, str('Geant4DetectorSensitivesConstruction/ConstructSD'))
+  sensitives.enableUI()
+  seq.adopt(sensitives)
+
+  # Enable GFlash shower model
+  model = DDG4.DetectorConstruction(kernel, str('Geant4Par01EMShowerModel/ShowerModel'))
+  # Mandatory model parameters
+  model.RegionName = 'SiRegion'
+  model.Material = 'Silicon'
+  model.ApplicableParticles = ['e+', 'e-']
+  model.Etrigger = {'e+': 0.1 * GeV, 'e-': 0.1 * GeV}
+  model.Enable = True
+  # Energy boundaries are optional: Units are GeV
+  model.Emin = {'e+': 0.1 * GeV, 'e-': 0.1 * GeV}
+  model.Ekill = {'e+': 0.1 * MeV, 'e-': 0.1 * MeV}
+  model.enableUI()
+  seq.adopt(model)
+
+  # Configure I/O
+  geant4.setupROOTOutput('RootOutput', 'SiliconBlock_FastSim_' + time.strftime('%Y-%m-%d_%H-%M'))
+
+  # Setup particle gun
+  gun = geant4.setupGun("Gun", particle='e+', energy=50 * GeV, multiplicity=1)
+  gun.OutputLevel = generator_output_level
+
+  # And handle the simulation particles.
+  part = DDG4.GeneratorAction(kernel, "Geant4ParticleHandler/ParticleHandler")
+  kernel.generatorAction().adopt(part)
+  part.SaveProcesses = ['Decay']
+  part.MinimalKineticEnergy = 100 * MeV
+  part.OutputLevel = Output.INFO  # generator_output_level
+  part.enableUI()
+  user = DDG4.Action(kernel, "Geant4TCUserParticleHandler/UserParticleHandler")
+  user.TrackingVolume_Zmax = 3.0 * m
+  user.TrackingVolume_Rmax = 3.0 * m
+  user.enableUI()
+  part.adopt(user)
+
+  geant4.setupCalorimeter('SiliconBlockUpper')
+  geant4.setupCalorimeter('SiliconBlockDown')
+
+  # Now build the physics list:
+  phys = geant4.setupPhysics('FTFP_BERT')
+  ph = DDG4.PhysicsList(kernel, str('Geant4FastPhysics/FastPhysicsList'))
+  ph.EnabledParticles = ['e+', 'e-']
+  ph.BeVerbose = True
+  ph.enableUI()
+  phys.adopt(ph)
+  phys.dump()
+
+  geant4.execute()
+
+if __name__ == "__main__":
+  run()
diff --git a/examples/ClientTests/scripts/SiliconBlockGFlash.py b/examples/ClientTests/scripts/SiliconBlockGFlash.py
index 86b4e3b49..4719cd6c2 100644
--- a/examples/ClientTests/scripts/SiliconBlockGFlash.py
+++ b/examples/ClientTests/scripts/SiliconBlockGFlash.py
@@ -35,6 +35,17 @@ from g4units import GeV, MeV, m
 
 
 def run():
+  nevts = -1
+  macro = None
+  batch = False
+  for i in range(len(sys.argv)):
+    if sys.argv[i] == '-batch':
+      batch = True
+    elif sys.argv[i] == '-events':
+      nevts = int(sys.argv[i+1])
+    elif sys.argv[i] == '-macro':
+      macro = sys.argv[i+1]
+
   kernel = DDG4.Kernel()
   install_dir = os.environ['DD4hepExamplesINSTALL']
   kernel.loadGeometry(str("file:" + install_dir + "/examples/ClientTests/compact/SiliconBlock.xml"))
@@ -43,10 +54,12 @@ def run():
   geant4 = DDG4.Geant4(kernel, tracker='Geant4TrackerCombineAction', calo='Geant4CalorimeterAction')
   geant4.printDetectors()
   # Configure UI
-  if len(sys.argv) > 1:
-    geant4.setupCshUI(macro=sys.argv[1])
+  if macro:
+    ui = geant4.setupCshUI(macro=macro)
   else:
-    geant4.setupCshUI()
+    ui = geant4.setupCshUI()
+  if batch:
+    ui.Commands = ['/run/beamOn '+str(nevts), '/ddg4/UI/terminate']
 
   # Configure field
   geant4.setupTrackingField(prt=True)
@@ -83,7 +96,7 @@ def run():
   seq.adopt(model)
 
   # Configure I/O
-  geant4.setupROOTOutput('RootOutput', 'SiliconBlock_' + time.strftime('%Y-%m-%d_%H-%M'))
+  geant4.setupROOTOutput('RootOutput', 'SiliconBlock_GFlash_' + time.strftime('%Y-%m-%d_%H-%M'))
 
   # Setup particle gun
   gun = geant4.setupGun("Gun", particle='e+', energy=50 * GeV, multiplicity=1)
diff --git a/examples/DDG4/scripts/TestProperties.py b/examples/DDG4/scripts/TestProperties.py
index 1c278e287..623100aa0 100644
--- a/examples/DDG4/scripts/TestProperties.py
+++ b/examples/DDG4/scripts/TestProperties.py
@@ -436,11 +436,7 @@ def run():
   phys = geant4.setupPhysics('FTFP_BERT')
   phys.dump()
   ui.Commands = ['/ddg4/Test/show', '/ddg4/Test/dumpProperties', '/ddg4/UI/exit']
-  kernel.NumEvents = 0
-  kernel.configure()
-  kernel.initialize()
-  kernel.run()
-  kernel.terminate()
+  geant4.execute()
 
 
 if __name__ == "__main__":
diff --git a/examples/DDG4_MySensDet/CMakeLists.txt b/examples/DDG4_MySensDet/CMakeLists.txt
index bfd22f520..a0f6bfefc 100644
--- a/examples/DDG4_MySensDet/CMakeLists.txt
+++ b/examples/DDG4_MySensDet/CMakeLists.txt
@@ -63,6 +63,7 @@ if (DD4HEP_USE_GEANT4)
     COMMAND    "${CMAKE_INSTALL_PREFIX}/bin/run_test_DDG4_MySensDet.sh"
     EXEC_ARGS  ${Python_EXECUTABLE} ${DDG4_MySensDet_INSTALL}/scripts/MyTrackerSD_sim.py 
                --compact=file:${CMAKE_INSTALL_PREFIX}/examples/ClientTests/compact/SiliconBlock.xml
+	       -batch -events 3
     REGEX_PASS NONE
     REGEX_FAIL "Exception;EXCEPTION;ERROR;Error" )
 
diff --git a/examples/DDG4_MySensDet/scripts/MyTrackerSD_sim.py b/examples/DDG4_MySensDet/scripts/MyTrackerSD_sim.py
index f0d00511f..5d5140f83 100644
--- a/examples/DDG4_MySensDet/scripts/MyTrackerSD_sim.py
+++ b/examples/DDG4_MySensDet/scripts/MyTrackerSD_sim.py
@@ -2,6 +2,7 @@
 #
 from __future__ import absolute_import, unicode_literals
 import os
+import sys
 import time
 import DDG4
 from DDG4 import OutputLevel as Output
@@ -19,6 +20,17 @@ from g4units import GeV
 
 
 def run():
+  nevts = -1
+  macro = None
+  batch = False
+  for i in range(len(sys.argv)):
+    if sys.argv[i] == '-batch':
+      batch = True
+    elif sys.argv[i] == '-events':
+      nevts = int(sys.argv[i+1])
+    elif sys.argv[i] == '-macro':
+      macro = sys.argv[i+1]
+
   kernel = DDG4.Kernel()
   install_dir = os.environ['DD4hepExamplesINSTALL']
   kernel.loadGeometry(str("file:" + install_dir + "/examples/ClientTests/compact/SiliconBlock.xml"))
@@ -27,10 +39,15 @@ def run():
   # ===> This is actually the ONLY difference to ClientTests/scripts/SiliconBlock.py
   # =======================================================================================
   geant4 = DDG4.Geant4(kernel, tracker='MyTrackerSDAction')
-
   geant4.printDetectors()
-  kernel.NumEvents = 5
-  kernel.UI = ''
+
+  # Configure UI
+  if macro:
+    ui = geant4.setupCshUI(macro=macro)
+  else:
+    ui = geant4.setupCshUI()
+  if batch:
+    ui.Commands = ['/run/beamOn '+str(nevts), '/ddg4/UI/terminate']
 
   # Configure field
   geant4.setupTrackingField(prt=True)
diff --git a/examples/DDG4_MySensDet/src/MyTrackerSDAction.cpp b/examples/DDG4_MySensDet/src/MyTrackerSDAction.cpp
index 6ed13a791..f4b0624ac 100644
--- a/examples/DDG4_MySensDet/src/MyTrackerSDAction.cpp
+++ b/examples/DDG4_MySensDet/src/MyTrackerSDAction.cpp
@@ -54,7 +54,7 @@ namespace dd4hep {
     }
 
     /// Method for generating hit(s) using the information of G4Step object.
-    template <> bool Geant4SensitiveAction<MyTrackerSD>::process(G4Step* step,G4TouchableHistory* /*hist*/ ) {
+    template <> bool Geant4SensitiveAction<MyTrackerSD>::process(const G4Step* step,G4TouchableHistory* /*hist*/ ) {
       Geant4StepHandler h(step);
       Position prePos    = h.prePos();
       Position postPos   = h.postPos();
-- 
GitLab