diff --git a/DDG4/examples/CLICSidSimu.py b/DDG4/examples/CLICSidSimu.py
index 37b259bc86dcf506a6a5780b7f2fd625df1cb526..ef58298f4d7b04967d47ccb0586a9e7018a0da38 100644
--- a/DDG4/examples/CLICSidSimu.py
+++ b/DDG4/examples/CLICSidSimu.py
@@ -43,8 +43,8 @@ def run():
 
   # Configure I/O
   evt_root = simple.setupROOTOutput('RootOutput','CLICSiD_'+time.strftime('%Y-%m-%d_%H-%M'))
-  evt_lcio = simple.setupLCIOOutput('LcioOutput','CLICSiD_'+time.strftime('%Y-%m-%d_%H-%M'))
-  evt_lcio.OutputLevel = Output.ERROR
+  #evt_lcio = simple.setupLCIOOutput('LcioOutput','CLICSiD_'+time.strftime('%Y-%m-%d_%H-%M'))
+  #evt_lcio.OutputLevel = Output.ERROR
 
 
   generator_output_level = Output.INFO
@@ -57,7 +57,7 @@ def run():
   Generation of isotrope tracks using the DDG4 partcle gun:
 
   # Setup particle gun
-  gun = simple.setupGun('Gun','pi-',energy=10*GeV,isotrop=True,multiplicity=3)
+  gun = simple.setupGun('Gun','pi-',energy=10*GeV,isotrop=True,multiplicity=1)
   gun.OutputLevel = 5 # generator_output_level
   gun.Mask = 1
   #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -101,16 +101,15 @@ def run():
   """
   Generation of primary particles from LCIO input files
   """
-
   # First particle file reader
   gen = DDG4.GeneratorAction(kernel,"LCIOInputAction/LCIO1");
-  gen.Input = "LCIOStdHepReader|/home/frankm/SW/data/e2e2nn_gen_1343_1.stdhep"
+  #gen.Input = "LCIOStdHepReader|/home/frankm/SW/data/e2e2nn_gen_1343_1.stdhep"
   #gen.Input = "LCIOStdHepReader|/home/frankm/SW/data/qq_gen_128_999.stdhep"
-  gen.Input = "LCIOStdHepReader|/home/frankm/SW/data/smuonLR_PointK_3TeV_BS_noBkg_run0001.stdhep"
+  #gen.Input = "LCIOStdHepReader|/home/frankm/SW/data/smuonLR_PointK_3TeV_BS_noBkg_run0001.stdhep"
   gen.Input = "LCIOStdHepReader|/home/frankm/SW/data/bbbb_3TeV.stdhep"
+  #gen.Input = "LCIOFileReader|/home/frankm/SW/data/mcparticles_pi-_5GeV.slcio"
   gen.OutputLevel = 4 # generator_output_level
   gen.Mask = 1
-  gen.MomentumScale = 0.1
   kernel.generatorAction().adopt(gen)
   # Install vertex smearing for this interaction
   gen = DDG4.GeneratorAction(kernel,"Geant4InteractionVertexSmear/Smear1");  
@@ -135,6 +134,7 @@ def run():
   gen.Offset = (20*mm, 10*mm, 10*mm, 0*ns)
   gen.Sigma = (2*mm, 1*mm, 1*mm, 0*ns)
   kernel.generatorAction().adopt(gen)
+
   #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
   # Merge all existing interaction records
@@ -152,7 +152,10 @@ def run():
   kernel.generatorAction().adopt(part)
   #part.SaveProcesses = ['conv','Decay']
   part.SaveProcesses = ['Decay']
-  part.OutputLevel = 4 # generator_output_level
+  part.MinimalKineticEnergy = 100*MeV
+  part.Z_trackers = 165.70*cm  # EcalEndcap_zmin
+  part.R_trackers = 126.50*cm  # EcalBarrel_rmin
+  part.OutputLevel = 5 # generator_output_level
   part.enableUI()
   #user = DDG4.Action(kernel,"Geant4UserParticleHandler/UserParticleHandler")
   #part.adopt(user)
diff --git a/DDG4/include/DDG4/Geant4HitCollection.h b/DDG4/include/DDG4/Geant4HitCollection.h
index 3978dbd59db56880c656275282e633ba61a9155c..0a642b69cea04ae1a85627e6f6cb23bab6eb8349 100644
--- a/DDG4/include/DDG4/Geant4HitCollection.h
+++ b/DDG4/include/DDG4/Geant4HitCollection.h
@@ -288,6 +288,51 @@ namespace DD4hep {
       void getHitsUnchecked(std::vector<void*>& result);
     };
 
+
+    /** @class PositionCompare Geant4HitCollection.h DDG4/Geant4HitCollection.h
+     *
+     *  Class for hit matching using the hit position.
+     *
+     * @author  M.Frank
+     * @version 1.0
+     */
+    template<typename TYPE, typename POS> struct PositionCompare : public Geant4HitCollection::Compare {
+      const POS& pos;
+      /// Constructor
+      PositionCompare(const POS& p) : pos(p)  {      }
+      /// Comparison function
+      virtual void* operator()(const Geant4HitWrapper& w) const;
+    };
+
+    template <typename TYPE, typename POS> 
+      void* PositionCompare<TYPE,POS>::operator()(const Geant4HitWrapper& w) const {
+      TYPE* h = w;
+      return pos == h->position ? h : 0;
+    }
+
+    /** @class PositionCompare Geant4HitCollection.h DDG4/Geant4HitCollection.h
+     *
+     *  Class for hit matching using the hit's cell identifier.
+     *
+     * @author  M.Frank
+     * @version 1.0
+     */
+    template<typename TYPE> struct CellIDCompare : public Geant4HitCollection::Compare {
+      long long int id;
+      /// Constructor
+      CellIDCompare(long long int i) : id(i) {      }
+      /// Comparison function.
+      virtual void* operator()(const Geant4HitWrapper& w) const;
+    };
+
+    template <typename TYPE> 
+      void* CellIDCompare<TYPE>::operator()(const Geant4HitWrapper& w) const {
+      TYPE* h = w;
+      if ( id == h->cellID )
+	return h;
+      return 0;
+    }
+
   }    // End namespace Simulation
 }      // End namespace DD4hep
 
diff --git a/DDG4/include/DDG4/Geant4InputHandling.h b/DDG4/include/DDG4/Geant4InputHandling.h
new file mode 100644
index 0000000000000000000000000000000000000000..e6779249f7d4cf10c3307cd8c121676cc13f3289
--- /dev/null
+++ b/DDG4/include/DDG4/Geant4InputHandling.h
@@ -0,0 +1,55 @@
+//====================================================================
+//  AIDA Detector description implementation
+//--------------------------------------------------------------------
+//
+//  Author     : M.Frank
+//
+//====================================================================
+#ifndef DD4HEP_DDG4_GEANT4INPUTHANDLING_H
+#define DD4HEP_DDG4_GEANT4INPUTHANDLING_H
+
+// Framework include files
+#include "DDG4/Geant4Primary.h"
+
+// Forward declarations
+class G4Event;
+
+/*
+ *   DD4hep namespace declaration
+ */
+namespace DD4hep {
+
+  /*
+   *   Simulation namespace declaration
+   */
+  namespace Simulation {
+
+    // Forward declarations
+    class Geant4Action;
+    class Geant4Context;
+
+    /// Initialize the generation of one event
+    int generationInitialization(const Geant4Action* caller,const Geant4Context* context);
+
+    /// Merge all interactions present in the context
+    int mergeInteractions(const Geant4Action* caller,const Geant4Context* context);
+
+    /// Boost particles of one interaction identified by its mask
+    int boostInteraction(const Geant4Action* caller,
+			 Geant4PrimaryEvent::Interaction* inter,
+			 double alpha);
+
+    /// Smear the primary vertex of an interaction
+    int smearInteraction(const Geant4Action* caller,
+			 Geant4PrimaryEvent::Interaction* inter,
+			 double dx, double dy, double dz, double dt);
+
+
+    /// Generate all primary vertices corresponding to the merged interaction
+    int generatePrimaries(const Geant4Action* caller,
+			  const Geant4Context* context,
+			  G4Event* event);
+
+  }    // End namespace Simulation
+}      // End namespace DD4hep
+#endif /* DD4HEP_DDG4_GEANT4INPUTHANDLING_H  */
diff --git a/DDG4/include/DDG4/Geant4Particle.h b/DDG4/include/DDG4/Geant4Particle.h
index f79faa0e283c2d9c7f448410048b67e94733900b..0dc6a874d41a03f3b5523e087d838dd4edf79581 100644
--- a/DDG4/include/DDG4/Geant4Particle.h
+++ b/DDG4/include/DDG4/Geant4Particle.h
@@ -191,6 +191,7 @@ namespace DD4hep {
       void dump2(int level, const std::string& src, const char* tag, int g4id, bool inrec) const;
       /// Output type 3:+++ <tag> ID:  0 e-           status:00000014 type:       11 Vertex:(+0.00e+00,+0.00e+00,+0.00e+00) [mm] time: +0.00e+00 [ns] #Par:  0 #Dau:  4
       void dump3(int level, const std::string& src, const char* tag) const;
+      void dump4(int level, const std::string& src, const char* tag) const;
 
       /// Handlers
 
diff --git a/DDG4/include/DDG4/Geant4ParticleGun.h b/DDG4/include/DDG4/Geant4ParticleGun.h
index 253ccca46c1db45fd160b0ff20e4c254a71995fb..17750f03bc875323ac2338054e807249279c1111 100644
--- a/DDG4/include/DDG4/Geant4ParticleGun.h
+++ b/DDG4/include/DDG4/Geant4ParticleGun.h
@@ -24,6 +24,7 @@ namespace DD4hep {
    *   Simulation namespace declaration
    */
   namespace Simulation {
+
     /** @class Geant4ParticleGun Geant4ParticleGun.h DDG4/Geant4ParticleGun.h
      *
      * Implementation wrapper of the Geant4 particle gun
@@ -45,6 +46,8 @@ namespace DD4hep {
       int m_mask;
       /// Property: Isotrope particles?
       bool m_isotrop;
+      /// Property: Standalone mode: includes interaction merging and primary generation
+      bool m_standalone;
 
       /// Pointer to geant4 particle definition
       G4ParticleDefinition* m_particle;
diff --git a/DDG4/include/DDG4/Geant4ParticleHandler.h b/DDG4/include/DDG4/Geant4ParticleHandler.h
index e3f390f224445436f89067efcbeb706ee3e15e27..ff291107d6c393222167003f101980886468cfe2 100644
--- a/DDG4/include/DDG4/Geant4ParticleHandler.h
+++ b/DDG4/include/DDG4/Geant4ParticleHandler.h
@@ -75,6 +75,9 @@ namespace DD4hep {
       /// Property: Energy cut below which particles are not collected, but assigned to the parent
       double m_kinEnergyCut;
 
+      double m_zTracker, m_rTracker;
+
+
       /// Global particle identifier. Obtained at the begin of the event.
       int m_globalParticleID, m_initialParticleID;
       /// User action pointer
diff --git a/DDG4/include/DDG4/Geant4ParticlePrint.h b/DDG4/include/DDG4/Geant4ParticlePrint.h
index a9a44a697bf5f5fe84d6a5d83e577a55545f3543..808ef2e5d1f69a3e2a34d0d6d4a6899a6de2c80a 100644
--- a/DDG4/include/DDG4/Geant4ParticlePrint.h
+++ b/DDG4/include/DDG4/Geant4ParticlePrint.h
@@ -14,6 +14,9 @@
 #include "DDG4/Geant4GeneratorAction.h"
 #include "DDG4/Geant4Particle.h"
 
+// Forward declarations
+class G4Event;
+
 /*
  *   DD4hep namespace declaration
  */
@@ -44,16 +47,18 @@ namespace DD4hep {
       bool m_printEnd;
       /// Property: Flag to indicate output type as part of the generator action
       bool m_printGeneration;
+      /// Property: Flag to indicate output of hit data in tree
+      bool m_printHits;
 
-      void printParticle(const std::string& prefix, Geant4ParticleHandle p) const;
+      void printParticle(const std::string& prefix, const G4Event* e, Geant4ParticleHandle p) const;
       /// Print record of kept particles
-      void printParticles(const ParticleMap& particles) const;
+      void printParticles(const G4Event* e, const ParticleMap& particles) const;
       /// Print tree of kept particles
-      void printParticleTree(const ParticleMap& particles, int level, Geant4ParticleHandle p)  const;
+      void printParticleTree(const G4Event* e, const ParticleMap& particles, int level, Geant4ParticleHandle p)  const;
       /// Print tree of kept particles
-      void printParticleTree(const ParticleMap& particles)  const;
+      void printParticleTree(const G4Event* e, const ParticleMap& particles)  const;
       /// Print particle table
-      void makePrintout(int event_id)  const;
+      void makePrintout(const G4Event* e)  const;
 
 
     public:
diff --git a/DDG4/include/DDG4/Geant4SensDetAction.h b/DDG4/include/DDG4/Geant4SensDetAction.h
index 2ec461117ac90d5e18eebbdcbdcb6f1ac6509a62..86107bbc0312c1069f32540dc190f8f42d9f4628 100644
--- a/DDG4/include/DDG4/Geant4SensDetAction.h
+++ b/DDG4/include/DDG4/Geant4SensDetAction.h
@@ -30,6 +30,12 @@ class G4VReadOutGeometry;
  */
 namespace DD4hep {
 
+  // Forward declarations
+  namespace Geometry  {
+    class LCDD;
+    class DetElement;
+  }
+
   /*
    *   Simulation namespace declaration
    */
@@ -405,6 +411,44 @@ namespace DD4hep {
       return sequence().defineCollection<TYPE>(this, coll_name);
     }
 
+    /** @class Geant4SensitiveAction Geant4SensDetAction.h DDG4/Geant4SensDetAction.h
+     *
+     * Templated implementation to realize sensitive detectors.
+     * Default implementations for all functions are provided in the file
+     * DDG4/Geant4SensDetAction.inl.
+     *
+     * Users may override any of the templated callbacks or the of the virtual functions
+     * of the base class using explicit template specialization.
+     * An example may be found in DDG4/plugins/eant4SDActions.
+     *
+     * @author  M.Frank
+     * @version 1.0
+     */
+    template <typename T> class Geant4SensitiveAction : public Geant4Sensitive  {
+    protected:
+      /// Collection identifier
+      size_t m_collectionID;
+    public:
+      /// Standard , initializing constructor
+      Geant4SensitiveAction(Geant4Context* context, 
+			    const std::string& name, 
+			    Geometry::DetElement det, 
+			    Geometry::LCDD& lcdd);
+      /// Default destructor
+      virtual ~Geant4SensitiveAction();
+      /// Define collections created by this sensitivie action object
+      virtual void defineCollections() {}
+      /// G4VSensitiveDetector interface: Method invoked at the begining of each event. 
+      virtual void begin(G4HCofThisEvent* hce);
+      /// G4VSensitiveDetector interface: Method invoked at the end of each event. 
+      virtual void end(G4HCofThisEvent* hce);
+      /// G4VSensitiveDetector interface: Method for generating hit(s) using the G4Step object.
+      virtual bool process(G4Step* step,G4TouchableHistory* history);
+      /// G4VSensitiveDetector interface: Method invoked if the event was aborted.
+      virtual void clear(G4HCofThisEvent* hce);
+    };
+
+
   }    // End namespace Simulation
 }      // End namespace DD4hep
 
diff --git a/DDG4/include/DDG4/Geant4SensDetAction.inl b/DDG4/include/DDG4/Geant4SensDetAction.inl
new file mode 100644
index 0000000000000000000000000000000000000000..cd63b2f0bfa0584654f2b7582abe8766336ee227
--- /dev/null
+++ b/DDG4/include/DDG4/Geant4SensDetAction.inl
@@ -0,0 +1,57 @@
+// $Id: Geant4Field.cpp 513 2013-04-05 14:31:53Z gaede $
+//====================================================================
+//  AIDA Detector description implementation for LCD
+//--------------------------------------------------------------------
+//
+//  Author     : M.Frank
+//
+//====================================================================
+
+// Framework include files
+#ifndef DD4HEP_DDG4_GEANT4SENSDETACTION_H
+#include "DDG4/Geant4SensDetAction.h"
+#endif
+#include "DD4hep/InstanceCount.h"
+
+namespace DD4hep {
+  namespace Simulation   {
+
+    /// Standard , initializing constructor
+    template <typename T> 
+    Geant4SensitiveAction<T>::Geant4SensitiveAction(Geant4Context* context, 
+						    const std::string& name, 
+						    Geometry::DetElement det, 
+						    Geometry::LCDD& lcdd)
+      : Geant4Sensitive(context,name,det,lcdd), m_collectionID(0)
+    {
+      defineCollections();
+      InstanceCount::increment(this);
+    }
+
+    /// Default destructor
+    template <typename T> Geant4SensitiveAction<T>::~Geant4SensitiveAction()  {
+      InstanceCount::decrement(this);
+    }
+
+    /// G4VSensitiveDetector interface: Method invoked at the begining of each event. 
+    template <typename T> void Geant4SensitiveAction<T>::begin(G4HCofThisEvent* hce)  {
+      Geant4Sensitive::begin(hce);
+    }
+
+    /// G4VSensitiveDetector interface: Method invoked at the end of each event. 
+    template <typename T> void Geant4SensitiveAction<T>::end(G4HCofThisEvent* hce)  {
+      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);
+    }
+
+    /// G4VSensitiveDetector interface: Method invoked if the event was aborted.
+    template <typename T> void Geant4SensitiveAction<T>::clear(G4HCofThisEvent* hce)  {
+      Geant4Sensitive::clear(hce);
+    }
+
+  }
+}
diff --git a/DDG4/include/DDG4/Geant4TrackHandler.h b/DDG4/include/DDG4/Geant4TrackHandler.h
index c5553631c7b095931a60112c30592627233631b5..35e93a04b059831ea0ce3ee94e185a102bdb0b13 100644
--- a/DDG4/include/DDG4/Geant4TrackHandler.h
+++ b/DDG4/include/DDG4/Geant4TrackHandler.h
@@ -137,6 +137,9 @@ namespace DD4hep {
       G4VPhysicalVolume* vol() const {
         return track->GetVolume();
       }
+      G4ThreeVector momentum() const  {
+	return track->GetMomentum();
+      }
       /// Next physical volume of the track
       G4VPhysicalVolume* nextVol() const {
         return track->GetNextVolume();
diff --git a/DDG4/plugins/Geant4SDActions.cpp b/DDG4/plugins/Geant4SDActions.cpp
index 608c6ca48c27ee7cae059a3e2ad0cbb68a985d35..511ceca1fc8bf741790ec1c93d665fd219626e35 100644
--- a/DDG4/plugins/Geant4SDActions.cpp
+++ b/DDG4/plugins/Geant4SDActions.cpp
@@ -7,91 +7,13 @@
 //
 //====================================================================
 // Framework include files
-#include "DDG4/Geant4SensDetAction.h"
+#include "DDG4/Geant4SensDetAction.inl"
 #include "DDG4/Geant4Data.h"
 #include "DD4hep/Printout.h"
 
 using namespace std;
 
-/*
- *   DD4hep namespace declaration
- */
-namespace DD4hep {
-
-  /*
-   *   Simulation namespace declaration
-   */
-  namespace Simulation   {
-
-    template <typename T> class Geant4SensitiveAction : public Geant4Sensitive  {
-    protected:
-      /// Collection identifiers
-      size_t m_collectionID;
-    public:
-      typedef SimpleHit::Contribution HitContribution;
-      /// Standard , initializing constructor
-      Geant4SensitiveAction(Geant4Context* context, const string& name, DetElement det, LCDD& lcdd);
-      /// Default destructor
-      virtual ~Geant4SensitiveAction();
-      /// Define collections created by this sensitivie action object
-      virtual void defineCollections() {}
-      /// G4VSensitiveDetector interface: Method invoked at the begining of each event. 
-      virtual void begin(G4HCofThisEvent* hce);
-      /// G4VSensitiveDetector interface: Method invoked at the end of each event. 
-      virtual void end(G4HCofThisEvent* hce);
-      /// G4VSensitiveDetector interface: Method for generating hit(s) using the G4Step object.
-      virtual bool process(G4Step* step,G4TouchableHistory* history);
-      /// G4VSensitiveDetector interface: Method invoked if the event was aborted.
-      virtual void clear(G4HCofThisEvent* hce);
-    };
-  }
-}
-#include "DD4hep/InstanceCount.h"
 #include "DDG4/Geant4TouchableHandler.h"
-
-namespace DD4hep {
-  namespace Simulation   {
-
-    /// Standard , initializing constructor
-    template <typename T> 
-    Geant4SensitiveAction<T>::Geant4SensitiveAction(Geant4Context* context, 
-						    const string& name, 
-						    DetElement det, 
-						    LCDD& lcdd)
-      : Geant4Sensitive(context,name,det,lcdd), m_collectionID(0)
-    {
-      defineCollections();
-      InstanceCount::increment(this);
-    }
-
-    /// Default destructor
-    template <typename T> Geant4SensitiveAction<T>::~Geant4SensitiveAction()  {
-      InstanceCount::decrement(this);
-    }
-
-    /// G4VSensitiveDetector interface: Method invoked at the begining of each event. 
-    template <typename T> void Geant4SensitiveAction<T>::begin(G4HCofThisEvent* hce)  {
-      Geant4Sensitive::begin(hce);
-    }
-
-    /// G4VSensitiveDetector interface: Method invoked at the end of each event. 
-    template <typename T> void Geant4SensitiveAction<T>::end(G4HCofThisEvent* hce)  {
-      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);
-    }
-
-    /// G4VSensitiveDetector interface: Method invoked if the event was aborted.
-    template <typename T> void Geant4SensitiveAction<T>::clear(G4HCofThisEvent* hce)  {
-      Geant4Sensitive::clear(hce);
-    }
-
-  }
-}
-
 #include "DDG4/Geant4StepHandler.h"
 #include "DDG4/Geant4VolumeManager.h"
 #include "DDG4/Geant4Mapping.h"
@@ -102,30 +24,7 @@ namespace DD4hep {
 namespace DD4hep {
   namespace Simulation   {
 
-    template<typename TYPE> struct PositionCompare : public Geant4HitCollection::Compare {
-      const Position& pos;
-      Geant4HitWrapper::HitManipulator* manip;
-      /// Constructor
-      PositionCompare(const Position& p) : pos(p), manip(Geant4HitWrapper::HitManipulator::instance<TYPE>())  {      }
-      /// Comparison function
-      virtual void* operator()(const Geant4HitWrapper& w) const {
-	TYPE* h = w;//(const TYPE*)manip->castHit<TYPE>(w);
-	return pos == h->position ? h : 0;
-      }
-    };
-    template<typename TYPE> struct CellIDCompare : public Geant4HitCollection::Compare {
-      long long int id;
-      Geant4HitWrapper::HitManipulator* manip;
-      /// Constructor
-      CellIDCompare(long long int i) : id(i), manip(Geant4HitWrapper::HitManipulator::instance<TYPE>())  {      }
-      /// Comparison function
-      virtual void* operator()(const Geant4HitWrapper& w) const {
-	TYPE* h = w;//(const TYPE*)manip->castHit<TYPE>(w);
-	if ( id == h->cellID )
-	  return h;
-	return 0;
-      }
-    };
+    typedef Geant4HitData::Contribution HitContribution;
 
     /// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
     ///               Geant4SensitiveAction<Geant4Tracker>
@@ -243,7 +142,7 @@ namespace DD4hep {
 	HitCollection*  coll    = collection(m_collectionID);
 	HitContribution contrib = Hit::extractContribution(step);
 	Position        pos     = h.prePos();
-	Hit* hit = coll->find<Hit>(PositionCompare<Hit>(pos));
+	Hit* hit = coll->find<Hit>(PositionCompare<Hit,Position>(pos));
 	if ( !hit ) {
 	  hit = new Hit(pos);
 	  hit->cellID = volumeID(step);
diff --git a/DDG4/plugins/Geant4XMLSetup.cpp b/DDG4/plugins/Geant4XMLSetup.cpp
index 1f34bd040c9c49fa563a1661f5d478df186456d0..79b3635848478e3a7ca3f7ec5655f7abc9b732ec 100644
--- a/DDG4/plugins/Geant4XMLSetup.cpp
+++ b/DDG4/plugins/Geant4XMLSetup.cpp
@@ -426,7 +426,15 @@ namespace DD4hep  {
   template <> void Converter<XMLSetup>::operator()(xml_h seq)  const  {
     xml_elt_t compact(seq);
     // First execute the basic setup from the plugins module
-    ROOT::Reflex::PluginService::Create<NamedObject*>("geant4_xml_setup",&lcdd,&seq);
+    long result = ROOT::Reflex::PluginService::Create<long>("geant4_XML_reader",&lcdd,&seq);
+    if ( 0 == result )  {
+      throw runtime_error("DD4hep: Failed to locate plugin to interprete files of type"
+			  " \"" + seq.tag() + "\" - no factory of type geant4_XML_reader.");
+    }
+    result = *(long*) result;
+    if (result != 1) {
+      throw runtime_error("DD4hep: Failed to parse the XML tag " + seq.tag() + " with the plugin geant4_XML_reader");
+    }
     xml_coll_t(compact,_Unicode(kernel)).for_each(Converter<Kernel>(lcdd,param));
     // Now deal with the new stuff.....
     xml_coll_t(compact,_Unicode(actions) ).for_each(_Unicode(action),Converter<Action>(lcdd,param));
diff --git a/DDG4/python/DDG4.py b/DDG4/python/DDG4.py
index be43da09fb577a5fa2aff09789f2bbfdc4a60778..f863a9222ba17689946f71367bdeccee9c39c828 100644
--- a/DDG4/python/DDG4.py
+++ b/DDG4/python/DDG4.py
@@ -225,13 +225,17 @@ class Simple:
     self.kernel.generatorAction().add(gun)
     return gun
 
-  def setupCshUI(self):
+  def setupUI(typ='csh',vis=False,ui=True):
     # Configure UI
     ui = Action(self.kernel,"Geant4UIManager/UI")
-    ui.HaveVIS = True
-    ui.HaveUI = True
-    ui.SessionType = 'csh'
+    ui.HaveVIS = vis
+    ui.HaveUI = ui
+    ui.SessionType = typ
     self.kernel.registerGlobalAction(ui)
+
+  def setupCshUI(self,typ='csh',vis=False,ui=True):
+    self.setupUI('csh',vis,ui)
+
   def setupROOTOutput(self,name,output):
     evt_root = EventAction(self.kernel,'Geant4Output2ROOT/'+name)
     evt_root.Control = True
diff --git a/DDG4/src/Geant4GeneratorActionInit.cpp b/DDG4/src/Geant4GeneratorActionInit.cpp
index 5194dfb366f1581616535a6a17fd4665cfb880f7..09ee12e1d1c837a34eba79ee74f1775686994f5e 100644
--- a/DDG4/src/Geant4GeneratorActionInit.cpp
+++ b/DDG4/src/Geant4GeneratorActionInit.cpp
@@ -10,9 +10,9 @@
 #include "DD4hep/Printout.h"
 #include "DD4hep/InstanceCount.h"
 #include "DDG4/Geant4Kernel.h"
-#include "DDG4/Geant4Primary.h"
 #include "DDG4/Geant4RunAction.h"
 #include "DDG4/Geant4GeneratorActionInit.h"
+#include "DDG4/Geant4InputHandling.h"
 
 #include "G4Run.hh"
 
@@ -52,30 +52,5 @@ void Geant4GeneratorActionInit::operator()(G4Event* /* event */)  {
   ++m_evtRun;
   /// + Printout
   print("+++ Initializing event %d. Within run:%d event %d.",m_evtTotal,m_run,m_evtRun);
-
-  /**
-   *  This action should register all event extension required for the further 
-   *  processing. We want to avoid that every client has to check if a given 
-   *  object is present or not and than later install the required data structures.
-   */
-  context()->event().addExtension(new Geant4PrimaryMap());
-
-  // The final set of created particles in the simulation.
-  context()->event().addExtension(new Geant4ParticleMap());
-
-  //
-  // The Geant4PrimaryEvent extension contains a whole set of 
-  // Geant4PrimaryInteraction objects each may represent a complete
-  // interaction. Particles and vertices may be unbiased.
-  // This is the input to the translator forming the final 
-  // Geant4PrimaryInteraction (see below) containing rebiased particle
-  // and vertex maps.
-  Geant4PrimaryEvent* evt = new Geant4PrimaryEvent();
-  context()->event().addExtension(evt);
-  //
-  // The Geant4PrimaryInteraction extension contains the final
-  // vertices and particles ready to be injected to Geant4.
-  Geant4PrimaryInteraction* inter = new Geant4PrimaryInteraction();
-  inter->setNextPID(-1);
-  context()->event().addExtension(inter);
+  generationInitialization(this,context());
 }
diff --git a/DDG4/src/Geant4HitCollection.cpp b/DDG4/src/Geant4HitCollection.cpp
index b1a1b4604b598f61e8d61ac139c7404a18a39e97..f6b9c94c5019eb9fca50e7b8ce5430469a207475 100644
--- a/DDG4/src/Geant4HitCollection.cpp
+++ b/DDG4/src/Geant4HitCollection.cpp
@@ -10,6 +10,7 @@
 // Framework include files
 #include "DD4hep/InstanceCount.h"
 #include "DDG4/Geant4HitCollection.h"
+#include "DDG4/Geant4Data.h"
 #include "G4Allocator.hh"
 
 using namespace DD4hep;
diff --git a/DDG4/src/Geant4InputHandling.cpp b/DDG4/src/Geant4InputHandling.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0a2180100431e02634e6ad8dfb0105e20b838216
--- /dev/null
+++ b/DDG4/src/Geant4InputHandling.cpp
@@ -0,0 +1,338 @@
+// $Id: Geant4Field.cpp 888 2013-11-14 15:54:56Z markus.frank@cern.ch $
+//====================================================================
+//  AIDA Detector description implementation for LCD
+//--------------------------------------------------------------------
+//
+//  Author     : M.Frank
+//
+//====================================================================
+// Framework include files
+#include "DDG4/Geant4InputHandling.h"
+#include "DDG4/Geant4Primary.h"
+#include "DDG4/Geant4Context.h"
+#include "DDG4/Geant4Action.h"
+#include "CLHEP/Units/SystemOfUnits.h"
+#include "CLHEP/Units/PhysicalConstants.h"
+
+#include "G4ParticleDefinition.hh"
+#include "G4Event.hh"
+#include "G4PrimaryVertex.hh"
+#include "G4PrimaryParticle.hh"
+
+// C/C++ include files
+#include <stdexcept>
+#include <cmath>
+
+using namespace std;
+using namespace DD4hep;
+using namespace DD4hep::Simulation;
+
+typedef ReferenceBitMask<int> PropertyMask;
+
+/// Initialize the generation of one event
+int DD4hep::Simulation::generationInitialization(const Geant4Action* /* caller */,
+						 const Geant4Context* context)
+{
+  /**
+   *  This action should register all event extension required for the further 
+   *  processing. We want to avoid that every client has to check if a given 
+   *  object is present or not and than later install the required data structures.
+   */
+  context->event().addExtension(new Geant4PrimaryMap());
+
+  // The final set of created particles in the simulation.
+  context->event().addExtension(new Geant4ParticleMap());
+
+  //
+  // The Geant4PrimaryEvent extension contains a whole set of 
+  // Geant4PrimaryInteraction objects each may represent a complete
+  // interaction. Particles and vertices may be unbiased.
+  // This is the input to the translator forming the final 
+  // Geant4PrimaryInteraction (see below) containing rebiased particle
+  // and vertex maps.
+  Geant4PrimaryEvent* evt = new Geant4PrimaryEvent();
+  context->event().addExtension(evt);
+  //
+  // The Geant4PrimaryInteraction extension contains the final
+  // vertices and particles ready to be injected to Geant4.
+  Geant4PrimaryInteraction* inter = new Geant4PrimaryInteraction();
+  inter->setNextPID(-1);
+  context->event().addExtension(inter);
+  return 1;
+}
+
+/// Append input interaction to global output
+static void appendInteraction(const Geant4Action* caller,
+			      Geant4PrimaryInteraction* output, 
+			      Geant4PrimaryInteraction* input)
+{
+  Geant4PrimaryInteraction::ParticleMap::iterator ip, ipend;
+  for( ip=input->particles.begin(), ipend=input->particles.end(); ip != ipend; ++ip )  {
+    Geant4Particle* p = (*ip).second;
+    output->particles.insert(make_pair(p->id,p->addRef()));
+  }
+  Geant4PrimaryInteraction::VertexMap::iterator ivfnd, iv, ivend;
+  for( iv=input->vertices.begin(), ivend=input->vertices.end(); iv != ivend; ++iv )   {
+    ivfnd = output->vertices.find((*iv).second->mask);
+    if ( ivfnd != output->vertices.end() )   {
+      caller->abortRun("Duplicate primary interaction identifier!",
+		       "Cannot handle 2 interactions with identical identifiers!");
+    }
+    output->vertices.insert(make_pair((*iv).second->mask,(*iv).second->addRef()));
+  }
+}
+
+static void rebaseParticles(Geant4PrimaryInteraction::ParticleMap& particles, int &offset)    {
+  Geant4PrimaryInteraction::ParticleMap::iterator ip, ipend;
+  int mx_id = offset;
+  // Now move begin and end-vertex of all primary and generator particles accordingly
+  for( ip=particles.begin(), ipend=particles.end(); ip != ipend; ++ip )  {
+    Geant4ParticleHandle p((*ip).second);
+    p.offset(offset);
+    mx_id = p->id+1 > mx_id ? p->id+1 : mx_id;
+  }
+  offset = mx_id;
+}
+
+static void rebaseVertices(Geant4PrimaryInteraction::VertexMap& vertices, int part_offset)    {
+  Geant4PrimaryInteraction::VertexMap::iterator iv, ivend;    
+  set<int> in, out;
+  set<int>::iterator i;
+  // Now move begin and end-vertex of all primary vertices accordingly
+  for(iv=vertices.begin(), ivend=vertices.end(); iv != ivend; ++iv)  {
+    Geant4Vertex* v = (*iv).second;
+    in  = v->in;
+    out = v->out;
+    for(in=v->in, i=in.begin(), v->in.clear(); i != in.end(); ++i)
+      v->in.insert((*i)+part_offset);
+    for(out=v->out, i=out.begin(), v->out.clear(); i != out.end(); ++i)
+      v->out.insert((*i)+part_offset);
+  }
+}
+
+/// Merge all interactions present in the context
+int DD4hep::Simulation::mergeInteractions(const Geant4Action* caller,
+					  const Geant4Context* context)   
+{
+  typedef Geant4PrimaryEvent::Interaction  Interaction;
+  typedef vector<Interaction*>             Interactions;
+  Geant4Event& event = context->event();
+  Geant4PrimaryEvent* evt = event.extension<Geant4PrimaryEvent>();
+  Interaction* output = event.extension<Interaction>();
+  Interactions inter  = evt->interactions();
+  int particle_offset = 0;
+
+  for(Interactions::const_iterator i=inter.begin(); i != inter.end(); ++i)  {
+    Interaction* interaction = *i;
+    int vertex_offset = particle_offset;
+    if ( !interaction->applyMask() )   {
+      caller->abortRun("Found single interaction with multiple primary vertices!",
+		       "Cannot merge individual interactions with more than one primary!");
+    }
+    rebaseParticles(interaction->particles,particle_offset);
+    rebaseVertices(interaction->vertices,vertex_offset);
+    appendInteraction(caller,output,interaction);
+  }
+  output->setNextPID(particle_offset);
+  Geant4PrimaryInteraction::ParticleMap::iterator ip, ipend;
+  caller->debug("+++ Merging MC input record from %d interactions:",(int)inter.size());
+  for( ip=output->particles.begin(), ipend=output->particles.end(); ip != ipend; ++ip )
+    Geant4ParticleHandle((*ip).second).dump1(DEBUG,caller->name(),"Merged particles");
+  return 1;
+}
+
+/// Boost particles of one interaction identified by its mask
+int DD4hep::Simulation::boostInteraction(const Geant4Action* /* caller */,
+					 Geant4PrimaryEvent::Interaction* inter, 
+					 double alpha)
+{
+#define SQR(x)  (x*x)
+  Geant4PrimaryEvent::Interaction::VertexMap::iterator iv;    
+  Geant4PrimaryEvent::Interaction::ParticleMap::iterator ip;
+  double gamma = std::sqrt(1 + SQR(tan(alpha)));
+  double betagamma = std::tan(alpha);
+
+  if ( alpha != 0.0 )  {
+    // Now move begin and end-vertex of all primary vertices accordingly
+    for(iv=inter->vertices.begin(); iv != inter->vertices.end(); ++iv)  {
+      Geant4Vertex* v = (*iv).second;
+      double t = gamma * v->time + betagamma * v->x / c_light;
+      double x = gamma * v->x + betagamma * c_light * v->time;
+      double y = v->y;
+      double z = v->z;
+      v->x = x;
+      v->y = y;
+      v->z = z;
+      v->time = t;
+    }
+
+    // Now move begin and end-vertex of all primary and generator particles accordingly
+    for(ip=inter->particles.begin(); ip != inter->particles.end(); ++ip)  {
+      Geant4Particle* p = (*ip).second;
+      double t = gamma * p->time + betagamma * p->vsx / c_light;
+      double x = gamma * p->vsx + betagamma * c_light * p->time;
+      double y = p->vsx;
+      double z = p->vsz;
+
+      double m  = p->definition->GetPDGMass();
+      double e2 = SQR(p->psx)+SQR(p->psy)+SQR(p->psz)+SQR(m);
+      double px = betagamma * std::sqrt(e2) + gamma * p->psx;
+      double py = p->psy;
+      double pz = p->psz;
+
+      p->vsx = x;
+      p->vsy = y;
+      p->vsz = z;
+      p->time = t;
+
+      p->psx += px;
+      p->psy += py;
+      p->psz += pz;
+    }
+  }
+  return 1;
+}
+
+/// Smear the primary vertex of an interaction
+int DD4hep::Simulation::smearInteraction(const Geant4Action* /* caller */,
+					 Geant4PrimaryEvent::Interaction* inter, 
+					 double dx, double dy, double dz, double dt)
+{
+  Geant4PrimaryEvent::Interaction::VertexMap::iterator iv;    
+  Geant4PrimaryEvent::Interaction::ParticleMap::iterator ip;
+
+  // Now move begin and end-vertex of all primary vertices accordingly
+  for(iv=inter->vertices.begin(); iv != inter->vertices.end(); ++iv)  {
+    Geant4Vertex* v = (*iv).second;
+    v->x += dx;
+    v->y += dy;
+    v->z += dz;
+    v->time += dt;
+  }
+  // Now move begin and end-vertex of all primary and generator particles accordingly
+  for(ip=inter->particles.begin(); ip != inter->particles.end(); ++ip)  {
+    Geant4Particle* p = (*ip).second;
+    p->vsx += dx;
+    p->vsy += dy;
+    p->vsz += dz;
+    p->vex += dx;
+    p->vey += dy;
+    p->vez += dz;
+    p->time += dt;
+  }
+  return 1;
+}
+
+static G4PrimaryParticle* createG4Primary(const Geant4ParticleHandle p)  {
+  G4PrimaryParticle* g4 = new G4PrimaryParticle(p->pdgID, p->psx, p->psy, p->psz);
+  g4->SetMass(p->mass);
+  return g4;
+}
+
+static map<Geant4Particle*,G4PrimaryParticle*>
+getRelevant(set<int>& visited,
+	    map<int,G4PrimaryParticle*>& prim,
+	    Geant4PrimaryInteraction::ParticleMap& pm, 
+	    const Geant4ParticleHandle p)  
+{
+  typedef map<Geant4Particle*,G4PrimaryParticle*> Primaries;
+  Primaries res;
+  visited.insert(p->id);
+  PropertyMask status(p->status);
+  if ( status.isSet(G4PARTICLE_GEN_STABLE) )  {
+    if ( prim.find(p->id) == prim.end() )  {
+      G4PrimaryParticle* p4 = createG4Primary(p);
+      prim[p->id] = p4;
+      res.insert(make_pair(p,p4));
+    }
+  }
+  else if ( p->daughters.size() > 0 )  {
+    const Geant4Particle::Particles& dau = p->daughters;
+    int first_daughter = *(dau.begin());
+    Geant4ParticleHandle dp = pm[first_daughter];
+    double en = p.energy();
+    double me = en > std::numeric_limits<double>::epsilon() ? p->mass / en : 0.0;
+    //  fix by S.Morozov for real != 0
+    double proper_time = fabs(dp->time-p->time) * me;
+    double proper_time_Precision =  pow(10.,-DBL_DIG)*me*fmax(fabs(p->time),fabs(dp->time));
+    bool isProperTimeZero = ( proper_time <= proper_time_Precision ) ;
+    // -- remove original --- if (proper_time != 0) {
+    if ( !isProperTimeZero ) {
+      map<int,G4PrimaryParticle*>::iterator ip4 = prim.find(p->id);
+      G4PrimaryParticle* p4 = (ip4 == prim.end()) ? 0 : (*ip4).second;
+      if ( !p4 )  {
+	p4 = createG4Primary(p);
+	p4->SetProperTime(proper_time);
+	prim[p->id] = p4;
+	Primaries daughters;
+	for(Geant4Particle::Particles::const_iterator i=dau.begin(); i!=dau.end(); ++i)  {
+	  if ( visited.find(*i) == visited.end() )  {
+	    Primaries tmp = getRelevant(visited,prim,pm,pm[*i]);
+	    daughters.insert(tmp.begin(),tmp.end());
+	  }
+	}
+	for(Primaries::iterator i=daughters.begin(); i!=daughters.end(); ++i)
+	  p4->SetDaughter((*i).second);
+      }
+      res.insert(make_pair(p,p4));
+    }
+    else  {
+      for(Geant4Particle::Particles::const_iterator i=dau.begin(); i!=dau.end(); ++i)  {
+	if ( visited.find(*i) == visited.end() )  {
+	  Primaries tmp = getRelevant(visited,prim,pm,pm[*i]);
+	  res.insert(tmp.begin(),tmp.end());
+	}
+      }
+    }
+  }
+  return res;
+}
+
+/// Generate all primary vertices corresponding to the merged interaction
+int DD4hep::Simulation::generatePrimaries(const Geant4Action* caller,
+					  const Geant4Context* context,
+					  G4Event* event)
+{
+  typedef map<Geant4Particle*,G4PrimaryParticle*> Primaries;
+  typedef Geant4PrimaryInteraction Interaction;
+  Geant4PrimaryMap* primaries   = context->event().extension<Geant4PrimaryMap>();
+  Interaction*      interaction = context->event().extension<Interaction>();
+  Interaction::ParticleMap& pm  = interaction->particles;
+  Interaction::VertexMap&   vm  = interaction->vertices;
+  map<int,G4PrimaryParticle*> prim;
+  set<int> visited;
+
+  Geant4PrimaryInteraction::VertexMap::iterator ivfnd, iv, ivend;
+  for(Interaction::VertexMap::const_iterator iend=vm.end(),i=vm.begin(); i!=iend; ++i)  {
+    int num_part = 0;
+    Geant4Vertex* v = (*i).second;
+    G4PrimaryVertex* v4 = new G4PrimaryVertex(v->x,v->y,v->z,v->time);
+    event->AddPrimaryVertex(v4);
+    caller->print("+++++ G4PrimaryVertex at (%+.2e,%+.2e,%+.2e) [mm] %+.2e [ns]",
+		  v->x/mm,v->y/mm,v->z/mm,v->time/ns);    
+    for(Geant4Vertex::Particles::const_iterator ip=v->out.begin(); ip!=v->out.end(); ++ip)  {
+      Geant4ParticleHandle p = pm[*ip];
+      if ( p->parents.size() == 0 )  {
+	Primaries relevant = getRelevant(visited,prim,pm,p);
+	for(Primaries::const_iterator j=relevant.begin(); j!= relevant.end(); ++j)  {
+	  Geant4ParticleHandle r = (*j).first;
+	  G4PrimaryParticle* p4 = (*j).second;
+	  PropertyMask reason(r->reason);
+	  reason.set(G4PARTICLE_PRIMARY);
+	  v4->SetPrimary(p4);
+	  caller->printM1("+++ +-> G4Primary[%3d] ID:%3d type:%9d/%-12s "
+			  "Momentum:(%+.2e,%+.2e,%+.2e) [GeV] time:%+.2e [ns] #Par:%3d #Dau:%3d",
+			  num_part,r->id,r->pdgID,r.particleName().c_str(),
+			  r->psx/GeV,r->psy/GeV,r->psz/GeV,r->time/ns,
+			  int(r->parents.size()),int(r->daughters.size()));
+	  ++num_part;
+	}
+      }
+    }
+  }
+  for(map<int,G4PrimaryParticle*>::iterator i=prim.begin(); i!=prim.end(); ++i)  {
+    Geant4ParticleHandle p = pm[(*i).first];
+    primaries->primaryMap[(*i).second] = p->addRef();
+  }
+  return 1;
+}
diff --git a/DDG4/src/Geant4InteractionMerger.cpp b/DDG4/src/Geant4InteractionMerger.cpp
index 840c7efcc157c1486317cdb9dd562fd39e2a8831..7423bca01b612e88d85ce1abc0eb7914d656aa3a 100644
--- a/DDG4/src/Geant4InteractionMerger.cpp
+++ b/DDG4/src/Geant4InteractionMerger.cpp
@@ -9,13 +9,9 @@
 // Framework include files
 #include "DD4hep/Printout.h"
 #include "DD4hep/InstanceCount.h"
-#include "DDG4/Geant4Primary.h"
+#include "DDG4/Geant4InputHandling.h"
 #include "DDG4/Geant4InteractionMerger.h"
 
-#include <stdexcept>
-
-using namespace std;
-using namespace DD4hep;
 using namespace DD4hep::Simulation;
 
 /// Standard constructor
@@ -30,75 +26,10 @@ Geant4InteractionMerger::~Geant4InteractionMerger()  {
   InstanceCount::decrement(this);
 }
 
-void rebaseParticles(Geant4PrimaryInteraction::ParticleMap& particles, int &offset)    {
-  Geant4PrimaryInteraction::ParticleMap::iterator ip, ipend;
-  int mx_id = offset;
-  // Now move begin and end-vertex of all primary and generator particles accordingly
-  for( ip=particles.begin(), ipend=particles.end(); ip != ipend; ++ip )  {
-    Geant4ParticleHandle p((*ip).second);
-    p.offset(offset);
-    mx_id = p->id+1 > mx_id ? p->id+1 : mx_id;
-  }
-  offset = mx_id;
-}
-
-void rebaseVertices(Geant4PrimaryInteraction::VertexMap& vertices, int part_offset)    {
-  Geant4PrimaryInteraction::VertexMap::iterator iv, ivend;    
-  set<int> in, out;
-  set<int>::iterator i;
-  // Now move begin and end-vertex of all primary vertices accordingly
-  for(iv=vertices.begin(), ivend=vertices.end(); iv != ivend; ++iv)  {
-    Geant4Vertex* v = (*iv).second;
-    in  = v->in;
-    out = v->out;
-    for(in=v->in, i=in.begin(), v->in.clear(); i != in.end(); ++i)
-      v->in.insert((*i)+part_offset);
-    for(out=v->out, i=out.begin(), v->out.clear(); i != out.end(); ++i)
-      v->out.insert((*i)+part_offset);
-  }
-}
-
-/// Append input interaction to global output
-void Geant4InteractionMerger::appendInteraction(Geant4PrimaryInteraction* output, Geant4PrimaryInteraction* input)   {
-  Geant4PrimaryInteraction::ParticleMap::iterator ip, ipend;
-  for( ip=input->particles.begin(), ipend=input->particles.end(); ip != ipend; ++ip )  {
-    Geant4Particle* p = (*ip).second;
-    output->particles.insert(make_pair(p->id,p->addRef()));
-  }
-  Geant4PrimaryInteraction::VertexMap::iterator ivfnd, iv, ivend;
-  for( iv=input->vertices.begin(), ivend=input->vertices.end(); iv != ivend; ++iv )   {
-    ivfnd = output->vertices.find((*iv).second->mask);
-    if ( ivfnd != output->vertices.end() )   {
-      abortRun("Duplicate primary interaction identifier!",
-	       "Cannot handle 2 interactions with identical identifiers!");
-    }
-    output->vertices.insert(make_pair((*iv).second->mask,(*iv).second->addRef()));
-  }
-}
-
 /// Event generation action callback
 void Geant4InteractionMerger::operator()(G4Event* /* event */)  {
-  typedef Geant4PrimaryEvent::Interaction  Interaction;
-  typedef vector<Interaction*>             Interactions;
   Geant4PrimaryEvent* evt = context()->event().extension<Geant4PrimaryEvent>();
-  Interaction* output = context()->event().extension<Interaction>();
-  Interactions inter  = evt->interactions();
-  int particle_offset = 0;
-
-  for(Interactions::const_iterator i=inter.begin(); i != inter.end(); ++i)  {
-    Interaction* interaction = *i;
-    int vertex_offset = particle_offset;
-    if ( !interaction->applyMask() )   {
-      abortRun("Found single interaction with multiple primary vertices!",
-	       "Cannot merge individual interactions with more than one primary!");
-    }
-    rebaseParticles(interaction->particles,particle_offset);
-    rebaseVertices(interaction->vertices,vertex_offset);
-    appendInteraction(output,interaction);
-  }
-  output->setNextPID(particle_offset);
-  Geant4PrimaryInteraction::ParticleMap::iterator ip, ipend;
-  debug("+++ Merged MC input record from %d interactions:",(int)inter.size());
-  for( ip=output->particles.begin(), ipend=output->particles.end(); ip != ipend; ++ip )
-    Geant4ParticleHandle((*ip).second).dump1(DEBUG,name(),"Merged particles");
+  const std::vector<Geant4PrimaryEvent::Interaction*>& inter  = evt->interactions();
+  debug("+++ Merging MC input record from %d interactions:",(int)inter.size());
+  mergeInteractions(this,context());
 }
diff --git a/DDG4/src/Geant4InteractionVertexBoost.cpp b/DDG4/src/Geant4InteractionVertexBoost.cpp
index d9b889cd1f856ddea522cc6f062e86d9d3bd1aee..1960fd9d1822ecbaa225c323504ef1e0d37d887b 100644
--- a/DDG4/src/Geant4InteractionVertexBoost.cpp
+++ b/DDG4/src/Geant4InteractionVertexBoost.cpp
@@ -10,25 +10,13 @@
 // Framework include files
 #include "DD4hep/Printout.h"
 #include "DD4hep/InstanceCount.h"
-#include "DDG4/Geant4Random.h"
-#include "DDG4/Geant4Context.h"
-#include "DDG4/Geant4Primary.h"
+#include "DDG4/Geant4InputHandling.h"
 #include "DDG4/Geant4InteractionVertexBoost.h"
-#include "CLHEP/Units/SystemOfUnits.h"
-#include "CLHEP/Units/PhysicalConstants.h"
 
-#include "G4ParticleDefinition.hh"
-
-// C/C++ include files
-#include <stdexcept>
-#include <cmath>
-
-using namespace std;
 using namespace DD4hep::Simulation;
-#define SQR(x)  (x*x)
 
 /// Standard constructor
-Geant4InteractionVertexBoost::Geant4InteractionVertexBoost(Geant4Context* context, const string& name)
+Geant4InteractionVertexBoost::Geant4InteractionVertexBoost(Geant4Context* context, const std::string& name)
   : Geant4GeneratorAction(context, name)
 {
   InstanceCount::increment(this);
@@ -44,56 +32,9 @@ Geant4InteractionVertexBoost::~Geant4InteractionVertexBoost() {
 
 /// Callback to generate primary particles
 void Geant4InteractionVertexBoost::operator()(G4Event*) {
-  typedef Geant4PrimaryEvent::Interaction Interaction;
-  typedef Geant4Particle Particle;
-  typedef Geant4Particle Vertex;
-  Geant4PrimaryEvent* evt = context()->event().extension<Geant4PrimaryEvent>();
-  Interaction* inter = evt->get(m_mask);
-
+  Geant4PrimaryEvent::Interaction* inter = 
+    context()->event().extension<Geant4PrimaryEvent>()->get(m_mask);
   if ( inter )  {
-    Interaction::VertexMap::iterator iv;    
-    Interaction::ParticleMap::iterator ip;
-    double alpha = m_angle;
-    double gamma = std::sqrt(1 + SQR(tan(alpha)));
-    double betagamma = std::tan(alpha);
-
-    if ( alpha != 0.0 )  {
-      // Now move begin and end-vertex of all primary vertices accordingly
-      for(iv=inter->vertices.begin(); iv != inter->vertices.end(); ++iv)  {
-	Geant4Vertex* v = (*iv).second;
-	double t = gamma * t + betagamma * v->x / c_light;
-	double x = gamma * v->x + betagamma * c_light * v->time;
-	double y = v->y;
-	double z = v->z;
-	v->x = x;
-	v->y = y;
-	v->z = z;
-	v->time = t;
-      }
-
-      // Now move begin and end-vertex of all primary and generator particles accordingly
-      for(ip=inter->particles.begin(); ip != inter->particles.end(); ++ip)  {
-	Particle* p = (*ip).second;
-	double t = gamma * p->time + betagamma * p->vsx / c_light;
-	double x = gamma * p->vsx + betagamma * c_light * p->time;
-	double y = p->vsx;
-	double z = p->vsz;
-
-	double m  = p->definition->GetPDGMass();
-	double e2 = SQR(p->psx)+SQR(p->psy)+SQR(p->psz)+SQR(m);
-	double px = betagamma * std::sqrt(e2) + gamma * p->psx;
-	double py = p->psy;
-	double pz = p->psz;
-
-	p->vsx = x;
-	p->vsy = y;
-	p->vsz = z;
-	p->time = t;
-
-	p->psx += px;
-	p->psy += py;
-	p->psz += pz;
-      }
-    }
+    boostInteraction(this, inter, m_angle);
   }
 }
diff --git a/DDG4/src/Geant4InteractionVertexSmear.cpp b/DDG4/src/Geant4InteractionVertexSmear.cpp
index 68a0f824fd121fd21c8cd3f5aa1a7b3d245a22b6..a531b6490d69e395ccc8664f96af17e04885e919 100644
--- a/DDG4/src/Geant4InteractionVertexSmear.cpp
+++ b/DDG4/src/Geant4InteractionVertexSmear.cpp
@@ -12,19 +12,16 @@
 #include "DD4hep/InstanceCount.h"
 #include "DDG4/Geant4Random.h"
 #include "DDG4/Geant4Context.h"
-#include "DDG4/Geant4Primary.h"
+#include "DDG4/Geant4InputHandling.h"
 #include "DDG4/Geant4InteractionVertexSmear.h"
-#include "CLHEP/Units/SystemOfUnits.h"
 
 // C/C++ include files
-#include <stdexcept>
 #include <cmath>
 
-using namespace std;
 using namespace DD4hep::Simulation;
 
 /// Standard constructor
-Geant4InteractionVertexSmear::Geant4InteractionVertexSmear(Geant4Context* context, const string& name)
+Geant4InteractionVertexSmear::Geant4InteractionVertexSmear(Geant4Context* context, const std::string& name)
   : Geant4GeneratorAction(context, name)
 {
   InstanceCount::increment(this);
@@ -49,36 +46,14 @@ void Geant4InteractionVertexSmear::operator()(G4Event*) {
   Interaction* inter = evt->get(m_mask);
 
   if ( inter )  {
-    Interaction::VertexMap::iterator iv;    
-    Interaction::ParticleMap::iterator ip;
     double dx = rndm.gauss(m_offset.x(),m_sigma.x());
     double dy = rndm.gauss(m_offset.y(),m_sigma.y());
     double dz = rndm.gauss(m_offset.z(),m_sigma.z());
     double dt = rndm.gauss(m_offset.t(),m_sigma.t());
-
     print("+++ Smearing primary vertex for interaction type %d (%d Vertices, %d particles) "
 	  "by (%+.2e mm, %+.2e mm, %+.2e mm, %+.2e ns)",
 	  m_mask,int(inter->vertices.size()),int(inter->particles.size()),dx,dy,dz,dt);
-
-    // Now move begin and end-vertex of all primary vertices accordingly
-    for(iv=inter->vertices.begin(); iv != inter->vertices.end(); ++iv)  {
-      Geant4Vertex* v = (*iv).second;
-      v->x += dx;
-      v->y += dy;
-      v->z += dz;
-      v->time += dt;
-    }
-    // Now move begin and end-vertex of all primary and generator particles accordingly
-    for(ip=inter->particles.begin(); ip != inter->particles.end(); ++ip)  {
-      Particle* p = (*ip).second;
-      p->vsx += dx;
-      p->vsy += dy;
-      p->vsz += dz;
-      p->vex += dx;
-      p->vey += dy;
-      p->vez += dz;
-      p->time += dt;
-    }
+    smearInteraction(this,inter,dx,dy,dz,dt);
   }
   else  {
     print("+++ No interaction of type %d present.",m_mask);
diff --git a/DDG4/src/Geant4Output2ROOT.cpp b/DDG4/src/Geant4Output2ROOT.cpp
index 85a933ad7136b74d0c7ff158e9936baced9222ec..dc44761191df2ae57d1d098a4eed4324a3b80f9d 100644
--- a/DDG4/src/Geant4Output2ROOT.cpp
+++ b/DDG4/src/Geant4Output2ROOT.cpp
@@ -161,18 +161,18 @@ void Geant4Output2ROOT::saveCollection(OutputContext<G4Event>& /* ctxt */, G4VHi
     if ( truth && nhits > 0 )   {
       try  {
 	for(size_t i=0; i<nhits; ++i)   {
-	  SimpleHit* h = coll->hit(i);
-	  SimpleTracker::Hit* trk_hit = dynamic_cast<SimpleTracker::Hit*>(h);
+	  Geant4HitData* h = coll->hit(i);
+	  Geant4Tracker::Hit* trk_hit = dynamic_cast<Geant4Tracker::Hit*>(h);
 	  if ( 0 != trk_hit )   {
-	    SimpleHit::Contribution& t = trk_hit->truth;
+	    Geant4HitData::Contribution& t = trk_hit->truth;
 	    int trackID = t.trackID;
 	    t.trackID = truth->particleID(trackID);
 	  }
-	  SimpleCalorimeter::Hit* cal_hit = dynamic_cast<SimpleCalorimeter::Hit*>(h);
+	  Geant4Calorimeter::Hit* cal_hit = dynamic_cast<Geant4Calorimeter::Hit*>(h);
 	  if ( 0 != cal_hit )   {
-	    SimpleHit::Contributions& c = cal_hit->truth;
-	    for(SimpleHit::Contributions::iterator j=c.begin(); j!=c.end(); ++j)  {
-	      SimpleHit::Contribution& t = *j;
+	    Geant4HitData::Contributions& c = cal_hit->truth;
+	    for(Geant4HitData::Contributions::iterator j=c.begin(); j!=c.end(); ++j)  {
+	      Geant4HitData::Contribution& t = *j;
 	      int trackID = t.trackID;
 	      t.trackID = truth->particleID(trackID);
 	    }
diff --git a/DDG4/src/Geant4Particle.cpp b/DDG4/src/Geant4Particle.cpp
index cb70c4434cad0a5a2fda90cf5036da0b3daffebf..69b10132ae13f543344e10d8ac5542e1d11f0f3a 100644
--- a/DDG4/src/Geant4Particle.cpp
+++ b/DDG4/src/Geant4Particle.cpp
@@ -20,6 +20,7 @@
 
 using namespace DD4hep;
 using namespace DD4hep::Simulation;
+typedef ReferenceBitMask<int> PropertyMask;
 
 /// Default destructor
 ParticleExtension::~ParticleExtension() {
@@ -276,6 +277,45 @@ void Geant4ParticleHandle::dump3(int level, const std::string& src, const char*
 	   text);
 }
 
+void Geant4ParticleHandle::dump4(int level, const std::string& src, const char* tag) const  {
+  Geant4ParticleHandle p(*this);
+  char equiv[32];
+  PropertyMask mask(p->reason);
+  PropertyMask status(p->status);
+  std::string proc_name = p.processName();
+  std::string proc_type = p.processTypeName();
+  int parent_id = p->parents.empty() ? -1 : *(p->parents.begin());
+
+  equiv[0] = 0;
+  if ( p->parents.end() == p->parents.find(p->g4Parent) )  {
+    ::snprintf(equiv,sizeof(equiv),"/%d",p->g4Parent);
+  }
+  printout((DD4hep::PrintLevel)level,src,
+	   "+++ %s ID:%7d %12s %6d%-7s %7s %3s %5d %3s %+.3e  %-4s %-7s %-3s %-3s %2d  [%s%s%s] %c%c%c%c",
+	   tag,
+	   p->id,
+	   p.particleName().c_str(),
+	   parent_id,equiv,
+	   yes_no(mask.isSet(G4PARTICLE_PRIMARY)),
+	   yes_no(mask.isSet(G4PARTICLE_HAS_SECONDARIES)),
+	   int(p->daughters.size()),
+	   yes_no(mask.isSet(G4PARTICLE_ABOVE_ENERGY_THRESHOLD)),
+	   p.energy(),
+	   yes_no(mask.isSet(G4PARTICLE_CREATED_CALORIMETER_HIT)),
+	   yes_no(mask.isSet(G4PARTICLE_CREATED_TRACKER_HIT)),
+	   yes_no(mask.isSet(G4PARTICLE_KEEP_PROCESS)),
+	   mask.isSet(G4PARTICLE_KEEP_PARENT) ? "YES" : "",
+	   p.numParent(),
+	   proc_name.c_str(),
+	   p->process ? "/" : "",
+	   proc_type.c_str(),
+	   status.isSet(G4PARTICLE_GEN_EMPTY) ? 'E' : '.',
+	   status.isSet(G4PARTICLE_GEN_STABLE) ? 'S' : '.',
+	   status.isSet(G4PARTICLE_GEN_DECAYED) ? 'D' : '.',
+	   status.isSet(G4PARTICLE_GEN_DOCUMENTATION) ? 'd' : '.'
+	   );
+}
+
 /// Default destructor
 Geant4ParticleMap::~Geant4ParticleMap()    {
   clear();
diff --git a/DDG4/src/Geant4ParticleGun.cpp b/DDG4/src/Geant4ParticleGun.cpp
index 290545cf7f6a2842a0161f82976e578f10fde7c3..216ec2d4943bfed05a14bbcc5dc49becee30588e 100644
--- a/DDG4/src/Geant4ParticleGun.cpp
+++ b/DDG4/src/Geant4ParticleGun.cpp
@@ -14,6 +14,7 @@
 #include "DDG4/Geant4Random.h"
 #include "DDG4/Geant4Primary.h"
 #include "DDG4/Geant4ParticleGun.h"
+#include "DDG4/Geant4InputHandling.h"
 #include "CLHEP/Units/SystemOfUnits.h"
 
 #include "G4ParticleTable.hh"
@@ -41,6 +42,7 @@ Geant4ParticleGun::Geant4ParticleGun(Geant4Context* context, const string& name)
   declareProperty("direction", m_direction);
   declareProperty("isotrop", m_isotrop = false);
   declareProperty("Mask", m_mask = 1);
+  declareProperty("Standalone", m_standalone = true);
 }
 
 /// Default destructor
@@ -49,8 +51,12 @@ Geant4ParticleGun::~Geant4ParticleGun() {
 }
 
 /// Callback to generate primary particles
-void Geant4ParticleGun::operator()(G4Event* )   {
+void Geant4ParticleGun::operator()(G4Event* event)   {
   typedef DD4hep::ReferenceBitMask<int> PropertyMask;
+  if ( m_standalone )  {
+    generationInitialization(this,context());
+  }
+
   Geant4Event& evt = context()->event();
   Geant4PrimaryEvent* prim = evt.extension<Geant4PrimaryEvent>();
   if (0 == m_particle || m_particle->GetParticleName() != m_particleName.c_str()) {
@@ -116,4 +122,9 @@ void Geant4ParticleGun::operator()(G4Event* )   {
     p.dump3(outputLevel()-1,name(),"+->");
   }
   ++m_shotNo;
+
+  if ( m_standalone ) {
+    mergeInteractions(this,context());
+    generatePrimaries(this,context(),event);
+  }
 }
diff --git a/DDG4/src/Geant4ParticleHandler.cpp b/DDG4/src/Geant4ParticleHandler.cpp
index 67d3eb05a82da7e912a9869490e6f947cc4306c9..1b7f1c3b085e281d65152863844bf5d2f2fe3299 100644
--- a/DDG4/src/Geant4ParticleHandler.cpp
+++ b/DDG4/src/Geant4ParticleHandler.cpp
@@ -69,6 +69,8 @@ Geant4ParticleHandler::Geant4ParticleHandler(Geant4Context* context, const strin
   declareProperty("KeepAllParticles",    m_keepAll = false);
   declareProperty("SaveProcesses",       m_processNames);
   declareProperty("MinimalKineticEnergy",m_kinEnergyCut = 100e0*MeV);
+  declareProperty("Z_trackers",m_zTracker=1e100);
+  declareProperty("R_trackers",m_rTracker=1e100);
   InstanceCount::increment(this);
 }
 
@@ -155,6 +157,7 @@ void Geant4ParticleHandler::mark(const G4Track* track)   {
   else if ( !mask.isSet(G4PARTICLE_CREATED_TRACKER_HIT) )  {
     mask.set(G4PARTICLE_CREATED_TRACKER_HIT);
   }
+  //Geant4ParticleHandle(&m_currTrack).dump4(outputLevel(),vol->GetName(),"hit created by particle");
 }
 
 /// Event generation action callback
@@ -172,13 +175,8 @@ void Geant4ParticleHandler::operator()(G4Event* event)  {
 /// User stepping callback
 void Geant4ParticleHandler::step(const G4Step* step, G4SteppingManager* mgr)   {
   typedef vector<const G4Track*> _Sec;
-  Geant4StepHandler h(step);
   ++m_currTrack.steps;
-  const G4ThreeVector& v = h.postPosG4();
-  m_currTrack.vex = v.x();
-  m_currTrack.vey = v.y();
-  m_currTrack.vez = v.z();
-  if ( h.trkKineEnergy() > m_kinEnergyCut )  {
+  if ( (m_currTrack.reason&G4PARTICLE_ABOVE_ENERGY_THRESHOLD) )  {
     //
     // Tracks below the energy threshold are NOT stored.
     // If these tracks produce hits or are selected due to another signature, 
@@ -199,13 +197,14 @@ void Geant4ParticleHandler::step(const G4Step* step, G4SteppingManager* mgr)   {
 void Geant4ParticleHandler::begin(const G4Track* track)   {
   Geant4TrackHandler h(track);
   double kine = h.kineticEnergy();
-  G4ThreeVector m = track->GetMomentum();
+  G4ThreeVector m = h.momentum();
   const G4ThreeVector& v = h.vertex();
   int reason = (kine > m_kinEnergyCut) ? G4PARTICLE_ABOVE_ENERGY_THRESHOLD : 0;
   G4PrimaryParticle* prim = primary(h.id(),context()->event().event());
   Particle* prim_part = 0;
 
 
+
   if ( prim )   {
     Geant4PrimaryMap::Primaries::const_iterator iprim = m_primaryMap->primaryMap.find(prim);
     if ( iprim == m_primaryMap->primaryMap.end() )  {
@@ -247,12 +246,6 @@ void Geant4ParticleHandler::begin(const G4Track* track)   {
     m_currTrack.definition   = h.trackDef();
     m_currTrack.pdgID        = h.trackDef()->GetPDGEncoding();
     m_currTrack.mass         = h.trackDef()->GetPDGMass();
-    // Once the daughter gets simulated, the parent is already done....
-    ParticleMap::iterator ipar = m_particleMap.find(h.parent());
-    if ( ipar != m_particleMap.end() )  {
-      Particle* p_par = (*ipar).second;
-      m_currTrack.parents.insert(p_par->id);
-    }
     ++m_globalParticleID;
   }
   m_currTrack.steps       = 0;
@@ -292,35 +285,35 @@ void Geant4ParticleHandler::begin(const G4Track* track)   {
 /// Post-track action callback
 void Geant4ParticleHandler::end(const G4Track* track)   {
   Geant4TrackHandler h(track);
+  Geant4ParticleHandle ph(&m_currTrack);
   int g4_id = h.id();
+  int track_reason = m_currTrack.reason;
   PropertyMask mask(m_currTrack.reason);
 
+  double r_prod = sqrt(ph->vsx*ph->vsx + ph->vsy*ph->vsy);
+  double z_prod = fabs(ph->vsz);
+  if ( r_prod > m_rTracker || z_prod > m_zTracker )  {
+    m_currTrack.reason = 0;
+  }
+
+  // These are candate tracks with a probability to be stored due to their properties:
+  // - primary particle
+  // - hits created
+  // - secondaries
+  // - above energy threshold
+  // - to be kept due to creator process 
+  //
   if ( !mask.isNull() )   {
-    // These are candate tracks with a probability to be stored due to their properties:
-    // - primary particle
-    // - hits created
-    // - secondaries
-    // - above energy threshold
-    // - to be kept due to creator process 
-    //
     // Update vertex end point and final momentum
-    Geant4ParticleHandle ph(&m_currTrack);
     G4ThreeVector m = track->GetMomentum();
+    const G4ThreeVector& p = track->GetPosition();
     ph->pex = m.x();
     ph->pey = m.y();
     ph->pez = m.z();
+    ph->vex = p.x();
+    ph->vey = p.y();
+    ph->vez = p.z();
     m_equivalentTracks[g4_id] = g4_id;
-    // Add this track to it's parents list of daughters
-    ParticleMap::iterator ipar = m_particleMap.find(ph->g4Parent);
-    if ( ipar != m_particleMap.end() )  {
-      Particle* p_par = (*ipar).second;
-      p_par->daughters.insert(ph->id);
-      ph->mask |= p_par->mask;
-      G4ThreeVector dist(ph->vsx-p_par->vex,ph->vsy-p_par->vey,ph->vsz-p_par->vez);
-      if ( dist.r() > 1e-15 )   {
-	// Set flag that the end vertex of the parent is not the start vertex of this track....
-      }
-    }
     /// Final update of the particle using the user handler
     if ( m_userHandler )  {
       m_userHandler->begin(track, m_currTrack);
@@ -330,15 +323,30 @@ void Geant4ParticleHandler::end(const G4Track* track)   {
       ph.dump2(outputLevel()-1,name(),"Add Primary",h.id(),ip!=m_particleMap.end());
     }
     // Create a new MC particle from the current track information saved in the pre-tracking action
-    Particle* p = ip==m_particleMap.end() ? (m_particleMap[g4_id] = new Particle()) : (*ip).second;
-    p->get_data(m_currTrack);
+    Particle* part = 0;
+    if ( ip==m_particleMap.end() ) part = m_particleMap[g4_id] = new Particle();
+    else part = (*ip).second;
+    part->get_data(m_currTrack);
   }
   else   {
     // These are tracks without any special properties.
     //
     // We will not store them on the record, but have to memorise the 
     // track identifier in order to restore the history for the created hits.
-    m_equivalentTracks[g4_id] = m_currTrack.g4Parent;
+    int pid = m_currTrack.g4Parent;
+    m_equivalentTracks[g4_id] = pid;
+    // Need to find the last stored particle and OR this particle's mask 
+    // with the mask of the last stored particle
+    TrackEquivalents::const_iterator iequiv, iend = m_equivalentTracks.end();
+    ParticleMap::iterator ip;
+    for(ip=m_particleMap.find(pid); ip == m_particleMap.end(); ip=m_particleMap.find(pid))  {
+      if ((iequiv=m_equivalentTracks.find(pid)) == iend) break;  // ERROR
+      pid = (*iequiv).second;
+    }
+    if ( ip != m_particleMap.end() )
+      (*ip).second->reason |= track_reason;
+    else
+      ph.dump3(outputLevel()+3,name(),"No real parent present");
   }
 }
 
@@ -358,8 +366,9 @@ void Geant4ParticleHandler::beginEvent(const G4Event* event)  {
 
 /// Debugging: Dump Geant4 particle map
 void Geant4ParticleHandler::dumpMap(const char* tag)  const  {
-  for(ParticleMap::const_iterator iend=m_particleMap.end(), i=m_particleMap.begin(); i!=iend; ++i)
-    Geant4ParticleHandle((*i).second).dump1(INFO,name(),tag);
+  for(ParticleMap::const_iterator iend=m_particleMap.end(), i=m_particleMap.begin(); i!=iend; ++i)  {
+    Geant4ParticleHandle((*i).second).dump4(INFO,name(),tag);
+  }
 }
 
 /// Post-event action callback
@@ -438,30 +447,27 @@ void Geant4ParticleHandler::rebaseSimulatedTracks(int )   {
     else
       error("+++ No Equivalent particle for track:%d last known is:%d",(*i).second,g4_equiv);
   }
-  m_equivalentTracks = equivalents;
-  equivalents.clear();
 
-  // (3) Update the particle's parents and replace the original Geant4 track with the
+  // (3) Compute the particle's parents and daughters. 
+  //     Replace the original Geant4 track with the
   //     equivalent particle still present in the record.
   for(ParticleMap::const_iterator ipar, iend=m_particleMap.end(), i=m_particleMap.begin(); i!=iend; ++i)  {
     Particle* p = (*i).second;
-    set<int> daughters = p->daughters;
-    p->daughters.clear();
-    for(set<int>::iterator id=daughters.begin(); id!=daughters.end(); ++id)
-      p->daughters.insert(orgParticles[*id]);             // Requires (1)
-    //if ( 0 == (p->status&G4PARTICLE_GEN_GENERATOR) )
-      {
-      if ( p->g4Parent > 0 )  {
-	p->parents.clear();
-	p->parents.insert(equivalentTrack(p->g4Parent));  // Requires (2)
-	ipar = m_particleMap.find(p->g4Parent);
-	if ( ipar != iend )   {
-	  set<int>& dau = (*ipar).second->daughters;
-	  if ( dau.find(p->id) == dau.end() ) dau.insert(p->id);
-	}
+    if ( p->g4Parent > 0 )  {
+      int equiv_id = equivalents[p->g4Parent];
+      if ( (ipar=finalParticles.find(equiv_id)) != finalParticles.end() )  {
+	Particle* q = (*ipar).second;
+	q->daughters.insert(p->id);
+	p->parents.insert(q->id);
+      }
+      else   {
+	error("+++ Inconsistency in particle record: Geant4 parent %d "
+	      "of particle %d (equiv:%d) not in record!",
+	      p->g4Parent,p->id,equiv_id);
       }
     }
   }
+  m_equivalentTracks = equivalents;
   m_particleMap = finalParticles;
 }
 
@@ -537,8 +543,6 @@ int Geant4ParticleHandler::recombineParents()  {
 	if ( ip != m_particleMap.end() )   {
 	  Particle* parent_part = (*ip).second;
 	  PropertyMask(parent_part->reason).set(mask.value());
-	  // Remove track from parent's list of daughters
-	  parent_part->removeDaughter(id);
 	  parent_part->steps += p->steps;
 	  parent_part->secondaries += p->secondaries;
 	  /// Update of the particle using the user handler
@@ -615,7 +619,7 @@ int Geant4ParticleHandler::equivalentTrack(int g4_id)  const  {
   int equiv_id  = g4_id;
   if ( g4_id != 0 )  {
     TrackEquivalents::const_iterator iequiv = m_equivalentTracks.find(equiv_id);
-    return (iequiv == m_equivalentTracks.end()) ? -1 : (*iequiv).second;
+    if ( iequiv != m_equivalentTracks.end() ) return (*iequiv).second;
   }
   return -1;
 }
diff --git a/DDG4/src/Geant4ParticlePrint.cpp b/DDG4/src/Geant4ParticlePrint.cpp
index af5b4e3efd07befb698e2b25fa462a5ef3e02799..27e082177162c85bcdf306b7de8d580e69aa58a2 100644
--- a/DDG4/src/Geant4ParticlePrint.cpp
+++ b/DDG4/src/Geant4ParticlePrint.cpp
@@ -12,6 +12,7 @@
 #include "DD4hep/InstanceCount.h"
 #include "DDG4/Geant4ParticlePrint.h"
 #include "DDG4/Geant4Data.h"
+#include "DDG4/Geant4HitCollection.h"
 #include <cstring>
 
 #include "G4Event.hh"
@@ -30,6 +31,7 @@ Geant4ParticlePrint::Geant4ParticlePrint(Geant4Context* context, const std::stri
   declareProperty("PrintBegin",m_printBegin=false);
   declareProperty("PrintEnd",  m_printEnd=true);
   declareProperty("PrintGen",  m_printGeneration=true);
+  declareProperty("PrintHits", m_printHits=false);
   InstanceCount::increment(this);
 }
 
@@ -39,13 +41,13 @@ Geant4ParticlePrint::~Geant4ParticlePrint()  {
 }
 
 /// Print particle table
-void Geant4ParticlePrint::makePrintout(int event_id) const  {
+void Geant4ParticlePrint::makePrintout(const G4Event* e) const  {
   Geant4ParticleMap* parts = context()->event().extension<Geant4ParticleMap>();
   if ( parts )   {
     const ParticleMap& particles = parts->particles();
-    print("+++ ******** MC Particle Printout for event ID:%d ********",event_id);
-    if ( (m_outputType&2) != 0 ) printParticleTree(particles);  // Tree printout....
-    if ( (m_outputType&1) != 0 ) printParticles(particles);     // Table printout....
+    print("+++ ******** MC Particle Printout for event ID:%d ********",e->GetEventID());
+    if ( (m_outputType&2) != 0 ) printParticleTree(e,particles);  // Tree printout....
+    if ( (m_outputType&1) != 0 ) printParticles(0,particles);     // Table printout....
     return;
   }
   except("No Geant4MonteCarloTruth object present in the event structure to access the particle information!", c_name());
@@ -53,20 +55,20 @@ void Geant4ParticlePrint::makePrintout(int event_id) const  {
 
 /// Generation action callback
 void Geant4ParticlePrint::operator()(G4Event* e)  {
-  if ( m_printGeneration ) makePrintout(e->GetEventID());
+  if ( m_printGeneration ) makePrintout(e);
 }
 
 /// Pre-event action callback
 void Geant4ParticlePrint::begin(const G4Event* e)  {
-  if ( m_printBegin ) makePrintout(e->GetEventID());
+  if ( m_printBegin ) makePrintout(e);
 }
 
 /// Post-event action callback
 void Geant4ParticlePrint::end(const G4Event* e)  {
-  if ( m_printEnd ) makePrintout(e->GetEventID());
+  if ( m_printEnd ) makePrintout(e);
 }
 
-void Geant4ParticlePrint::printParticle(const std::string& prefix, Geant4ParticleHandle p) const   {
+void Geant4ParticlePrint::printParticle(const std::string& prefix, const G4Event* e, Geant4ParticleHandle p) const   {
   char equiv[32];
   PropertyMask mask(p->reason);
   PropertyMask status(p->status);
@@ -101,10 +103,45 @@ void Geant4ParticlePrint::printParticle(const std::string& prefix, Geant4Particl
 	status.isSet(G4PARTICLE_GEN_DECAYED) ? 'D' : '.',
 	status.isSet(G4PARTICLE_GEN_DOCUMENTATION) ? 'd' : '.'
 	);
+  if ( e && m_printHits )  {
+    Geant4ParticleMap* truth = context()->event().extension<Geant4ParticleMap>();
+    G4HCofThisEvent* hc = e->GetHCofThisEvent();
+    for (int ihc=0, nhc=hc->GetNumberOfCollections(); ihc<nhc; ++ihc)   {
+      G4VHitsCollection* c = hc->GetHC(ihc);
+      Geant4HitCollection* coll = dynamic_cast<Geant4HitCollection*>(c);
+      size_t nhits = coll->GetSize();
+      for(size_t i=0; i<nhits; ++i)   {
+	Geant4HitData* h = coll->hit(i);
+	Geant4Tracker::Hit* trk_hit = dynamic_cast<Geant4Tracker::Hit*>(h);
+	if ( 0 != trk_hit )   {
+	  Geant4HitData::Contribution& t = trk_hit->truth;
+	  int trackID = t.trackID;
+	  int trueID  = truth->particleID(trackID);
+	  if ( trueID == p->id )   {
+	    print("+++ %20s           %s[%d]  (%+.2e,%+.2e,%+.2e)[mm]","",c->GetName().c_str(),i,
+		  trk_hit->position.x(),trk_hit->position.y(),trk_hit->position.z());
+	  }
+	}
+	Geant4Calorimeter::Hit* cal_hit = dynamic_cast<Geant4Calorimeter::Hit*>(h);
+	if ( 0 != cal_hit )   {
+	  Geant4HitData::Contributions& contrib = cal_hit->truth;
+	  for(Geant4HitData::Contributions::iterator j=contrib.begin(); j!=contrib.end(); ++j)  {
+	    Geant4HitData::Contribution& t = *j;
+	    int trackID = t.trackID;
+	    int trueID  = truth->particleID(trackID);
+	    if ( trueID == p->id )   {
+	      print("+++ %20s           %s[%d]  (%+.2e,%+.2e,%+.2e)[mm]","",c->GetName().c_str(),i,
+		    cal_hit->position.x(),cal_hit->position.y(),cal_hit->position.z());
+	    }
+	  }
+	}
+      }
+    }
+  }
 }
 
 /// Print record of kept particles
-void Geant4ParticlePrint::printParticles(const ParticleMap& particles) const  {
+void Geant4ParticlePrint::printParticles(const G4Event* e, const ParticleMap& particles) const  {
   int num_energy = 0;
   int num_parent = 0;
   int num_process = 0;
@@ -119,7 +156,7 @@ void Geant4ParticlePrint::printParticles(const ParticleMap& particles) const  {
   for(ParticleMap::const_iterator i=particles.begin(); i!=particles.end(); ++i)  {
     Geant4ParticleHandle p = (*i).second;
     PropertyMask mask(p->reason);
-    printParticle("MC Particle Track",p);
+    printParticle("MC Particle Track",e, p);
     num_secondaries += int(p->daughters.size());
     if ( mask.isSet(G4PARTICLE_ABOVE_ENERGY_THRESHOLD) ) ++num_energy;
     if ( mask.isSet(G4PARTICLE_PRIMARY) ) ++num_primary;
@@ -136,7 +173,7 @@ void Geant4ParticlePrint::printParticles(const ParticleMap& particles) const  {
 	num_calo_hits,num_tracker_hits,num_process,num_parent);
 }
 
-void Geant4ParticlePrint::printParticleTree(const ParticleMap& particles, int level, Geant4ParticleHandle p)  const  {
+void Geant4ParticlePrint::printParticleTree(const G4Event* e, const ParticleMap& particles, int level, Geant4ParticleHandle p)  const  {
   char txt[32];
   size_t len = sizeof(txt)-1;
   // Ensure we do not overwrite the array
@@ -149,18 +186,18 @@ void Geant4ParticlePrint::printParticleTree(const ParticleMap& particles, int le
   txt[level+6]='+';
   ::memset(txt+level+6+1,'-',len-level-3-6);
 
-  printParticle(txt, p);
+  printParticle(txt, e, p);
   const set<int>& daughters = p->daughters;
   // For all particles, the set of daughters must be contained in the record.
   for(set<int>::const_iterator id=daughters.begin(); id!=daughters.end(); ++id)   {
     int id_dau = *id;
     Geant4ParticleHandle dau = (*particles.find(id_dau)).second;
-    printParticleTree(particles,level+1,dau);
+    printParticleTree(e, particles, level+1, dau);
   }
 }
 
 /// Print tree of kept particles
-void Geant4ParticlePrint::printParticleTree(const ParticleMap& particles)  const  {
+void Geant4ParticlePrint::printParticleTree(const G4Event* e, const ParticleMap& particles)  const  {
   print("+++ MC Particle Parent daughter relationships. [%d particles]",int(particles.size()));
   print("+++ MC Particles %12s #Tracks:%7d %-12s Parent%-7s "
 	"Primary Secondary Energy %-8s Calo Tracker Process/Par  Details",
@@ -168,6 +205,6 @@ void Geant4ParticlePrint::printParticleTree(const ParticleMap& particles)  const
   for(ParticleMap::const_iterator i=particles.begin(); i!=particles.end(); ++i)  {
     Geant4ParticleHandle p = (*i).second;
     PropertyMask mask(p->reason);
-    if ( mask.isSet(G4PARTICLE_PRIMARY) ) printParticleTree(particles,0,p);
+    if ( mask.isSet(G4PARTICLE_PRIMARY) ) printParticleTree(e, particles, 0, p);
   }
 }
diff --git a/DDG4/src/Geant4PrimaryHandler.cpp b/DDG4/src/Geant4PrimaryHandler.cpp
index bdbd15065825e1ed58b493cac6c485a6b861ee3e..687aed5d7e58635d6d715d2c0e105c457dc9b9d8 100644
--- a/DDG4/src/Geant4PrimaryHandler.cpp
+++ b/DDG4/src/Geant4PrimaryHandler.cpp
@@ -9,22 +9,11 @@
 // Framework include files
 #include "DD4hep/Printout.h"
 #include "DD4hep/InstanceCount.h"
-#include "DDG4/Geant4Primary.h"
+#include "DDG4/Geant4InputHandling.h"
 #include "DDG4/Geant4PrimaryHandler.h"
 
-#include "G4Event.hh"
-#include "G4PrimaryVertex.hh"
-#include "G4PrimaryParticle.hh"
-
-#include <stdexcept>
-
-using namespace std;
-using namespace DD4hep;
 using namespace DD4hep::Simulation;
 
-typedef Geant4PrimaryInteraction Interaction;
-typedef ReferenceBitMask<int> PropertyMask;
-
 /// Standard constructor
 Geant4PrimaryHandler::Geant4PrimaryHandler(Geant4Context* context, const std::string& nam)
   : Geant4GeneratorAction(context,nam)
@@ -37,109 +26,7 @@ Geant4PrimaryHandler::~Geant4PrimaryHandler()  {
   InstanceCount::decrement(this);
 }
 
-static G4PrimaryParticle* createG4Primary(const Geant4ParticleHandle p)  {
-  G4PrimaryParticle* g4 = new G4PrimaryParticle(p->pdgID, p->psx, p->psy, p->psz);
-  g4->SetMass(p->mass);
-  return g4;
-}
-
-typedef map<Geant4Particle*,G4PrimaryParticle*> Primaries;
-Primaries getRelevant(set<int>& visited,
-						    map<int,G4PrimaryParticle*>& prim,
-						    Interaction::ParticleMap& pm, 
-						    const Geant4ParticleHandle p)  
-{
-  Primaries res;
-  visited.insert(p->id);
-  PropertyMask status(p->status);
-  if ( status.isSet(G4PARTICLE_GEN_STABLE) )  {
-    if ( prim.find(p->id) == prim.end() )  {
-      G4PrimaryParticle* p4 = createG4Primary(p);
-      prim[p->id] = p4;
-      res.insert(make_pair(p,p4));
-    }
-  }
-  else if ( p->daughters.size() > 0 )  {
-    const Geant4Particle::Particles& dau = p->daughters;
-    int first_daughter = *(dau.begin());
-    Geant4ParticleHandle dp = pm[first_daughter];
-    double en = p.energy();
-    double me = en > std::numeric_limits<double>::epsilon() ? p->mass / en : 0.0;
-    //  fix by S.Morozov for real != 0
-    double proper_time = fabs(dp->time-p->time) * me;
-    double proper_time_Precision =  pow(10.,-DBL_DIG)*me*fmax(fabs(p->time),fabs(dp->time));
-    bool isProperTimeZero = ( proper_time <= proper_time_Precision ) ;
-    // -- remove original --- if (proper_time != 0) {
-    if ( !isProperTimeZero ) {
-      map<int,G4PrimaryParticle*>::iterator ip4 = prim.find(p->id);
-      G4PrimaryParticle* p4 = (ip4 == prim.end()) ? 0 : (*ip4).second;
-      if ( !p4 )  {
-	p4 = createG4Primary(p);
-	p4->SetProperTime(proper_time);
-	prim[p->id] = p4;
-	Primaries daughters;
-	for(Geant4Particle::Particles::const_iterator i=dau.begin(); i!=dau.end(); ++i)  {
-	  if ( visited.find(*i) == visited.end() )  {
-	    Primaries tmp = getRelevant(visited,prim,pm,pm[*i]);
-	    daughters.insert(tmp.begin(),tmp.end());
-	  }
-	}
-	for(Primaries::iterator i=daughters.begin(); i!=daughters.end(); ++i)
-	  p4->SetDaughter((*i).second);
-      }
-      res.insert(make_pair(p,p4));
-    }
-    else  {
-      for(Geant4Particle::Particles::const_iterator i=dau.begin(); i!=dau.end(); ++i)  {
-	if ( visited.find(*i) == visited.end() )  {
-	  Primaries tmp = getRelevant(visited,prim,pm,pm[*i]);
-	  res.insert(tmp.begin(),tmp.end());
-	}
-      }
-    }
-  }
-  return res;
-}
-
 /// Event generation action callback
 void Geant4PrimaryHandler::operator()(G4Event* event)  {
-  Geant4PrimaryMap* primaries   = context()->event().extension<Geant4PrimaryMap>();
-  Interaction*      interaction = context()->event().extension<Interaction>();
-  Interaction::ParticleMap& pm  = interaction->particles;
-  Interaction::VertexMap&   vm  = interaction->vertices;
-  map<int,G4PrimaryParticle*> prim;
-  set<int> visited;
-
-  Geant4PrimaryInteraction::VertexMap::iterator ivfnd, iv, ivend;
-  for(Interaction::VertexMap::const_iterator iend=vm.end(),i=vm.begin(); i!=iend; ++i)  {
-    int num_part = 0;
-    Geant4Vertex* v = (*i).second;
-    G4PrimaryVertex* v4 = new G4PrimaryVertex(v->x,v->y,v->z,v->time);
-    event->AddPrimaryVertex(v4);
-    print("+++++ G4PrimaryVertex at (%+.2e,%+.2e,%+.2e) [mm] %+.2e [ns]",
-	  v->x/mm,v->y/mm,v->z/mm,v->time/ns);    
-    for(Geant4Vertex::Particles::const_iterator ip=v->out.begin(); ip!=v->out.end(); ++ip)  {
-      Geant4ParticleHandle p = pm[*ip];
-      if ( p->parents.size() == 0 )  {
-	Primaries relevant = getRelevant(visited,prim,pm,p);
-	for(Primaries::const_iterator j=relevant.begin(); j!= relevant.end(); ++j)  {
-	  Geant4ParticleHandle r = (*j).first;
-	  G4PrimaryParticle* p4 = (*j).second;
-	  PropertyMask reason(r->reason);
-	  reason.set(G4PARTICLE_PRIMARY);
-	  v4->SetPrimary(p4);
-	  printM1("+++ +-> G4Primary[%3d] ID:%3d type:%9d/%-12s "
-		  "Momentum:(%+.2e,%+.2e,%+.2e) [GeV] time:%+.2e [ns] #Par:%3d #Dau:%3d",
-		  num_part,r->id,r->pdgID,r.particleName().c_str(),
-		  r->psx/GeV,r->psy/GeV,r->psz/GeV,r->time/ns,
-		  int(r->parents.size()),int(r->daughters.size()));
-	  ++num_part;
-	}
-      }
-    }
-  }
-  for(map<int,G4PrimaryParticle*>::iterator i=prim.begin(); i!=prim.end(); ++i)  {
-    Geant4ParticleHandle p = pm[(*i).first];
-    primaries->primaryMap[(*i).second] = p->addRef();
-  }
+  generatePrimaries(this, context(), event);
 }
diff --git a/DDG4/src/Geant4UIManager.cpp b/DDG4/src/Geant4UIManager.cpp
index 459626226c8322aae76b43588a25e0eb120edc11..97ebd1d9b0900587de40a854cac3cef4754f87a4 100644
--- a/DDG4/src/Geant4UIManager.cpp
+++ b/DDG4/src/Geant4UIManager.cpp
@@ -108,6 +108,6 @@ void Geant4UIManager::start() {
 
 /// Stop and release resources
 void Geant4UIManager::stop() {
-  // deletePtr(m_vis);
-  //deletePtr(m_ui);
+  deletePtr(m_vis);
+  deletePtr(m_ui);
 }