From f96763a7399646d3b72a64a3eded177eaebc3fc7 Mon Sep 17 00:00:00 2001
From: Markus Frank <markus.frank@cern.ch>
Date: Mon, 15 Sep 2014 09:44:42 +0000
Subject: [PATCH] Improces DDG4 MC thruth and LCIO I/O. Please see
 doc/release.notes

---
 DDCore/include/DD4hep/Primitives.h            |   7 +-
 DDEve/DDEve/DDG4IO.C                          |  28 +-
 DDG4/CMakeLists.txt                           |   2 +-
 DDG4/examples/CLICSidSimu.py                  | 110 ++++--
 DDG4/include/DDG4/Geant4Action.h              | 100 ++---
 DDG4/include/DDG4/Geant4Context.h             |  12 +-
 DDG4/include/DDG4/Geant4Data.h                |  95 ++---
 DDG4/include/DDG4/Geant4DataConversion.h      |   6 +
 DDG4/include/DDG4/Geant4DataDump.h            |   4 +-
 DDG4/include/DDG4/Geant4GeneratorActionInit.h |  75 ++++
 DDG4/include/DDG4/Geant4HitCollection.h       |  27 +-
 DDG4/include/DDG4/Geant4InteractionMerger.h   |  42 +++
 .../DDG4/Geant4InteractionVertexBoost.h       |  49 +++
 .../DDG4/Geant4InteractionVertexSmear.h       |  51 +++
 DDG4/include/DDG4/Geant4IsotropeGenerator.h   |  55 +++
 DDG4/include/DDG4/Geant4MonteCarloTruth.h     |   3 +-
 DDG4/include/DDG4/Geant4Particle.h            | 303 +++++++++++++++
 DDG4/include/DDG4/Geant4ParticleGun.h         |   5 -
 DDG4/include/DDG4/Geant4ParticleHandler.h     |  30 +-
 DDG4/include/DDG4/Geant4ParticlePrint.h       |  25 +-
 DDG4/include/DDG4/Geant4Primary.h             | 150 ++++++++
 DDG4/include/DDG4/Geant4PrimaryHandler.h      |  42 +++
 DDG4/include/DDG4/Geant4Random.h              |  69 ++++
 DDG4/include/DDG4/Geant4SensDetAction.h       |  13 +-
 DDG4/include/DDG4/Geant4UserParticleHandler.h |   4 +-
 DDG4/include/DDG4/Geant4Vertex.h              |  72 ++++
 DDG4/lcio/EventReader.cpp                     | 303 ---------------
 DDG4/lcio/EventReader.h                       | 125 -------
 DDG4/lcio/Geant4Output2LCIO.cpp               |  28 +-
 DDG4/lcio/HepEventReader.cpp                  |  14 +-
 DDG4/lcio/LCIOConversions.cpp                 | 159 ++++----
 DDG4/lcio/LCIOEventReader.cpp                 |  20 +
 DDG4/lcio/LCIOEventReader.h                   |  82 +++++
 ...LcioEventReader.cpp => LCIOFileReader.cpp} |  32 +-
 DDG4/lcio/LCIOInputAction.cpp                 | 344 +++++++++++++++++
 DDG4/lcio/LCIOInputAction.h                   |  87 +++++
 DDG4/lcio/LCIOMCParticles.cpp                 | 150 ++++++++
 ...oStdHepReader.cpp => LCIOStdHepReader.cpp} |  35 +-
 DDG4/plugins/Geant4EscapeCounter.cpp          |   5 +-
 DDG4/plugins/Geant4Factories.cpp              |  22 ++
 DDG4/python/DDG4Dict.C                        |  11 +-
 DDG4/src/Geant4Action.cpp                     | 125 +++----
 DDG4/src/Geant4Context.cpp                    |   4 +-
 DDG4/src/Geant4Data.cpp                       | 107 +-----
 DDG4/src/Geant4DataConversion.cpp             |  14 +-
 DDG4/src/Geant4DataDump.cpp                   |   7 +-
 DDG4/src/Geant4Exec.cpp                       |   8 +-
 DDG4/src/Geant4GeneratorActionInit.cpp        |  81 ++++
 DDG4/src/Geant4HitCollection.cpp              |  10 +
 DDG4/src/Geant4InteractionMerger.cpp          |  93 +++++
 DDG4/src/Geant4InteractionVertexBoost.cpp     |  99 +++++
 DDG4/src/Geant4InteractionVertexSmear.cpp     |  84 +++++
 DDG4/src/Geant4IsotropeGenerator.cpp          |  92 +++++
 DDG4/src/Geant4Output2ROOT.cpp                |  14 +-
 DDG4/src/Geant4Particle.cpp                   | 315 ++++++++++++++++
 DDG4/src/Geant4ParticleGun.cpp                |  18 +-
 DDG4/src/Geant4ParticleHandler.cpp            | 346 ++++++++++++------
 DDG4/src/Geant4ParticlePrint.cpp              | 121 +++---
 DDG4/src/Geant4Primary.cpp                    | 119 ++++++
 DDG4/src/Geant4PrimaryHandler.cpp             |  71 ++++
 DDG4/src/Geant4ROOTDump.cpp                   |   7 +-
 DDG4/src/Geant4Random.cpp                     |  82 +++++
 DDG4/src/Geant4SensDetAction.cpp              |   6 +-
 DDG4/src/Geant4TestActions.cpp                |  32 +-
 DDG4/src/Geant4Vertex.cpp                     |  61 +++
 UtilityApps/src/run_plugin.h                  |   2 +-
 doc/release.notes                             |  13 +
 67 files changed, 3576 insertions(+), 1151 deletions(-)
 create mode 100644 DDG4/include/DDG4/Geant4GeneratorActionInit.h
 create mode 100644 DDG4/include/DDG4/Geant4InteractionMerger.h
 create mode 100644 DDG4/include/DDG4/Geant4InteractionVertexBoost.h
 create mode 100644 DDG4/include/DDG4/Geant4InteractionVertexSmear.h
 create mode 100644 DDG4/include/DDG4/Geant4IsotropeGenerator.h
 create mode 100644 DDG4/include/DDG4/Geant4Particle.h
 create mode 100644 DDG4/include/DDG4/Geant4Primary.h
 create mode 100644 DDG4/include/DDG4/Geant4PrimaryHandler.h
 create mode 100644 DDG4/include/DDG4/Geant4Random.h
 create mode 100644 DDG4/include/DDG4/Geant4Vertex.h
 delete mode 100644 DDG4/lcio/EventReader.cpp
 delete mode 100644 DDG4/lcio/EventReader.h
 create mode 100644 DDG4/lcio/LCIOEventReader.cpp
 create mode 100644 DDG4/lcio/LCIOEventReader.h
 rename DDG4/lcio/{LcioEventReader.cpp => LCIOFileReader.cpp} (66%)
 create mode 100644 DDG4/lcio/LCIOInputAction.cpp
 create mode 100644 DDG4/lcio/LCIOInputAction.h
 create mode 100644 DDG4/lcio/LCIOMCParticles.cpp
 rename DDG4/lcio/{LcioStdHepReader.cpp => LCIOStdHepReader.cpp} (62%)
 create mode 100644 DDG4/src/Geant4GeneratorActionInit.cpp
 create mode 100644 DDG4/src/Geant4InteractionMerger.cpp
 create mode 100644 DDG4/src/Geant4InteractionVertexBoost.cpp
 create mode 100644 DDG4/src/Geant4InteractionVertexSmear.cpp
 create mode 100644 DDG4/src/Geant4IsotropeGenerator.cpp
 create mode 100644 DDG4/src/Geant4Particle.cpp
 create mode 100644 DDG4/src/Geant4Primary.cpp
 create mode 100644 DDG4/src/Geant4PrimaryHandler.cpp
 create mode 100644 DDG4/src/Geant4Random.cpp
 create mode 100644 DDG4/src/Geant4Vertex.cpp

diff --git a/DDCore/include/DD4hep/Primitives.h b/DDCore/include/DD4hep/Primitives.h
index f68088aec..df05dd66d 100644
--- a/DDCore/include/DD4hep/Primitives.h
+++ b/DDCore/include/DD4hep/Primitives.h
@@ -134,6 +134,11 @@ namespace DD4hep {
       delete p;
     p = 0;
   }
+  /// Helper to delete objects from heap and reset the pointer. Saves many many lines of code
+  template <typename T> inline void deleteObject(T* p) {
+    if (0 != p)
+      delete p;
+  }
   /// Helper to delete objects from heap and reset the pointer
   template <typename T> inline void destroyObject(T*& p) {
     deletePtr(p);
@@ -236,7 +241,7 @@ namespace DD4hep {
     void set(const T& m)   {
       mask |= m;
     }
-    bool isSet(const T& m)   {
+    bool isSet(const T& m)  const {
       return (mask&m) == m;
     }
     bool testBit(int bit) const  {
diff --git a/DDEve/DDEve/DDG4IO.C b/DDEve/DDEve/DDG4IO.C
index 8c349f570..15dde5880 100644
--- a/DDEve/DDEve/DDG4IO.C
+++ b/DDEve/DDEve/DDG4IO.C
@@ -21,6 +21,7 @@ namespace DD4hep { namespace Geometry {
 class G4Step;
 class G4StepPoint;
 #include "DDG4/Geant4Data.h"
+#include "DDG4/Geant4Particle.h"
 #include "DDEve/DDEveEventData.h"
 
 #ifdef __DD4HEP_DDEVE_EXCLUSIVE__
@@ -34,7 +35,7 @@ namespace DD4hep {
    *   Simulation namespace declaration
    */
   namespace Simulation {
-    #define NO_CALL {      throw "This function shoule never ever be called!";    }
+#define NO_CALL {      throw "This function shoule never ever be called!";    }
     /// Default constructor
     inline SimpleRun::SimpleRun() {    }
     /// Default destructor
@@ -46,15 +47,22 @@ namespace DD4hep {
 
     /// Default destructor
     inline DataExtension::~DataExtension()  {    }
+    /// Default destructor
+    inline DataExtension::~ParticleExtension()  {    }
     /// Default constructor
-    inline Particle::Particle()   {     }
+    inline Geant4Particle::Geant4Particle()   {     }
     /// Copy constructor
-    inline Particle::Particle(const Particle&)   {  NO_CALL   }
+    inline Geant4Particle::Geant4Particle(const Geant4Particle&)   {  NO_CALL   }
     /// Default destructor
-    inline Particle::~Particle()   {     }
+    inline Geant4Particle::~Geant4Particle()   {     }
     /// Remove daughter from set
-    inline void Particle::removeDaughter(int)   {   NO_CALL  }
-
+    inline void Geant4Particle::removeDaughter(int)   {   NO_CALL  }
+    /// Default destructor
+    inline Geant4PrimaryMap::~Geant4PrimaryMap();
+    /// Default destructor
+    inline Geant4ParticleMap::~Geant4ParticleMap() {     }
+    /// Access the equivalent track id (shortcut to the usage of TrackEquivalents)
+    inline int Geant4ParticleMap::particleID(int, bool) const   {   NO_CALL  }
     /// Default constructor
     inline SimpleHit::SimpleHit()   {    }
     /// Default destructor
@@ -92,8 +100,8 @@ namespace DD4hep {
 #pragma link C++ class DD4hep::Simulation::SimpleEvent+;
 
 #pragma link C++ class DD4hep::Simulation::DataExtension+;
-#pragma link C++ class DD4hep::Simulation::Particle+;
-#pragma link C++ class std::vector<DD4hep::Simulation::Particle*>+;
+#pragma link C++ class DD4hep::Simulation::Geant4Particle+;
+#pragma link C++ class std::vector<DD4hep::Simulation::Geant4Particle*>+;
 
 #pragma link C++ class DD4hep::Simulation::SimpleHit+;
 #pragma link C++ class std::vector<DD4hep::Simulation::SimpleHit*>+;
@@ -132,7 +140,7 @@ namespace {
     if (source )  {
       static TClass* cl_calo = gROOT->GetClass(typeid(SimpleCalorimeter::Hit));
       static TClass* cl_tracker = gROOT->GetClass(typeid(SimpleTracker::Hit));
-      //static TClass* cl_particles = gROOT->GetClass(typeid(Particle));
+      //static TClass* cl_particles = gROOT->GetClass(typeid(Geant4Particle));
       void* result = 0;
       SimpleHit* hit = (SimpleHit*)source;
       const std::type_info& type = typeid(*hit);
@@ -145,7 +153,7 @@ namespace {
 
   void* _convertParticleFunc(void* source, DDEveParticle* p)  {
     if (source )  {
-      Particle* s = (Particle*)source;
+      Geant4Particle* s = (Geant4Particle*)source;
       p->id = s->id;
       p->vsx = s->vsx;
       p->vsy = s->vsy;
diff --git a/DDG4/CMakeLists.txt b/DDG4/CMakeLists.txt
index 80b396893..da5eedb16 100644
--- a/DDG4/CMakeLists.txt
+++ b/DDG4/CMakeLists.txt
@@ -48,7 +48,7 @@ if(DD4HEP_USE_LCIO)
   include_directories(  ${LCIO_INCLUDE_DIRS} )
   file(GLOB lcio_sources lcio/*.cpp)
   add_library(DD4hepG4LCIO SHARED ${lcio_sources})
-  target_link_libraries(DD4hepG4LCIO DD4hepCore DD4hepG4 ${Geant4_LIBRARIES} ${LCIO_LIBRARIES} ${ROOT_LIBRARIES} Reflex)
+  target_link_libraries(DD4hepG4LCIO DD4hepCore DD4hepG4 ${Geant4_LIBRARIES} ${LCIO_LIBRARIES} ${ROOT_LIBRARIES} Reflex EG)
   SET_TARGET_PROPERTIES(DD4hepG4LCIO PROPERTIES VERSION ${DD4hep_VERSION} SOVERSION ${DD4hep_SOVERSION})
   dd4hep_generate_rootmap(DD4hepG4LCIO)
 endif()
diff --git a/DDG4/examples/CLICSidSimu.py b/DDG4/examples/CLICSidSimu.py
index c09e83475..24f690fb4 100644
--- a/DDG4/examples/CLICSidSimu.py
+++ b/DDG4/examples/CLICSidSimu.py
@@ -36,42 +36,102 @@ def run():
   kernel.runAction().adopt(run1)
 
   # Configure Event actions
-  evt2 = DDG4.EventAction(kernel,'Geant4TestEventAction/UserEvent_2')
-  evt2.Property_int    = 123454321
-  evt2.Property_double = 5e15*GeV
-  evt2.Property_string = 'Hello_2 from the python setup'
-  evt2.enableUI()
-  kernel.registerGlobalAction(evt2)
-
-  evt1 = DDG4.EventAction(kernel,'Geant4TestEventAction/UserEvent_1')
-  evt1.Property_int=01234
-  evt1.Property_double=1e11
-  evt1.Property_string='Hello_1'
-  evt1.enableUI()
-
-  kernel.eventAction().adopt(evt1)
-  kernel.eventAction().adopt(evt2)
-
   prt = DDG4.EventAction(kernel,'Geant4ParticlePrint/ParticlePrint')
-  prt.OutputType = 3 # Print both: table and tree
+  prt.OutputLevel = Output.INFO
+  prt.OutputType  = 3 # Print both: table and tree
   kernel.eventAction().adopt(prt)
 
   # 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
+  # Setup particle gun
+  #gun = simple.setupGun('Gun','pi-',energy=10*GeV,isotrop=True,multiplicity=3)
 
-  gen = DDG4.GeneratorAction(kernel,"Geant4TestGeneratorAction/Generate")
+  gen = DDG4.GeneratorAction(kernel,"Geant4GeneratorActionInit/GenerationInit")
   kernel.generatorAction().adopt(gen)
 
-  # Setup particle gun
-  gun = simple.setupGun('Gun','pi-',energy=10*GeV,isotrop=True,multiplicity=3)
+  """
+  # First particle generator: pi+
+  gen = DDG4.GeneratorAction(kernel,"Geant4IsotropeGenerator/IsotropPi+");
+  gen.particle = 'pi+'
+  gen.energy = 100 * GeV
+  gen.multiplicity = 2
+  gen.mask = 1
+  kernel.generatorAction().adopt(gen)
+  # Install vertex smearing for this interaction
+  gen = DDG4.GeneratorAction(kernel,"Geant4InteractionVertexSmear/SmearPi+");
+  gen.mask = 1
+  gen.offset = (20*mm, 10*mm, 10*mm, 0*ns)
+  gen.sigma = (4*mm, 1*mm, 1*mm, 0*ns)
+  kernel.generatorAction().adopt(gen)
+
+  # Second particle generator: e-
+  gen = DDG4.GeneratorAction(kernel,"Geant4IsotropeGenerator/IsotropE-");
+  gen.particle = 'e-'
+  gen.energy = 25 * GeV
+  gen.multiplicity = 3
+  gen.mask = 2
+  kernel.generatorAction().adopt(gen)
+  # Install vertex smearing for this interaction
+  gen = DDG4.GeneratorAction(kernel,"Geant4InteractionVertexSmear/SmearE-");
+  gen.mask = 2
+  gen.offset = (-20*mm, -10*mm, -10*mm, 0*ns)
+  gen.sigma = (12*mm, 8*mm, 8*mm, 0*ns)
+  kernel.generatorAction().adopt(gen)
+  """
+
+  generator_output_level = Output.INFO
+
+  # First particle file reader
+  gen = DDG4.GeneratorAction(kernel,"LCIOInputAction/LCIO1");
+  gen.Input = "LCIOStdHepReader|/home/frankm/SW/data/e2e2nn_gen_1343_1.stdhep"
+  gen.OutputLevel = 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");  
+  gen.OutputLevel = 4 #generator_output_level
+  gen.Mask = 1
+  gen.Offset = (-20*mm, -10*mm, -10*mm, 0*ns)
+  gen.Sigma = (12*mm, 8*mm, 8*mm, 0*ns)
+  kernel.generatorAction().adopt(gen)
+
+  # Second particle file reader
+  gen = DDG4.GeneratorAction(kernel,"LCIOInputAction/LCIO2");
+  gen.Input = "LCIOStdHepReader|/home/frankm/SW/data/e2e2nn_gen_1343_2.stdhep"
+  gen.OutputLevel = generator_output_level
+  gen.Mask = 2
+  gen.MomentumScale = 0.1
+  kernel.generatorAction().adopt(gen)
+  # Install vertex smearing for this interaction
+  gen = DDG4.GeneratorAction(kernel,"Geant4InteractionVertexSmear/Smear2");
+  gen.OutputLevel = generator_output_level
+  gen.Mask = 2
+  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
+  gen = DDG4.GeneratorAction(kernel,"Geant4InteractionMerger/InteractionMerger")
+  gen.OutputLevel = generator_output_level
+  kernel.generatorAction().adopt(gen)
+
+  # Finally generate Geant4 primaries
+  gen = DDG4.GeneratorAction(kernel,"Geant4PrimaryHandler/PrimaryHandler")
+  gen.OutputLevel = generator_output_level
+  kernel.generatorAction().adopt(gen)
 
-  trk = DDG4.GeneratorAction(kernel,"Geant4ParticleHandler/ParticleHandler")
-  kernel.generatorAction().adopt(trk)
-  trk.saveProcesses = ['conv','Decay']
-  trk.enableUI()
+  # And handle the simulation particles.
+  part = DDG4.GeneratorAction(kernel,"Geant4ParticleHandler/ParticleHandler")
+  kernel.generatorAction().adopt(part)
+  #part.SaveProcesses = ['conv','Decay']
+  part.SaveProcesses = ['Decay']
+  part.OutputLevel = generator_output_level
+  part.enableUI()
   user = DDG4.Action(kernel,"Geant4UserParticleHandler/UserParticleHandler")
-  trk.adopt(user)
+  part.adopt(user)
 
   """
   rdr = DDG4.GeneratorAction(kernel,"LcioGeneratorAction/Reader")
diff --git a/DDG4/include/DDG4/Geant4Action.h b/DDG4/include/DDG4/Geant4Action.h
index 172395aff..1daffe7d0 100644
--- a/DDG4/include/DDG4/Geant4Action.h
+++ b/DDG4/include/DDG4/Geant4Action.h
@@ -67,61 +67,13 @@ namespace DD4hep {
       static TypeName split(const std::string& type_name, const std::string& delim);
     };
 
-#if 0
-
-    /** @class Geant4UserTrajectory Geant4Action.h DDG4/Geant4Action.h
-     *
-     * @author  M.Frank
-     * @version 1.0
-     */
-    struct Geant4UserTrajectory {
-      /// Default constructor
-      Geant4UserTrajectory();
-      /// Standard destructor
-      virtual ~Geant4UserTrajectory();
-      /// accessors
-      virtual int trackID() const = 0;
-      virtual int parentID() const = 0;
-      virtual std::string particleName() const = 0;
-      virtual double charge() const = 0;
-      virtual int pdgID() const = 0;
-      virtual G4ThreeVector momentum() const = 0;
-      virtual int numPoints() const = 0;
-      virtual G4VTrajectoryPoint* point(int i) const = 0;
-    };
-
-    /** @class Geant4Trajectory Geant4Action.h DDG4/Geant4Action.h
-     *
-     * @author  M.Frank
-     * @version 1.0
-     */
-    struct Geant4Trajectory : public G4VTrajectory {
-      std::auto_ptr<Geant4UserTrajectory> trajectory;
-      /// Default constructor
-      Geant4Trajectory(Geant4UserTrajectory* traj);
-      /// Standard destructor
-      virtual ~Geant4Trajectory();
-      /// Mandatory G4 overloads: Get/Set functions
-      virtual G4int GetTrackID() const {return trajectory->trackID;}
-      virtual G4int GetParentID() const {return trajectory->parentID();}
-      virtual G4String GetParticleName() const {return trajectory->particleName();}
-      /// Mandatory G4 overloads:  Charge is that of G4DynamicParticle
-      virtual G4double GetCharge() const {return trajectory->charge();}
-      /// Mandatory G4 overloads:  Zero will be returned if the particle does not have PDG code.
-      virtual G4int GetPDGEncoding() const {return trajectory->pdgID();}
-      /// Mandatory G4 overloads:  Momentum at the origin of the track in global coordinate system.
-      virtual G4ThreeVector GetInitialMomentum() const {return trajectory->momentum();}
-
-      /// Mandatory G4 overloads:  Returns the number of trajectory points
-      virtual int GetPointEntries() const {return trajectory->numPoints();}
-      virtual G4VTrajectoryPoint* GetPoint(G4int i) const {return trajectory->point(i);}
-    };
-#endif
-
-    /// Default base class for all geant 4 actions and derivates thereof.
+    /// Default base class for all Geant 4 actions and derivates thereof.
     /**
-     * @author  M.Frank
-     * @version 1.0
+     *  This is a utility class supporting properties, output and access to 
+     *  event and run objects through the context.
+     *
+     *  @author  M.Frank
+     *  @version 1.0
      */
     class Geant4Action {
     protected:
@@ -327,39 +279,33 @@ namespace DD4hep {
       void installPropertyMessenger();
 
       /// Support for messages with variable output level using output level
-      void print(const std::string& fmt, ...) const;
-      /// Support for messages with variable output level using output level
-      void print(const std::string& tag, const std::string& fmt, ...) const;
+      void print(const char* fmt, ...) const;
+      /// Support for messages with variable output level using output level-1
+      void printM1(const char* fmt, ...) const;
+      /// Support for messages with variable output level using output level-2
+      void printM2(const char* fmt, ...) const;
+      /// Support for messages with variable output level using output level+1
+      void printP1(const char* fmt, ...) const;
+      /// Support for messages with variable output level using output level+2
+      void printP2(const char* fmt, ...) const;
 
       /// Support of debug messages.
-      void debug(const std::string& fmt, ...) const;
-      /// Support of warning messages.
-      void debug(const std::string& tag, const std::string& fmt, ...) const;
+      void debug(const char* fmt, ...) const;
       /// Support of info messages.
-      void info(const std::string& fmt, ...) const;
-      /// Support of warning messages.
-      void info(const std::string& tag, const std::string& fmt, ...) const;
+      void info(const char* fmt, ...) const;
       /// Support of warning messages.
-      void warning(const std::string& fmt, ...) const;
-      /// Support of warning messages.
-      void warning(const std::string& tag, const std::string& fmt, ...) const;
-      /// Support of error messages.
-      void error(const std::string& fmt, ...) const;
+      void warning(const char* fmt, ...) const;
       /// Support of error messages.
-      void error(const std::string& tag, const std::string& fmt, ...) const;
+      void error(const char* fmt, ...) const;
       /// Action to support error messages.
-      bool error(bool return_value, const std::string& fmt, ...) const;
+      bool error(bool return_value, const char* fmt, ...) const;
       /// Support of fatal messages. Throws exception
-      void fatal(const std::string& fmt, ...) const;
-      /// Support of warning messages.
-      void fatal(const std::string& tag, const std::string& fmt, ...) const;
+      void fatal(const char* fmt, ...) const;
       /// Support of exceptions: Print fatal message and throw runtime_error.
-      void except(const std::string& fmt, ...) const;
-      /// Support of warning messages.
-      void except(const std::string& tag, const std::string& fmt, ...) const;
+      void except(const char* fmt, ...) const;
 
       /// Abort Geant4 Run by throwing a G4Exception with type RunMustBeAborted
-      void abortRun(const std::string& exception, const std::string& fmt, ...) const;
+      void abortRun(const std::string& exception, const char* fmt, ...) const;
 
       /// Access to the main run action sequence from the kernel object
       Geant4RunActionSequence& runAction() const;
diff --git a/DDG4/include/DDG4/Geant4Context.h b/DDG4/include/DDG4/Geant4Context.h
index cd59f4aae..50a4c1c2e 100644
--- a/DDG4/include/DDG4/Geant4Context.h
+++ b/DDG4/include/DDG4/Geant4Context.h
@@ -39,6 +39,7 @@ namespace DD4hep {
     class Geant4Run;
     class Geant4Event;
     class Geant4Kernel;
+    class Geant4Random;
     class ContextUpdate;
     class Geant4RunActionSequence;
     class Geant4EventActionSequence;
@@ -110,21 +111,30 @@ namespace DD4hep {
      *  across different events.
      *  Hence: They are only useful to extend data of an event.
      *
+     *  Any random numbers used to process one event should be accessed
+     *  from this location. The framework ensures that the same seeded 
+     *  sequence is used throughout the processing of one single event.
+     *
      *  @author  M.Frank
      *  @version 1.0
      */
     class  Geant4Event : public ObjectExtensions  {
       /// Reference to the original Geant4 event object
       const G4Event* m_event;
+      /// Reference to the main random number generator
+      Geant4Random* m_random;
+
     public:
       /// Intializing constructor
-      Geant4Event(const G4Event* run);
+      Geant4Event(const G4Event* run, Geant4Random* rndm);
       /// Default destructor
       virtual ~Geant4Event();
       /// Access the G4Event directly: Automatic type conversion
       operator const G4Event&() const  {  return *m_event;   }
       /// Access the G4Event directly: Explicit G4Event accessor
       const G4Event& event() const     {  return *m_event;   }
+      /// Access the random number generator
+      Geant4Random& random() const     {  return *m_random;  }
 
       /// Add an extension object to the detector element
       /** Note:
diff --git a/DDG4/include/DDG4/Geant4Data.h b/DDG4/include/DDG4/Geant4Data.h
index 2009478be..3d51abafe 100644
--- a/DDG4/include/DDG4/Geant4Data.h
+++ b/DDG4/include/DDG4/Geant4Data.h
@@ -13,10 +13,14 @@
 #ifndef __DD4HEP_DDEVE_EXCLUSIVE__
 #include "DD4hep/Objects.h"
 #include "G4Step.hh"
+class G4PrimaryParticle;
 #else
-typedef void G4VProcess;
-typedef void G4ParticleDefinition;
+typedef void* G4Step;
+typedef void* G4StepPoint;
+typedef void* G4PrimaryParticle;
 #endif
+
+// C/C++ include files
 #include <set>
 #include <memory>
 
@@ -30,10 +34,15 @@ namespace DD4hep {
    */
   namespace Simulation {
 
-
+    // Forward type definitions
     typedef Geometry::Position Position;
     typedef Geometry::Position Direction;
 
+    // Forward declarations
+    class Geant4Particle;
+    class Geant4Vertex;
+    
+
     /** @class HitCompare Geant4Data.h DDG4/Geant4Data.h
      *
      *  Base class for hit comparisons.
@@ -112,59 +121,17 @@ namespace DD4hep {
       virtual ~DataExtension();      
     };
 
-    /// Track properties
-    enum ParticleProperties {
-      G4PARTICLE_CREATED_HIT = 1<<1, 
-      G4PARTICLE_PRIMARY = 1<<2,
-      G4PARTICLE_HAS_SECONDARIES = 1<<3,
-      G4PARTICLE_ABOVE_ENERGY_THRESHOLD = 1<<4,
-      G4PARTICLE_KEEP_PROCESS = 1<<5,
-      G4PARTICLE_KEEP_PARENT = 1<<6,
-      G4PARTICLE_CREATED_CALORIMETER_HIT = 1<<7,
-      G4PARTICLE_CREATED_TRACKER_HIT = 1<<8,
-      G4PARTICLE_KEEP_ALWAYS = 1<<9,
-      G4PARTICLE_LAST_NOTHING = 1<<31
-    };
-
-    /// Data structure to store the MC particle information 
-    /**
-     * @author  M.Frank
-     * @version 1.0
-     */
-    class Particle {
-    private:
-      /// Copy constructor
-      Particle(const Particle& c);
-    public:
-      int id, g4Parent, parent, reason, steps, secondaries, pdgID;
-      double vsx, vsy, vsz;
-      double vex, vey, vez;
-      double psx, psy, psz, pex, pey, pez, energy, time;
-      /// The list of daughters of this MC particle
-      std::set<int> daughters;
-      /// User data extension if required
-      std::auto_ptr<DataExtension> extension;  
-      const G4VProcess *process;  //!
-      const G4ParticleDefinition *definition;  //!
-      /// Default constructor
-      Particle();
-      /// Default destructor
-      virtual ~Particle();
-      /// Assignment operator
-      Particle& get_data(Particle& c);
-      /// Remove daughter from set
-      void removeDaughter(int id_daughter);
-    };
-
-    /** @class SimpleHit Geant4Data.h DDG4/Geant4Data.h
+    /// Base class for geant4 hit structures
+    /*
+     *  Base class for geant4 hit structures created by the
+     *  example sensitive detectors. This is a generic class
+     *  only dealing with the cellID. Users may add an extension 
+     *  object, which normally should not be necessary.
      *
-     * Base class for geant4 hit structures created by the
-     * example sensitive detectors.
-     *
-     * @author  M.Frank
-     * @version 1.0
+     *  @author  M.Frank
+     *  @version 1.0
      */
-    struct SimpleHit {
+    struct Geant4HitData {
       // cellID
       long long int cellID;
       /// User data extension if required
@@ -217,15 +184,15 @@ namespace DD4hep {
       typedef std::vector<MonteCarloContrib> Contributions;
     public:
       /// Default constructor
-      SimpleHit();
+      Geant4HitData();
       /// Default destructor
-      virtual ~SimpleHit();
+      virtual ~Geant4HitData();
       /// Extract the MC contribution for a given hit from the step information
       static Contribution extractContribution(G4Step* step);
     };
 
-    struct SimpleTracker {
-      /** @class SimpleTracker::Hit Geant4Data.h DDG4/Geant4Data.h
+    struct Geant4Tracker {
+      /** @class Geant4Tracker::Hit Geant4Data.h DDG4/Geant4Data.h
        *
        * Geant4 tracker hit class. Tracker hits contain the momentum
        * direction as well as the hit position.
@@ -233,7 +200,7 @@ namespace DD4hep {
        * @author  M.Frank
        * @version 1.0
        */
-      struct Hit : public SimpleHit {
+      struct Hit : public Geant4HitData {
         /// Hit position
         Position position;
         /// Hit direction
@@ -259,8 +226,8 @@ namespace DD4hep {
       };
     };
 
-    struct SimpleCalorimeter {
-      /** @class SimpleCalorimeter::Hit Geant4Data.h DDG4/Geant4Data.h
+    struct Geant4Calorimeter {
+      /** @class Geant4Calorimeter::Hit Geant4Data.h DDG4/Geant4Data.h
        *
        * Geant4 tracker hit class. Calorimeter hits contain the momentum
        * direction as well as the hit position.
@@ -268,7 +235,7 @@ namespace DD4hep {
        * @author  M.Frank
        * @version 1.0
        */
-      struct Hit : public SimpleHit {
+      struct Hit : public Geant4HitData {
       public:
         /// Hit position
         Position position;
@@ -285,6 +252,10 @@ namespace DD4hep {
         virtual ~Hit();
       };
     };
+    typedef Geant4HitData SimpleHit;
+    typedef Geant4Tracker SimpleTracker;
+    typedef Geant4Calorimeter SimpleCalorimeter;
+
   }    // End namespace Simulation
 }      // End namespace DD4hep
 #endif // DD4HEP_GEANT4DATA_H
diff --git a/DDG4/include/DDG4/Geant4DataConversion.h b/DDG4/include/DDG4/Geant4DataConversion.h
index 9174c92b8..44a39ff07 100644
--- a/DDG4/include/DDG4/Geant4DataConversion.h
+++ b/DDG4/include/DDG4/Geant4DataConversion.h
@@ -11,6 +11,7 @@
 
 // Framework include files
 #include "DD4hep/VolumeManager.h"
+#include "DD4hep/Detector.h"
 #include <typeinfo>
 
 /*
@@ -33,7 +34,12 @@ namespace DD4hep {
       Geant4ConversionHelper();
       /// Default destructor
       virtual ~Geant4ConversionHelper();
+      /// Access to the data encoding using the volume manager and a specified volume id
       static std::string encoding(Geometry::VolumeManager vm, Geometry::VolumeManager::VolumeID vid);
+      /// Access to the hit encoding in this sensitive detector
+      static std::string encoding(Geometry::Handle<Geometry::SensitiveDetectorObject> sd);
+      /// Access to the hit encoding in this readout object
+      static std::string encoding(Geometry::Readout ro);
     };
 
     /** @class Geant4Conversion Geant4DataConversion.h DDG4/Geant4DataConversion.h
diff --git a/DDG4/include/DDG4/Geant4DataDump.h b/DDG4/include/DDG4/Geant4DataDump.h
index e754e65b4..4d7065782 100644
--- a/DDG4/include/DDG4/Geant4DataDump.h
+++ b/DDG4/include/DDG4/Geant4DataDump.h
@@ -12,6 +12,7 @@
 // Framework include files
 #include "DD4hep/Printout.h"
 #include "DDG4/Geant4Data.h"
+#include "DDG4/Geant4Particle.h"
 
 // C/C++ include files
 #include <vector>
@@ -34,6 +35,7 @@ namespace DD4hep {
      */
     class Geant4DataDump  {
     public:
+      typedef Geant4Particle                       Particle;
       typedef std::vector<Particle*>               Particles;
 
       typedef SimpleTracker::Hit                   TrackerHit;
@@ -53,7 +55,7 @@ namespace DD4hep {
       virtual ~Geant4DataDump();
 
       /// Print a single particle to the output logging using the specified print level
-      void print(PrintLevel level, const Particle* p)  const;
+      void print(PrintLevel level, Geant4ParticleHandle p)  const;
       /// Print the particle container to the output logging using the specified print level
       void print(PrintLevel level, const std::string& container, const Particles* parts);
 
diff --git a/DDG4/include/DDG4/Geant4GeneratorActionInit.h b/DDG4/include/DDG4/Geant4GeneratorActionInit.h
new file mode 100644
index 000000000..700b6817f
--- /dev/null
+++ b/DDG4/include/DDG4/Geant4GeneratorActionInit.h
@@ -0,0 +1,75 @@
+// $Id: Geant4Hits.h 513 2013-04-05 14:31:53Z gaede $
+//====================================================================
+//  AIDA Detector description implementation
+//--------------------------------------------------------------------
+//
+//  Author     : M.Frank
+//
+//====================================================================
+#ifndef DD4HEP_DDG4_GEANT4GENERATORACTIONINIT_H
+#define DD4HEP_DDG4_GEANT4GENERATORACTIONINIT_H
+
+// Framework include files
+#include "DDG4/Geant4GeneratorAction.h"
+
+// Forward declarations
+class G4Event;
+class G4Run;
+
+/*
+ *   DD4hep namespace declaration
+ */
+namespace DD4hep {
+
+  /*
+   *   Simulation namespace declaration
+   */
+  namespace Simulation {
+
+    /** Geant4Action to collect the MC particle information.
+     *
+     *  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.
+     * 
+     *  These by default are extensions of type:
+     *  -- Geant4PrimaryEvent with multiple interaction sections, one for each interaction
+     *     This is the MAIN and ONLY information to feed Geant4
+     *
+     *  -- Geant4PrimaryInteraction containing the track/vertex information to create 
+     *     the primary particles for Geant4. This record is build from the Geant4PrimaryEvent
+     *     information.
+     *  -- Geant4PrimaryMap a map of the GEant4Particles converted to G4PrimaryParticles
+     *     to ease particle handling later.
+     *  -- Geant4ParticleMap the map of partcles created during the event simulation.
+     *     This map has directly the correct particle offsets, so that the merging of
+     *     Geant4PrimaryInteraction particles and the simulation particles is easy....
+     *    
+     *  @author  M.Frank
+     *  @version 1.0
+     */
+    class Geant4GeneratorActionInit : public Geant4GeneratorAction    {
+    protected:
+      /// Current run identifier
+      int m_run;
+      /// Counter for total number of events
+      int m_evtTotal;
+      /// Counter for total number of events in current run
+      int m_evtRun;
+    public:
+      /// Standard constructor
+      Geant4GeneratorActionInit(Geant4Context* context, const std::string& nam);
+      /// Default destructor
+      virtual ~Geant4GeneratorActionInit();
+      /// Event generation action callback
+      virtual void operator()(G4Event* event);
+      /// Begin-run action callback
+      void begin(const G4Run* run);
+      /// End-run action callback
+      void end(const G4Run* run);
+
+    };
+  }    // End namespace Simulation
+}      // End namespace DD4hep
+
+#endif // DD4HEP_DDG4_GEANT4GENERATORACTIONINIT_H
diff --git a/DDG4/include/DDG4/Geant4HitCollection.h b/DDG4/include/DDG4/Geant4HitCollection.h
index 198677724..1d13183e9 100644
--- a/DDG4/include/DDG4/Geant4HitCollection.h
+++ b/DDG4/include/DDG4/Geant4HitCollection.h
@@ -10,6 +10,7 @@
 #define DD4HEP_DDG4_GEANT4HITCOLLECTION_H
 
 // Framework include files
+#include "DD4hep/Handle.h"
 #include "DDG4/ComponentUtils.h"
 #include "G4VHitsCollection.hh"
 #include "G4VHit.hh"
@@ -25,6 +26,9 @@
  */
 namespace DD4hep {
 
+  /// Forward declarations
+  namespace Geometry  {   class SensitiveDetectorObject;   }
+
   /*
    *   Simulation namespace declaration
    */
@@ -167,8 +171,13 @@ namespace DD4hep {
      */
     class Geant4HitCollection: public G4VHitsCollection {
     public:
-      typedef std::vector<Geant4HitWrapper> WrappedHits;
+      /** Local type declarations  */
+      /// Hit wrapper
+      typedef std::vector<Geant4HitWrapper>    WrappedHits;
+      /// Hit manipulator
       typedef Geant4HitWrapper::HitManipulator Manip;
+      /// Sensitive detector
+      typedef Geometry::Handle<Geometry::SensitiveDetectorObject> SensitiveDetector;
 
       /** @class Compare Geant4HitCollection.h DDG4/Geant4HitCollection.h
        *
@@ -187,6 +196,8 @@ namespace DD4hep {
     protected:
       /// The collection of hit pointers in the wrapped format
       WrappedHits m_hits;
+      /// Handle to the sensitive detector
+      SensitiveDetector m_detector;
       /// The type of the objects in this collection. Set by the constructor
       Manip* m_manipulator;
 
@@ -203,20 +214,26 @@ namespace DD4hep {
     public:
       /// Initializing constructor (C++ version)
       template <typename TYPE>
-      Geant4HitCollection(const std::string& det, const std::string& coll)
-          : G4VHitsCollection(det, coll), m_manipulator(Geant4HitWrapper::manipulator<TYPE>()) {
+      Geant4HitCollection(const std::string& det, const std::string& coll, SensitiveDetector sd)
+	: G4VHitsCollection(det, coll), m_detector(sd),
+	m_manipulator(Geant4HitWrapper::manipulator<TYPE>())   {
         newInstance();
         m_hits.reserve(200);
       }
       /// Initializing constructor
       template <typename TYPE>
-      Geant4HitCollection(const std::string& det, const std::string& coll, const TYPE*)
-          : G4VHitsCollection(det, coll), m_manipulator(Geant4HitWrapper::manipulator<TYPE>()) {
+      Geant4HitCollection(const std::string& det, const std::string& coll, SensitiveDetector sd, const TYPE*)
+	: G4VHitsCollection(det, coll), m_detector(sd),
+	m_manipulator(Geant4HitWrapper::manipulator<TYPE>())   {
         newInstance();
         m_hits.reserve(200);
       }
       /// Default destructor
       virtual ~Geant4HitCollection();
+      /// Set the sensitive detector
+      void setSensitiveDetector(SensitiveDetector detector);
+      /// Access the sensitive detector
+      SensitiveDetector sensitiveDetector() const;
       /// Type information of the object stored
       const ComponentCast& type() const;
       /// Type information of the vector type for extracting data
diff --git a/DDG4/include/DDG4/Geant4InteractionMerger.h b/DDG4/include/DDG4/Geant4InteractionMerger.h
new file mode 100644
index 000000000..90e2a1690
--- /dev/null
+++ b/DDG4/include/DDG4/Geant4InteractionMerger.h
@@ -0,0 +1,42 @@
+// $Id: Geant4Hits.h 513 2013-04-05 14:31:53Z gaede $
+//====================================================================
+//  AIDA Detector description implementation
+//--------------------------------------------------------------------
+//
+//  Author     : M.Frank
+//
+//====================================================================
+#ifndef DD4HEP_DDG4_GEANT4INTERACTIONMERGER_H
+#define DD4HEP_DDG4_GEANT4INTERACTIONMERGER_H
+
+// Framework include files
+#include "DDG4/Geant4GeneratorAction.h"
+
+/*
+ *   DD4hep namespace declaration
+ */
+namespace DD4hep {
+
+  /*
+   *   Simulation namespace declaration
+   */
+  namespace Simulation {
+
+    /** Geant4Action to convert the particle information to Geant4
+     *
+     *  @author  M.Frank
+     *  @version 1.0
+     */
+    class Geant4InteractionMerger : public Geant4GeneratorAction    {
+    public:
+      /// Standard constructor
+      Geant4InteractionMerger(Geant4Context* context, const std::string& nam);
+      /// Default destructor
+      virtual ~Geant4InteractionMerger();
+      /// Event generation action callback
+      virtual void operator()(G4Event* event);
+    };
+  }    // End namespace Simulation
+}      // End namespace DD4hep
+
+#endif // DD4HEP_DDG4_GEANT4INTERACTIONMERGER_H
diff --git a/DDG4/include/DDG4/Geant4InteractionVertexBoost.h b/DDG4/include/DDG4/Geant4InteractionVertexBoost.h
new file mode 100644
index 000000000..fd2017763
--- /dev/null
+++ b/DDG4/include/DDG4/Geant4InteractionVertexBoost.h
@@ -0,0 +1,49 @@
+// $Id: Geant4Hits.h 513 2013-04-05 14:31:53Z gaede $
+//====================================================================
+//  AIDA Detector description implementation
+//--------------------------------------------------------------------
+//
+//  Author     : M.Frank
+//
+//====================================================================
+#ifndef DD4HEP_DDG4_GEANT4INTERACTIONVERTEXBOOST_H
+#define DD4HEP_DDG4_GEANT4INTERACTIONVERTEXBOOST_H
+
+// Framework include files
+#include "DDG4/Geant4GeneratorAction.h"
+
+// ROOT include files
+#include "Math/Vector4D.h"
+
+/*
+ *   DD4hep namespace declaration
+ */
+namespace DD4hep {
+
+  /*
+   *   Simulation namespace declaration
+   */
+  namespace Simulation {
+    /// Generate particles isotrop in space around origine (0,0,0)
+    /**
+     *
+     * @author  M.Frank
+     * @version 1.0
+     */
+    class Geant4InteractionVertexBoost: public Geant4GeneratorAction {
+    protected:
+      /// The constant Lorentz transformation angle
+      double m_angle;
+      /// Property: Unique identifier of the interaction to be modified
+      int m_mask;
+    public:
+      /// Standard constructor
+      Geant4InteractionVertexBoost(Geant4Context* context, const std::string& name);
+      /// Default destructor
+      virtual ~Geant4InteractionVertexBoost();
+      /// Callback to generate primary particles
+      virtual void operator()(G4Event* event);
+    };
+  }    // End namespace Simulation
+}      // End namespace DD4hep
+#endif /* DD4HEP_DDG4_GEANT4INTERACTIONVERTEXBOOST_H  */
diff --git a/DDG4/include/DDG4/Geant4InteractionVertexSmear.h b/DDG4/include/DDG4/Geant4InteractionVertexSmear.h
new file mode 100644
index 000000000..76cebb4df
--- /dev/null
+++ b/DDG4/include/DDG4/Geant4InteractionVertexSmear.h
@@ -0,0 +1,51 @@
+// $Id: Geant4Hits.h 513 2013-04-05 14:31:53Z gaede $
+//====================================================================
+//  AIDA Detector description implementation
+//--------------------------------------------------------------------
+//
+//  Author     : M.Frank
+//
+//====================================================================
+#ifndef DD4HEP_DDG4_GEANT4INTERACTIONVERTEXSMEAR_H
+#define DD4HEP_DDG4_GEANT4INTERACTIONVERTEXSMEAR_H
+
+// Framework include files
+#include "DDG4/Geant4GeneratorAction.h"
+
+// ROOT include files
+#include "Math/Vector4D.h"
+
+/*
+ *   DD4hep namespace declaration
+ */
+namespace DD4hep {
+
+  /*
+   *   Simulation namespace declaration
+   */
+  namespace Simulation {
+    /// Generate particles isotrop in space around origine (0,0,0)
+    /**
+     *
+     * @author  M.Frank
+     * @version 1.0
+     */
+    class Geant4InteractionVertexSmear: public Geant4GeneratorAction {
+    protected:
+      /// The constant smearing offset
+      ROOT::Math::PxPyPzEVector m_offset;
+      /// The gaussian sigmas to the offset
+      ROOT::Math::PxPyPzEVector m_sigma;      
+      /// Property: Unique identifier of the interaction created
+      int m_mask;
+    public:
+      /// Standard constructor
+      Geant4InteractionVertexSmear(Geant4Context* context, const std::string& name);
+      /// Default destructor
+      virtual ~Geant4InteractionVertexSmear();
+      /// Callback to generate primary particles
+      virtual void operator()(G4Event* event);
+    };
+  }    // End namespace Simulation
+}      // End namespace DD4hep
+#endif /* DD4HEP_DDG4_GEANT4INTERACTIONVERTEXSMEAR_H  */
diff --git a/DDG4/include/DDG4/Geant4IsotropeGenerator.h b/DDG4/include/DDG4/Geant4IsotropeGenerator.h
new file mode 100644
index 000000000..0fa7ba5e0
--- /dev/null
+++ b/DDG4/include/DDG4/Geant4IsotropeGenerator.h
@@ -0,0 +1,55 @@
+// $Id: Geant4Hits.h 513 2013-04-05 14:31:53Z gaede $
+//====================================================================
+//  AIDA Detector description implementation
+//--------------------------------------------------------------------
+//
+//  Author     : M.Frank
+//
+//====================================================================
+#ifndef DD4HEP_DDG4_GEANT4ISOTROPEGENERATOR_H
+#define DD4HEP_DDG4_GEANT4ISOTROPEGENERATOR_H
+
+// Framework include files
+#include "DDG4/Geant4GeneratorAction.h"
+
+// Forward declarations
+class G4ParticleDefinition;
+
+/*
+ *   DD4hep namespace declaration
+ */
+namespace DD4hep {
+
+  /*
+   *   Simulation namespace declaration
+   */
+  namespace Simulation {
+    /// Generate particles isotrop in space around origine (0,0,0)
+    /**
+     *
+     * @author  M.Frank
+     * @version 1.0
+     */
+    class Geant4IsotropeGenerator: public Geant4GeneratorAction {
+    protected:
+      /// Pointer to geant4 particle definition
+      G4ParticleDefinition* m_particle;
+      /// Property: Particle energy
+      double m_energy;
+      /// Property: Particle name
+      std::string m_particleName;
+      /// Property: Desired multiplicity of the particles to be shot
+      int m_multiplicity;
+      /// Property: User mask passed to all particles in the generated interaction
+      int m_mask;
+    public:
+      /// Standard constructor
+      Geant4IsotropeGenerator(Geant4Context* context, const std::string& name);
+      /// Default destructor
+      virtual ~Geant4IsotropeGenerator();
+      /// Callback to generate primary particles
+      virtual void operator()(G4Event* event);
+    };
+  }    // End namespace Simulation
+}      // End namespace DD4hep
+#endif /* DD4HEP_DDG4_GEANT4ISOTROPEGENERATOR_H  */
diff --git a/DDG4/include/DDG4/Geant4MonteCarloTruth.h b/DDG4/include/DDG4/Geant4MonteCarloTruth.h
index f19f64f54..7c9726b60 100644
--- a/DDG4/include/DDG4/Geant4MonteCarloTruth.h
+++ b/DDG4/include/DDG4/Geant4MonteCarloTruth.h
@@ -31,7 +31,7 @@ namespace DD4hep {
   namespace Simulation {
 
     // Forward declarations
-    class Particle;
+    class Geant4Particle;
 
     /** @class Geant4MonteCarloTruth Geant4MonteCarloTruth.h DDG4/Geant4MonteCarloTruth.h
      *
@@ -42,6 +42,7 @@ namespace DD4hep {
      */
     class Geant4MonteCarloTruth   {
     public:
+      typedef Geant4Particle           Particle;
       typedef std::map<int,Particle*>  ParticleMap;
       typedef std::map<int,int>        TrackEquivalents;
     protected:
diff --git a/DDG4/include/DDG4/Geant4Particle.h b/DDG4/include/DDG4/Geant4Particle.h
new file mode 100644
index 000000000..6dd0d3e82
--- /dev/null
+++ b/DDG4/include/DDG4/Geant4Particle.h
@@ -0,0 +1,303 @@
+// $Id: Geant4Data.h 513 2013-04-05 14:31:53Z gaede $
+//====================================================================
+//  AIDA Detector description implementation
+//--------------------------------------------------------------------
+//
+//  Author     : M.Frank
+//
+//====================================================================
+#ifndef DD4HEP_GEANT4PARTICLE_H
+#define DD4HEP_GEANT4PARTICLE_H
+
+// Framework include files
+
+// ROOT includes
+#include "Math/Vector4D.h"
+
+// Geant4 forward declarations
+class G4ParticleDefinition;
+class G4VProcess;
+
+// C/C++ include files
+#include <set>
+#include <map>
+#include <memory>
+
+/*
+ *   DD4hep namespace declaration
+ */
+namespace DD4hep {
+
+  /*
+   *   Simulation namespace declaration
+   */
+  namespace Simulation {
+
+    // Forward declarations
+    class Geant4Particle;
+
+    class ParticleExtension  {
+    public:
+      /// Default constructor
+      ParticleExtension() {}
+      /// Default destructor
+      virtual ~ParticleExtension();      
+    };
+
+    /// Track properties
+    enum Geant4ParticleProperties {
+      G4PARTICLE_CREATED_HIT = 1<<1, 
+      G4PARTICLE_PRIMARY = 1<<2,
+      G4PARTICLE_HAS_SECONDARIES = 1<<3,
+      G4PARTICLE_ABOVE_ENERGY_THRESHOLD = 1<<4,
+      G4PARTICLE_KEEP_PROCESS = 1<<5,
+      G4PARTICLE_KEEP_PARENT = 1<<6,
+      G4PARTICLE_CREATED_CALORIMETER_HIT = 1<<7,
+      G4PARTICLE_CREATED_TRACKER_HIT = 1<<8,
+      G4PARTICLE_KEEP_ALWAYS = 1<<9,
+
+      // Generator status for a given particles: bit 0...3 come from LCIO, rest is internal
+      G4PARTICLE_GEN_EMPTY           = 1<<0,  // Empty line
+      G4PARTICLE_GEN_STABLE          = 1<<1,  // undecayed particle, stable in the generator
+      G4PARTICLE_GEN_DECAYED         = 1<<2,  // particle decayed in the generator
+      G4PARTICLE_GEN_DOCUMENTATION   = 1<<3,  // documentation line
+
+      G4PARTICLE_GEN_CREATED         = 1<<4,  // Particle generated by generator
+      G4PARTICLE_GEN_HISTORY         = 1<<5,  // Particle is not a primary, but generation history
+      G4PARTICLE_GEN_STATUS          = 0x3FF, // Mask for generator status (bit 0...9)
+
+      // Simulation status of a given particle
+      G4PARTICLE_SIM_CREATED         = 1<<10, // True if the particle has been created by the simulation program (rather than the generator)
+      G4PARTICLE_SIM_BACKSCATTER     = 1<<11, // True if the particle is the result of a backscatter from a calorimeter shower.
+      G4PARTICLE_SIM_DECAY_CALO      = 1<<12, // True if the particle has interacted in a calorimeter region.
+      G4PARTICLE_SIM_DECAY_TRACKER   = 1<<13, // True if the particle has interacted in a tracking region.
+      G4PARTICLE_SIM_STOPPED         = 1<<14, // True if the particle has been stopped by the simulation program.
+      G4PARTICLE_SIM_LEFT_DETECTOR   = 1<<15, // True if the particle has left the world volume undecayed.
+      G4PARTICLE_SIM_PARENT_RADIATED = 1<<16, // True if the particle's vertex is not the endpoint of the  parent particle.
+      G4PARTICLE_SIM_OVERLAY         = 1<<17, // True if the particle has been overlayed by the simulation (or digitization)  program.
+
+      G4PARTICLE_LAST_NOTHING = 1<<31
+    };
+
+
+
+    /// Data structure to store the MC particle information 
+    /**
+     * @author  M.Frank
+     * @version 1.0
+     */
+    class Geant4Particle {
+    private:
+      /// Copy constructor
+      Geant4Particle(const Geant4Particle& c);
+    public:
+      typedef std::set<int> Particles;
+      /// Reference counter
+      int ref;           //! not persistent
+      int id, g4Parent, reason, usermask;
+      int steps, secondaries, pdgID;
+      int status, colorFlow[2];
+      char charge, _spare[3];
+      float spin[3];
+      // 12 ints + 4 floats should be aligned to 8 bytes....
+      double vsx, vsy, vsz;
+      double vex, vey, vez;
+      double psx, psy, psz;
+      double pex, pey, pez;
+      double mass, time, properTime;
+      /// The list of daughters of this MC particle
+      Particles parents;
+      Particles daughters;
+
+      /// User data extension if required
+      std::auto_ptr<ParticleExtension> extension;  
+      const G4VProcess *process;  //! not persistent
+      const G4ParticleDefinition *definition;  //! not persistent
+      /// Default constructor
+      Geant4Particle();
+      /// Constructor with ID initialization
+      Geant4Particle(int part_id);
+      /// Default destructor
+      virtual ~Geant4Particle();
+      /// Increase reference count
+      Geant4Particle* addRef()  {
+	++ref; 
+	return this;
+      }
+      /// Decrease reference count. Deletes object if NULL
+      void release();
+      /// Assignment operator
+      Geant4Particle& get_data(Geant4Particle& c);
+      /// Remove daughter from set
+      void removeDaughter(int id_daughter);
+    };
+
+#ifndef __DD4HEP_DDEVE_EXCLUSIVE__
+    /// Data structure to access MC particle information 
+    /**
+     * @author  M.Frank
+     * @version 1.0
+     */
+    class Geant4ParticleHandle {
+    protected:
+      /// Particle pointer
+      Geant4Particle* particle;      
+    public:
+      /// Default constructor
+      Geant4ParticleHandle(Geant4Particle* part);
+      /// Initializing constructor
+      Geant4ParticleHandle(const Geant4ParticleHandle& h);
+      /// Assignment operator
+      Geant4ParticleHandle& operator=(Geant4Particle* part);
+      /// Overloaded -> operator to access particle details
+      Geant4Particle* operator->() const;
+      /// Conversion  operator to pointer
+      operator Geant4Particle*() const;
+      /// Accessor to the number of particle parents
+      size_t numParent() const;
+      /// Accessor to the number of particle daughters
+      size_t numDaughter() const;
+      /// Scalar particle momentum squared
+      double momentum2() const;
+      /// Scalar particle energy
+      double energy() const;
+      /// Scalar particle momentum
+      double momentum() const   {  return sqrt(momentum2()); }
+      /// Access to the Geant4 particle name
+      std::string particleName() const;
+      /// Access to the Geant4 particle type
+      std::string particleType() const;
+      /// Access to the creator process name
+      std::string processName() const;
+      /// Access to the creator process type name
+      std::string processTypeName() const;
+      /// Access patricle momentum, energy as 4 vector
+      ROOT::Math::PxPyPzM4D<double> pxPyPzM() const;
+      /// Access patricle momentum, energy as 4 vector
+      ROOT::Math::Cartesian3D<double> startVertex() const;
+      /// Access patricle momentum, energy as 4 vector
+      ROOT::Math::Cartesian3D<double> endVertex()  const;
+
+      /// Various output formats:
+
+      /// Output type 1:+++ <tag>   10 def:0xde4eaa8 [gamma     ,   gamma] reason:      20 E:+1.017927e+03  #Par:  1/4    #Dau:  2
+      void dump1(int level, const std::string& src, const char* tag) const;
+      /// Output type 2:+++ <tag>   20 G4:   7 def:0xde4eaa8 [gamma     ,   gamma] reason:      20 E:+3.304035e+01 in record:YES  #Par:  1/18   #Dau:  0
+      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;
+
+      /// Handlers
+
+      /// Offset all particle identifiers (id, parents, daughters) by a constant number
+      void offset(int off)  const;
+
+    };
+
+    inline Geant4ParticleHandle::Geant4ParticleHandle(const Geant4ParticleHandle& c)
+      : particle(c.particle) {
+    }
+
+    /// Initializing constructor
+    inline Geant4ParticleHandle::Geant4ParticleHandle(Geant4Particle* p)
+      : particle(p)  {
+    }
+
+    /// Overloaded -> operator to access particle details
+    inline Geant4Particle* Geant4ParticleHandle::operator->() const  {
+      return particle;
+    }
+    /// Assignment operator
+    inline Geant4ParticleHandle& Geant4ParticleHandle::operator=(Geant4Particle* part) { 
+      particle = part;
+      return *this;
+    }
+    /// Conversion  operator to pointer
+    inline Geant4ParticleHandle::operator Geant4Particle*() const  {
+      return particle;
+    }
+    /// Accessor to the number of particle parents
+    inline size_t Geant4ParticleHandle::numParent() const   {
+      return particle->parents.size();
+    }
+    /// Accessor to the number of particle daughters
+    inline size_t Geant4ParticleHandle::numDaughter() const   {
+      return particle->daughters.size();
+    }
+    /// Access patricle momentum, energy as 4 vector
+    inline ROOT::Math::PxPyPzM4D<double> Geant4ParticleHandle::pxPyPzM() const {
+      const Geant4Particle* p = particle;
+      return ROOT::Math::PxPyPzM4D<double>(p->psx,p->psy,p->psz,p->mass);
+    }
+
+    /// Access patricle momentum, energy as 4 vector
+    inline ROOT::Math::Cartesian3D<double> Geant4ParticleHandle::startVertex() const {
+      const Geant4Particle* p = particle;
+      return ROOT::Math::Cartesian3D<double>(p->vsx,p->vsy,p->vsz);
+    }
+
+    /// Access patricle momentum, energy as 4 vector
+    inline ROOT::Math::Cartesian3D<double> Geant4ParticleHandle::endVertex()  const {
+      const Geant4Particle* p = particle;
+      return ROOT::Math::Cartesian3D<double>(p->vex,p->vey,p->vez);
+    }
+
+    /// Scalar particle energy
+    inline double Geant4ParticleHandle::energy() const {
+      const Geant4Particle* p = particle;
+      ROOT::Math::PxPyPzM4D<double> v(p->psx,p->psy,p->psz,p->mass);
+      return v.E();
+    }
+    
+    /// Scalar particle momentum squared
+    inline double Geant4ParticleHandle::momentum2() const  {
+      const Geant4Particle* p = particle;
+      return (p->psx*p->psx + p->psy*p->psy + p->psz*p->psz);
+    }
+
+    /// Data structure to map particles produced during the generation and the simulation
+    /**
+     *  This data structure is added to the Geant4Event data extensions
+     *  by the Geant4GenerationInit action.
+     *  Particles are added:
+     *  - During the generation if the required modules are activated
+     *  - At the end of the handling of the MC truth are particles to be kept
+     *    are inserted if the required modules are activated such as the
+     *    Geant4ParticleHandler.
+     * 
+     *  Note: This object takes OWNERSHIP of the inserted particles!
+     *        beware of double deletion of objects!
+     *
+     *  @author  M.Frank
+     *  @version 1.0
+     */
+    class Geant4ParticleMap  {
+    public:
+      typedef Geant4Particle          Particle;
+      typedef std::map<int,Particle*> ParticleMap;
+      typedef std::map<int,int>       TrackEquivalents;
+      /// Mapping of particles of this event
+      ParticleMap particleMap; //! not persistent
+      /// Map associating the G4Track identifiers with identifiers of existing MCParticles
+      TrackEquivalents equivalentTracks;
+
+      /// Default constructor
+      Geant4ParticleMap() {}
+      /// Default destructor
+      virtual ~Geant4ParticleMap();
+      /// Clear particle maps
+      void clear();
+      /// Adopt particle maps
+      void adopt(ParticleMap& pm, TrackEquivalents& equiv);
+      /// Access the particle map
+      const ParticleMap& particles() const  {  return particleMap; }
+      /// Access the map of track equivalents
+      const TrackEquivalents& equivalents() const  {  return equivalentTracks;  }
+      /// Access the equivalent track id (shortcut to the usage of TrackEquivalents)
+      int particleID(int track, bool throw_if_not_found=true) const;
+    };
+#endif
+
+  }    // End namespace Simulation
+}      // End namespace DD4hep
+#endif // DD4HEP_GEANT4PARTICLE_H
diff --git a/DDG4/include/DDG4/Geant4ParticleGun.h b/DDG4/include/DDG4/Geant4ParticleGun.h
index 69bb5cd2a..52fb2ec75 100644
--- a/DDG4/include/DDG4/Geant4ParticleGun.h
+++ b/DDG4/include/DDG4/Geant4ParticleGun.h
@@ -1,4 +1,3 @@
-// $Id: Geant4Hits.h 513 2013-04-05 14:31:53Z gaede $
 //====================================================================
 //  AIDA Detector description implementation
 //--------------------------------------------------------------------
@@ -16,7 +15,6 @@
 // Forward declarations
 class G4ParticleDefinition;
 class G4ParticleGun;
-class TRandom1;
 
 /*
  *   DD4hep namespace declaration
@@ -42,8 +40,6 @@ namespace DD4hep {
       G4ParticleDefinition* m_particle;
       /// Pointer to the particle gun itself
       G4ParticleGun* m_gun;
-      /// Random number generator
-      TRandom1* m_rndm;
       /// Particle energy
       double m_energy;
       /// Particle name
@@ -65,4 +61,3 @@ namespace DD4hep {
   }    // End namespace Simulation
 }      // End namespace DD4hep
 #endif /* DD4HEP_DDG4_GEANT4PARTICLEGUN_H  */
-
diff --git a/DDG4/include/DDG4/Geant4ParticleHandler.h b/DDG4/include/DDG4/Geant4ParticleHandler.h
index 35f8038af..bafcea190 100644
--- a/DDG4/include/DDG4/Geant4ParticleHandler.h
+++ b/DDG4/include/DDG4/Geant4ParticleHandler.h
@@ -10,7 +10,7 @@
 #define DD4HEP_DDG4_GEANT4PARTICLEHANDLER_H
 
 // Framework include files
-#include "DDG4/Geant4Data.h"
+#include "DDG4/Geant4Primary.h"
 #include "DDG4/Geant4GeneratorAction.h"
 #include "DDG4/Geant4MonteCarloTruth.h"
 
@@ -32,18 +32,26 @@ namespace DD4hep {
 
     // Forward declarations
     class Particle;
+    class Geant4PrimaryMap;
     class Geant4UserParticleHandler;
 
     /** Geant4Action to collect the MC particle information.
      *
+     *  Extract the relevant particle information during the simulation step.
      *
-     * @author  M.Frank
-     * @version 1.0
+     *  @author  M.Frank
+     *  @version 1.0
      */
-    class Geant4ParticleHandler : public Geant4GeneratorAction, public Geant4MonteCarloTruth 
-    {
+    class Geant4ParticleHandler : public Geant4GeneratorAction, public Geant4MonteCarloTruth  {
     public:
       typedef std::vector<std::string> Processes;
+      struct FindParticleByID {
+	int pid;
+      FindParticleByID(int p) : pid(p) {}
+	inline bool operator()(const std::pair<int,Geant4Particle*>& p)  const {
+	  return p.second->id == pid;
+	}
+      };
     protected:
       
       /// Property: Steer printout at tracking action begin
@@ -52,10 +60,17 @@ namespace DD4hep {
       bool m_printEndTracking;
       /// Property: Flag to keep all particles generated
       bool m_keepAll;
+      /// Property: Flag if the handler is executed in standalone mode and hence must manage particles
+      bool m_ownsParticles;
       /// Property: Energy cut below which particles are not collected, but assigned to the parent
       double m_kinEnergyCut;
+
+      /// Global particle identifier. Obtained at the begin of the event.
+      int m_globalParticleID, m_initialParticleID;
       /// User action pointer
       Geant4UserParticleHandler* m_userHandler;
+      /// Primary map
+      Geant4PrimaryMap* m_primaryMap;
       /// Local buffer about the 'current' G4Track 
       Particle m_currTrack;
       /// Map with stored MC Particles
@@ -74,6 +89,11 @@ namespace DD4hep {
       /// Get proper equivalent track from the particle map according to the given geant4 track ID
       int equivalentTrack(int g4_id) const;
 
+      /// Rebase the simulated tracks, so that they fit to the generator particles
+      void rebaseSimulatedTracks(int base);
+      /// Debugging: Dump Geant4 particle map
+      void dumpMap(const char* tag) const;
+
     public:
       /// Standard constructor
       Geant4ParticleHandler(Geant4Context* context, const std::string& nam);
diff --git a/DDG4/include/DDG4/Geant4ParticlePrint.h b/DDG4/include/DDG4/Geant4ParticlePrint.h
index 1c5e2786e..4429e408b 100644
--- a/DDG4/include/DDG4/Geant4ParticlePrint.h
+++ b/DDG4/include/DDG4/Geant4ParticlePrint.h
@@ -11,7 +11,8 @@
 
 // Framework include files
 #include "DDG4/Geant4EventAction.h"
-#include "DDG4/Geant4MonteCarloTruth.h"
+#include "DDG4/Geant4GeneratorAction.h"
+#include "DDG4/Geant4Particle.h"
 
 /*
  *   DD4hep namespace declaration
@@ -29,21 +30,30 @@ namespace DD4hep {
      * @author  M.Frank
      * @version 1.0
      */
-    class Geant4ParticlePrint : public Geant4EventAction    {
+    class Geant4ParticlePrint : public Geant4EventAction	{
     public:
-      typedef Geant4MonteCarloTruth::ParticleMap ParticleMap;
-      typedef Geant4MonteCarloTruth::TrackEquivalents TrackEquivalents;
+      typedef Geant4ParticleMap::Particle Particle;
+      typedef Geant4ParticleMap::ParticleMap ParticleMap;
+      typedef Geant4ParticleMap::TrackEquivalents TrackEquivalents;
     protected:
       /// Property: Flag to indicate output type: 1: TABLE, 2:TREE, 3:BOTH (default)
       int m_outputType;
+      /// Property: Flag to indicate output type at begin of event
+      bool m_printBegin;
+      /// Property: Flag to indicate output type at end of event
+      bool m_printEnd;
+      /// Property: Flag to indicate output type as part of the generator action
+      bool m_printGeneration;
 
-      void printParticle(const std::string& prefix, const Particle* p) const;
+      void printParticle(const std::string& prefix, Geant4ParticleHandle p) const;
       /// Print record of kept particles
       void printParticles(const ParticleMap& particles) const;
       /// Print tree of kept particles
-      void printParticleTree(const ParticleMap& particles, int level, const Particle* p)  const;
+      void printParticleTree(const ParticleMap& particles, int level, Geant4ParticleHandle p)  const;
       /// Print tree of kept particles
       void printParticleTree(const ParticleMap& particles)  const;
+      /// Print particle table
+      void makePrintout()  const;
 
 
     public:
@@ -55,6 +65,9 @@ namespace DD4hep {
       virtual void begin(const G4Event* event);
       /// Post-event action callback
       virtual void end(const G4Event* event);
+      /// Generation action callback
+      virtual void operator()(G4Event* event);
+      
     };
   }    // End namespace Simulation
 }      // End namespace DD4hep
diff --git a/DDG4/include/DDG4/Geant4Primary.h b/DDG4/include/DDG4/Geant4Primary.h
new file mode 100644
index 000000000..3c3c39c55
--- /dev/null
+++ b/DDG4/include/DDG4/Geant4Primary.h
@@ -0,0 +1,150 @@
+// $Id: Geant4Data.h 513 2013-04-05 14:31:53Z gaede $
+//====================================================================
+//  AIDA Detector description implementation
+//--------------------------------------------------------------------
+//
+//  Author     : M.Frank
+//
+//====================================================================
+#ifndef DD4HEP_GEANT4PRIMARY_H
+#define DD4HEP_GEANT4PRIMARY_H
+
+// Framework include files
+#include "DDG4/Geant4Vertex.h"
+#include "DDG4/Geant4Particle.h"
+
+// C/C++ include files
+#include <set>
+#include <map>
+#include <vector>
+#include <memory>
+
+// Forward declarations
+class G4PrimaryParticle;
+
+/*
+ *   DD4hep namespace declaration
+ */
+namespace DD4hep {
+
+  /*
+   *   Simulation namespace declaration
+   */
+  namespace Simulation {
+
+    // Forward declarations
+    class Geant4Particle;
+    class Geant4Vertex;
+    
+    class PrimaryExtension  {
+    public:
+      /// Default constructor
+      PrimaryExtension() {}
+      /// Default destructor
+      virtual ~PrimaryExtension();      
+    };
+
+    /// Data structure to map primaries to particles.
+    /**
+     *  This data structure is added to the Geant4Event data extensions
+     *  by the Geant4GenerationInit action.
+     *
+     *  @author  M.Frank
+     *  @version 1.0
+     */
+    class Geant4PrimaryMap  {
+    public:
+      typedef std::map<const G4PrimaryParticle*,Geant4Particle*> Primaries;
+      /// Mapping of primary particles of this event
+      Primaries primaryMap; //! not persistent
+      /// Default constructor
+      Geant4PrimaryMap() {}
+      /// Default destructor
+      virtual ~Geant4PrimaryMap();
+    };
+    
+
+    /// Class modelling a single interaction with multiple primary vertices and particles
+    /*
+     *  @author  M.Frank
+     *  @version 1.0
+     */
+    class Geant4PrimaryInteraction   {
+    private:
+      /// Copy constructor
+      Geant4PrimaryInteraction(const Geant4PrimaryInteraction& c);
+      /// Assignment operator
+      Geant4PrimaryInteraction& operator=(const Geant4PrimaryInteraction& c);
+
+    public:
+      typedef Geant4Particle                  Particle;
+      typedef Geant4Vertex                    Vertex;
+      typedef std::map<int,Particle*>         ParticleMap;
+      typedef std::map<int,Vertex*>           VertexMap;
+      typedef std::auto_ptr<PrimaryExtension> ExtensionHandle;
+
+      /// The map of primary vertices for the particles.
+      VertexMap       vertices;
+      /// The map of particles participating in this primary interaction
+      ParticleMap     particles;
+      /// User data extension if required
+      ExtensionHandle extension;
+      /// User mask to flag the interaction. Also unique identifier
+      int             mask;
+      /// Next PID indentifier
+      int             next_particle_identifier;
+
+    public:
+      /// Default constructor
+      Geant4PrimaryInteraction();
+      /// Default destructor
+      virtual ~Geant4PrimaryInteraction();
+      /// Access a new particle identifier within the interaction
+      int nextPID();
+      /// Set the next PID value
+      void setNextPID(int value);
+    };
+
+    /// Class modelling a complete primary event with multiple interactions
+    /*
+     *  Multiple interactions allow a simple handling of overlay events
+     *
+     *  @author  M.Frank
+     *  @version 1.0
+     */
+    class Geant4PrimaryEvent   {
+    private:
+      /// Copy constructor
+      Geant4PrimaryEvent(const Geant4PrimaryEvent& c);
+      /// Assignment operator
+      Geant4PrimaryEvent& operator=(const Geant4PrimaryEvent& c);
+
+    public:
+      typedef Geant4PrimaryInteraction        Interaction;
+      typedef std::map<int,Interaction*>      Interactions;
+      typedef std::auto_ptr<PrimaryExtension> ExtensionHandle;
+
+    protected:
+      /// Set of primary interactions
+      Interactions    m_interactions;
+
+    public:
+      /// User data extension if required
+      ExtensionHandle extension;
+
+    public:
+      /// Default constructor
+      Geant4PrimaryEvent();
+      /// Default destructor
+      virtual ~Geant4PrimaryEvent();
+      /// Add a new interaction object to the event
+      void add(int id, Geant4PrimaryInteraction* interaction);
+      /// Retrieve an interaction by it's ID
+      Interaction* get(int id) const;
+      /// Retrieve all intractions
+      std::vector<Interaction*> interactions() const;
+    };
+
+  }    // End namespace Simulation
+}      // End namespace DD4hep
+#endif // DD4HEP_GEANT4PRIMARY_H
diff --git a/DDG4/include/DDG4/Geant4PrimaryHandler.h b/DDG4/include/DDG4/Geant4PrimaryHandler.h
new file mode 100644
index 000000000..0b6873257
--- /dev/null
+++ b/DDG4/include/DDG4/Geant4PrimaryHandler.h
@@ -0,0 +1,42 @@
+// $Id: Geant4Hits.h 513 2013-04-05 14:31:53Z gaede $
+//====================================================================
+//  AIDA Detector description implementation
+//--------------------------------------------------------------------
+//
+//  Author     : M.Frank
+//
+//====================================================================
+#ifndef DD4HEP_DDG4_GEANT4PRIMARYHANDLER_H
+#define DD4HEP_DDG4_GEANT4PRIMARYHANDLER_H
+
+// Framework include files
+#include "DDG4/Geant4GeneratorAction.h"
+
+/*
+ *   DD4hep namespace declaration
+ */
+namespace DD4hep {
+
+  /*
+   *   Simulation namespace declaration
+   */
+  namespace Simulation {
+
+    /** Geant4Action to convert the particle information to Geant4
+     *
+     *  @author  M.Frank
+     *  @version 1.0
+     */
+    class Geant4PrimaryHandler : public Geant4GeneratorAction    {
+    public:
+      /// Standard constructor
+      Geant4PrimaryHandler(Geant4Context* context, const std::string& nam);
+      /// Default destructor
+      virtual ~Geant4PrimaryHandler();
+      /// Event generation action callback
+      virtual void operator()(G4Event* event);
+    };
+  }    // End namespace Simulation
+}      // End namespace DD4hep
+
+#endif // DD4HEP_DDG4_GEANT4PRIMARYHANDLER_H
diff --git a/DDG4/include/DDG4/Geant4Random.h b/DDG4/include/DDG4/Geant4Random.h
new file mode 100644
index 000000000..29b5d3dc8
--- /dev/null
+++ b/DDG4/include/DDG4/Geant4Random.h
@@ -0,0 +1,69 @@
+// $Id: Geant4Data.h 513 2013-04-05 14:31:53Z gaede $
+//====================================================================
+//  AIDA Detector description implementation
+//--------------------------------------------------------------------
+//
+//  Author     : M.Frank
+//
+//====================================================================
+#ifndef DD4HEP_GEANT4RANDOM_H
+#define DD4HEP_GEANT4RANDOM_H
+
+// Framework include files
+
+// C/C++ include files
+
+/*
+ *   DD4hep namespace declaration
+ */
+namespace DD4hep {
+
+  /*
+   *   Simulation namespace declaration
+   */
+  namespace Simulation {
+
+    // Forward declarations
+    class Geant4Exec;
+
+    /// Mini interface to THE random generator of the application
+    /**
+     *  Mini interface to THE random generator of the application.
+     *  Necessary, that on every object creates its own instance, but accesses
+     *  the main instance avaible throu the Geant4Context.
+     *
+     *  This is mandatory to ensure reproducability of the event generation
+     *  process. Particular objects may use a dependent generator from 
+     *  an experiment framework like GAUDI.
+     *
+     *  This main interface is supposed to be stable. Unclear however is 
+     *  if the generation functions will have to become virtual....
+     *  Future will tell us.
+     *
+     *  @author  M.Frank
+     *  @version 1.0
+     */
+    class Geant4Random  {
+      friend class Geant4Exec;
+
+    protected:
+      /// Default constructor
+      Geant4Random();
+      /// Default destructor
+      virtual ~Geant4Random();
+    public:
+      void   circle(double &x, double &y, double r);
+      double exp(double tau);
+      double gauss(double mean=0, double sigma=1);
+      double landau(double mean=0, double sigma=1);
+      double rndm(int i=0);
+      void   rndmArray(int n, float *array);
+      void   rndmArray(int n, double *array);
+      void   sphere(double &x, double &y, double &z, double r);
+      double uniform(double x1=1);
+      double uniform(double x1, double x2);
+    };
+    
+  }    // End namespace Simulation
+}      // End namespace DD4hep
+#endif // DD4HEP_GEANT4RANDOM_H
diff --git a/DDG4/include/DDG4/Geant4SensDetAction.h b/DDG4/include/DDG4/Geant4SensDetAction.h
index 77674a7c1..9b720a68a 100644
--- a/DDG4/include/DDG4/Geant4SensDetAction.h
+++ b/DDG4/include/DDG4/Geant4SensDetAction.h
@@ -231,7 +231,9 @@ namespace DD4hep {
      */
     class Geant4SensDetActionSequence: public Geant4Action {
     public:
-      typedef G4VHitsCollection* (*create_t)(const std::string&, const std::string&);
+      
+      typedef Geometry::SensitiveDetector SensitiveDetector;
+      typedef Geant4HitCollection* (*create_t)(const std::string&, const std::string&, SensitiveDetector);
       typedef std::vector<std::pair<std::string, create_t> > HitCollections;
 
     protected:
@@ -248,15 +250,18 @@ namespace DD4hep {
       /// The list of sensitive detector objects
       Actors<Geant4Sensitive> m_actors;
       /// The list of sensitive detector filter objects
-      Actors<Geant4Filter> m_filters;
+      Actors<Geant4Filter>    m_filters;
 
       /// Hit collection creators
       HitCollections m_collections;
+      /// Reference to the sensitive detector element
+      SensitiveDetector m_sensitive;
       /// Reference to G4 sensitive detector
       Geant4ActionSD* m_detector;
+
       /// Create a new typed hit collection
-      template <typename TYPE> static G4VHitsCollection* _create(const std::string& det, const std::string& coll) {
-        return new Geant4HitCollection(det, coll, (TYPE*) 0);
+      template <typename TYPE> static Geant4HitCollection* _create(const std::string& det, const std::string& coll, SensitiveDetector sd) {
+        return new Geant4HitCollection(det, coll, sd, (TYPE*) 0);
       }
 
     public:
diff --git a/DDG4/include/DDG4/Geant4UserParticleHandler.h b/DDG4/include/DDG4/Geant4UserParticleHandler.h
index 5047595a0..745cb3de8 100644
--- a/DDG4/include/DDG4/Geant4UserParticleHandler.h
+++ b/DDG4/include/DDG4/Geant4UserParticleHandler.h
@@ -30,7 +30,7 @@ namespace DD4hep {
   namespace Simulation {
 
     // Forward declarations
-    class Particle;
+    class Geant4Particle;
     class Geant4ParticleHandler;
 
     /** Geant4ParticleHandler user extension action called by the particle handler.
@@ -45,6 +45,8 @@ namespace DD4hep {
      * @version 1.0
      */
     class Geant4UserParticleHandler : public Geant4Action  {
+    public:
+      typedef Geant4Particle Particle;
     public:
       /// Standard constructor
       Geant4UserParticleHandler(Geant4Context* context, const std::string& nam);
diff --git a/DDG4/include/DDG4/Geant4Vertex.h b/DDG4/include/DDG4/Geant4Vertex.h
new file mode 100644
index 000000000..3ad19da25
--- /dev/null
+++ b/DDG4/include/DDG4/Geant4Vertex.h
@@ -0,0 +1,72 @@
+// $Id: Geant4Data.h 513 2013-04-05 14:31:53Z gaede $
+//====================================================================
+//  AIDA Detector description implementation
+//--------------------------------------------------------------------
+//
+//  Author     : M.Frank
+//
+//====================================================================
+#ifndef DD4HEP_GEANT4VERTEX_H
+#define DD4HEP_GEANT4VERTEX_H
+
+// C/C++ include files
+#include <set>
+#include <memory>
+
+/*
+ *   DD4hep namespace declaration
+ */
+namespace DD4hep {
+
+  /*
+   *   Simulation namespace declaration
+   */
+  namespace Simulation {
+
+    // Forward declarations
+    class Geant4Vertex;
+
+    class VertexExtension  {
+    public:
+      /// Default constructor
+      VertexExtension() {}
+      /// Default destructor
+      virtual ~VertexExtension();      
+    };
+
+    /// Data structure to store the MC vertex information 
+    /**
+     * @author  M.Frank
+     * @version 1.0
+     */
+    class Geant4Vertex {
+    public:
+      typedef std::set<int> Particles;
+      /// Reference counter
+      int ref;            //! not persistent
+      /// Vertex data
+      double x,y,z,time;
+      /// The list of outgoing particles
+      Particles out;
+      /// The list of incoming particles
+      Particles in;
+      /// User data extension if required
+      std::auto_ptr<VertexExtension> extension;  
+
+      /// Default constructor
+      Geant4Vertex();
+      /// Copy constructor
+      Geant4Vertex(const Geant4Vertex& c);
+      /// Default destructor
+      virtual ~Geant4Vertex();
+      /// Assignment operator
+      Geant4Vertex& operator=(const Geant4Vertex& c);
+      /// Increase reference count
+      Geant4Vertex* addRef();
+      /// Decrease reference count. Deletes object if NULL
+      void release();
+    };
+
+  }    // End namespace Simulation
+}      // End namespace DD4hep
+#endif // DD4HEP_GEANT4VERTEX_H
diff --git a/DDG4/lcio/EventReader.cpp b/DDG4/lcio/EventReader.cpp
deleted file mode 100644
index bca719711..000000000
--- a/DDG4/lcio/EventReader.cpp
+++ /dev/null
@@ -1,303 +0,0 @@
-// $Id: Geant4Converter.cpp 603 2013-06-13 21:15:14Z markus.frank $
-//====================================================================
-//  AIDA Detector description implementation for LCD
-//--------------------------------------------------------------------
-//
-// @author  P.Kostka (main author)
-// @author  M.Frank  (code reshuffeling into new DDG4 scheme)
-//
-//====================================================================
-
-// Framework include files
-#include "EventReader.h"
-#include "DD4hep/Plugins.h"
-#include "G4Event.hh"
-#include "G4PrimaryParticle.hh"
-#include "G4ParticleTable.hh"
-#include "IMPL/MCParticleImpl.h"
-#include "IMPL/LCCollectionVec.h"
-#include "Randomize.hh"
-
-using namespace std;
-
-/// Initializing constructor
-DD4hep::lcio::EventReader::EventReader(const string& nam) : m_name(nam)   {
-}
-
-/// Default destructor
-DD4hep::lcio::EventReader::~EventReader()   {
-}
-
-static void setCharge(IMPL::MCParticleImpl* p)   {
-  // Initialise the particle charge looking at the actual 
-  // Particle Table, or set it to -1000 to flag missing 
-  // information, if PDG unknown in the actual physics list..
-  G4ParticleTable*      tab  = G4ParticleTable::GetParticleTable();
-  G4ParticleDefinition* def = tab->FindParticle(p->getPDG());
-  double charge = def ? def->GetPDGCharge() : -1000;
-  p->setCharge(charge);
-}
-
-/// Standard constructor
-DD4hep::lcio::LcioGeneratorAction::LcioGeneratorAction(Simulation::Geant4Context* context, const string& name)
-  : Simulation::Geant4GeneratorAction(context,name)
-{
-  declareProperty("Input",       m_input);
-  declareProperty("Sync",        m_SYNCEVT=0);
-  declareProperty("zSpread",     m_primaryVertexSpreadZ=0.0);
-  declareProperty("lorentzAngle",m_lorentzTransformationAngle=0.0);
-}
-
-/// Default destructor
-DD4hep::lcio::LcioGeneratorAction::~LcioGeneratorAction()   {
-}
-
-static string issue(int i)  {
-  stringstream str;
-  str << "lcio::LcioGeneratorAction: Event " << i;
-  return str.str();
-}
-
-/// Read an event and return a LCCollectionVec of MCParticles.
-DD4hep::lcio::LcioGeneratorAction::Particles *DD4hep::lcio::LcioGeneratorAction::readEvent(int which)  {
-  int evid = which + m_SYNCEVT;
-  if ( 0 == m_reader )  {
-    if ( m_input.empty() )  {
-      throw runtime_error("LcioGeneratorAction: No inoput file declared!");
-    }
-    string err;
-    Simulation::TypeName tn = Simulation::TypeName::split(m_input,"|");
-    try  {
-      m_reader = PluginService::Create<DD4hep::lcio::EventReader*>(tn.first,tn.second,int(0));
-      if ( 0 == m_reader )   {
-	abortRun(issue(evid),"Error creating reader plugin.",
-		 "Failed to create file reader of type %s. Cannot open dataset %s",
-		 tn.first.c_str(),tn.second.c_str());
-	return 0;
-      }
-    }
-    catch(const std::exception& e)  {
-      err = e.what();
-    }
-    if ( !err.empty() )  {
-      abortRun(issue(evid),err,"Error when reading file %s",m_input.c_str());
-      return 0;
-    }
-  }
-  Particles* parts = m_reader->readEvent();
-  if ( 0 == parts )  {
-    abortRun(issue(evid),"Error when reading file - may be end of file.",
-	     "Error when reading file %s",m_input.c_str());
-  }
-  return parts;
-}
-
-/// Callback to generate primary particles
-void DD4hep::lcio::LcioGeneratorAction::operator()(G4Event* evt)   {
-  //**********************************************************
-  // Read in the event
-  //**********************************************************
-  m_g4ParticleMap.clear();
-  m_convertedParticles.clear();
-  Particles* primaries = readEvent(evt->GetEventID());
-  if ( 0 == primaries ) return;
-
-  vector<MCParticle*> col(primaries->size()) ;
-  int NHEP = col.size();
-
-  // parameters of the Lorentz transformation matrix
-  const double zspreadparameter = m_primaryVertexSpreadZ;
-  const double alpha            = m_lorentzTransformationAngle;
-  const double gamma            = sqrt(1 + sqr(tan(alpha)));
-  const double betagamma        = tan(alpha);
-
-  double zspread = ( zspreadparameter == 0.0 ?  0.0 : G4RandGauss::shoot(0,zspreadparameter/mm ) );
-  //cout << " PrimaryVertexSpreadZ=" << zspreadparameter/mm  <<"mm, zspread=" << zspread << "mm" << endl;
-  G4ThreeVector particle_position = G4ThreeVector(0,0,zspread);
-
-  // build collection of MCParticles
-  for(int IHEP=0; IHEP<NHEP; IHEP++ ) {
-    Particle* mcp =  dynamic_cast<Particle*> ( primaries->getElementAt( IHEP ) );
-    setCharge(mcp);
-    //Boost to lab frame with crossing angle alpha
-    if (alpha != 0) {
-
-      double c_light = 299.792;
-      const double* p = mcp->getMomentum();
-      const double m  = mcp->getMass();
-      //double e = mcp->getEnergy();
-      // after the transformation (boost in x-direction)
-      double pPrime[3];
-      pPrime[0] = betagamma * sqrt(sqr(p[0])+sqr(p[1])+sqr(p[2])+sqr(m)) + gamma * p[0];
-      pPrime[1] = p[1];
-      pPrime[2] = p[2];
-
-      const double* v = mcp->getVertex();
-      const double t = mcp->getTime();
-      double vPrime[3];
-      double tPrime;
-      tPrime = gamma * t + betagamma * v[0] / c_light;
-      vPrime[0] = gamma * v[0] + betagamma * c_light * t;
-      vPrime[1] = v[1];
-      vPrime[2] = v[2];
-
-      // py and pz remain the same, E changes implicitly with px
-      mcp->setMomentum( pPrime );
-      mcp->setVertex( vPrime );
-      mcp->setTime( tPrime );
-      //cout << IHEP  << " alpha=" << alpha  <<" gamma=" << gamma << " betagamma=" << betagamma  << endl;
-      //	  cout << IHEP  << " unboosted momentum: ("  << e                << "," << p[0]      << "," << p[1]      << ","  <<  p[2]      << ")" << endl;
-      //	  cout << IHEP  << "   boosted momentum: ("  << mcp->getEnergy() << "," <<  betagamma * sqrt(sqr(p[0])+sqr(p[1])+sqr(p[2])+sqr(m)) + gamma * p[0] << ","  << pPrime[1] << "," <<  pPrime[2] << ")" << endl;
-      //	  cout << IHEP  << "                     ("  << mcp->getEnergy()-e << ","  << ( betagamma * sqrt(sqr(p[0])+sqr(p[1])+sqr(p[2])+sqr(m)) + gamma * p[0])-p[0] << ","  << pPrime[1]-p[1] << ","  <<  pPrime[2]-p[2] << ")" << endl;
-      //cout << IHEP  << "   unboosted vertex: (" << t      << "," << v[0]      << "," << v[1]      << "," <<  v[2]      << ")" << endl;
-      //	  cout << IHEP  << "     boosted vertex: (" << tPrime << "," << vPrime[0] << "," << vPrime[1] << "," <<  vPrime[2] << ")" << endl;
-      //	  cout << IHEP  << "     boosted vertex: (" << tPrime-t << "," << vPrime[0]-v[0] << "," << vPrime[1]-v[1] << "," <<  vPrime[2]-v[2] << ")" << endl;
-    }
-    // apply z spread
-    if (zspreadparameter != 0){
-      const double* v = mcp->getVertex();
-      double vPrime[3];
-      vPrime[0] = v[0];
-      vPrime[1] = v[1];
-      vPrime[2] = v[2] + zspread;
-      mcp->setVertex(vPrime);
-    }
-    col[IHEP] = dynamic_cast<MCParticle*>( mcp );
-  }
-
-  // check if there is at least one particle
-  if( NHEP == 0 ) return;
-  
-  // create G4PrimaryVertex object
-  double particle_time = 0.0;
-  G4PrimaryVertex* vertex = new G4PrimaryVertex(particle_position,particle_time);
-  // put initial particles to the vertex
-  for( size_t i=0; i< col.size(); i++ ){
-    MCParticle* mcp = col[i];
-    if ( mcp->getParents().size()==0 )   {
-      G4PrimarySet g4set = getRelevantParticles(mcp);
-      for (G4PrimarySet::iterator setit=g4set.begin(); setit != g4set.end(); setit++ ){
-	vertex->SetPrimary(*setit);
-	//cout << "G4PrimaryParticle ("<< (*setit)->GetPDGcode() << ") added to G4PrimaryVertex." << endl;
-      }
-    }
-  }
-  // Put the vertex to G4Event object
-  evt->AddPrimaryVertex(vertex);
-}
-
-DD4hep::lcio::LcioGeneratorAction::G4PrimarySet 
-DD4hep::lcio::LcioGeneratorAction::getRelevantParticles(MCParticle* p)      {
-  //    log each particle which has been called, to avoid double counting and increase efficiency
-  m_convertedParticles.insert(p);
-  G4ParticleMap::iterator mcpIT;
-  G4PrimarySet relevantParticlesSet; //holds all relevant decay particles of p
-  
-  // logic starts here:
-  // CASE1: if p is a stable particle: search for it in G4ParticleMap
-  // if it is already there: get G4PrimaryParticle version of p from G4ParticleMap
-  // else: create G4PrimaryParticle version of p and write it to G4ParticleMap
-  // in the end: insert this single G4PrimaryParticle verion of p to the 
-  // relevant particle list and return this "list".
-  if (p->getGeneratorStatus() == 1)    {
-    G4PrimaryParticle* g4p;
-    mcpIT = m_g4ParticleMap.find( p );
-    if( mcpIT != m_g4ParticleMap.end() ){
-      g4p =  mcpIT->second;
-    }
-    else    {
-      int    IDHEP = p->getPDG();
-      double PHEP1 = p->getMomentum()[0];
-      double PHEP2 = p->getMomentum()[1];
-      double PHEP3 = p->getMomentum()[2];
-      double PHEP5 = p->getMass();
-      // create G4PrimaryParticle object
-      g4p = new G4PrimaryParticle(IDHEP, PHEP1*GeV, PHEP2*GeV, PHEP3*GeV);
-      g4p->SetMass(PHEP5*GeV);
-      m_g4ParticleMap[ p ] = g4p;  
-    }
-    relevantParticlesSet.insert(g4p);
-    return relevantParticlesSet;
-  }
-
-  // CASE2: if p is not stable: get first decay daughter and calculate the proper time of p
-  // if proper time is not zero: particle is "relevant", since it carries vertex information
-  // if p is already in G4ParticleMap: take it
-  // otherwise: create G4PrimaryParticle version of p and write it to G4ParticleMap
-  // now collect all relevant particles of all daughters and setup "relevant mother-
-  // daughter-relations" between relevant decay particles and G4PrimaryParticle version of p
-  // in the end: insert only the G4PrimaryParticle version of p to the
-  // relevant particle list and return this "list". The added particle has now the correct pre-assigned
-  // decay products and (hopefully) the right lifetime.
-  else if(  p->getDaughters().size() > 0  ) {  //fg: require that there is at least one daughter - otherwise forget the particle
-    cout << "case 2" <<  endl;
-    // calculate proper time
-    MCParticle* dp = p->getDaughters()[0];
-    double proper_time = fabs((dp->getTime()-p->getTime()) * p->getMass()) / p->getEnergy();
-    //  fix by S.Morozov for real != 0
-    double aPrecision = dp->getTime() * p->getMass() / p->getEnergy();
-    double bPrecision =  p->getTime() * p->getMass() / p->getEnergy();
-    double ten = 10;
-    double proper_time_Precision =  pow(ten,-DBL_DIG)*fmax(fabs(aPrecision),fabs(bPrecision));
-
-    bool isProperTimeZero = ( proper_time <= proper_time_Precision );
-
-    // -- remove original --- if (proper_time != 0) {
-    if ( isProperTimeZero == false ) {
-      G4PrimaryParticle* g4p;
-      mcpIT = m_g4ParticleMap.find( p );
-      if( mcpIT != m_g4ParticleMap.end() ){
-	g4p =  mcpIT->second;
-      }
-      else   {
-	int    IDHEP = p->getPDG();    
-	double PHEP1 = p->getMomentum()[0];
-	double PHEP2 = p->getMomentum()[1];
-	double PHEP3 = p->getMomentum()[2];	
-	double PHEP5 = p->getMass();
-	// create G4PrimaryParticle object
-	g4p = new G4PrimaryParticle( IDHEP, PHEP1*GeV, PHEP2*GeV, PHEP3*GeV );	
-	g4p->SetMass( PHEP5*GeV );
-	g4p->SetProperTime( proper_time*ns );
-	m_g4ParticleMap[ p ] = g4p;
-	G4PrimarySet vec3;
-	for (size_t i=0; i<p->getDaughters().size(); i++){
-	  if (m_convertedParticles.count(p->getDaughters()[i])==0)  {
-	    G4PrimarySet vec2 = getRelevantParticles(p->getDaughters()[i]);
-	    G4PrimarySet::iterator setit;
-	    for (setit=vec2.begin(); setit != vec2.end(); setit++ ){
-	      vec3.insert(*setit);
-	    }
-	  }
-	}
-	G4PrimarySet::iterator setit;
-	for (setit=vec3.begin(); setit != vec3.end(); setit++ ){
-	  g4p->SetDaughter(*setit);
-	}
-      }
-      relevantParticlesSet.insert(g4p);
-      return relevantParticlesSet;
-    }
-
-    // CASE3: if p is not stable AND has zero lifetime: forget about p and retrieve all relevant
-    // decay particles of all daughters of p. In this case this step of recursion is just there for
-    // collecting all relevant decay products of daughters (and return them).
-    else   {
-      for (size_t i=0; i<p->getDaughters().size(); i++){
-	if (m_convertedParticles.count(p->getDaughters()[i])==0){
-	  G4PrimarySet vec2 = getRelevantParticles(p->getDaughters()[i]);
-	  G4PrimarySet::iterator setit;
-	  for (setit=vec2.begin(); setit != vec2.end(); setit++ ){
-	    relevantParticlesSet.insert(*setit);
-	  }
-	}
-      }
-      return relevantParticlesSet;
-    }
-  }
-  //fg: add a default return
-  return relevantParticlesSet;
-}
-
-#include "DDG4/Factories.h"
-DECLARE_GEANT4ACTION_NS(DD4hep::lcio,LcioGeneratorAction)
diff --git a/DDG4/lcio/EventReader.h b/DDG4/lcio/EventReader.h
deleted file mode 100644
index 00219a933..000000000
--- a/DDG4/lcio/EventReader.h
+++ /dev/null
@@ -1,125 +0,0 @@
-// $Id: Geant4Converter.cpp 603 2013-06-13 21:15:14Z markus.frank $
-//====================================================================
-//  AIDA Detector description implementation for LCD
-//--------------------------------------------------------------------
-//
-//====================================================================
-#ifndef DD4HEP_DDG4_LCIO_EVENTREADER_H
-#define DD4HEP_DDG4_LCIO_EVENTREADER_H
-
-// Framework include files
-#include "DD4hep/Primitives.h"
-#include "DDG4/Geant4GeneratorAction.h"
-
-// C/C++ include files
-#include <set>
-#include <map>
-
-// Forward declarations
-class G4Event;
-class G4PrimaryParticle;
-namespace IO    { class LCReader;        }
-namespace UTIL  { class LCStdHepRdr;     }
-namespace EVENT { class MCParticle;      }
-namespace IMPL  { class MCParticleImpl;  }
-namespace IMPL  { class LCCollectionVec; }
-
-
-/*
- *   DD4hep namespace declaration
- */
-namespace DD4hep   {
-  /*
-   *   lcio namespace declaration
-   */
-  namespace lcio {
-
-    /** @class EventReader EventReader.h DDG4/EventReader.h
-     * 
-     * Base class to read lcio files
-     *
-     * @author  P.Kostka (main author)
-     * @author  M.Frank  (code reshuffeling into new DDG4 scheme)
-     * @version 1.0
-     */
-    class EventReader  {
-    public:
-      typedef IMPL::LCCollectionVec Particles;
-    protected:
-      /// File name
-      std::string m_name;
-    public:
-      /// Initializing constructor
-      EventReader(const std::string& nam);
-      /// Default destructor
-      virtual ~EventReader();
-      /// File name
-      const std::string& name()  const   {  return m_name;   }
-      /// Read an event and return a LCCollectionVec of MCParticles.
-      virtual Particles *readEvent() = 0;
-    };
-
-    /** @class LcioGeneratorAction Geant4GeneratorAction.h DDG4/Geant4GeneratorAction.h
-     *
-     * Concrete implementation of the Geant4 generator action base class
-     * populating Geant4 primaries from LCIO and HepStd files.
-     *
-     * @author  P.Kostka (main author)
-     * @author  M.Frank  (code reshuffeling into new DDG4 scheme)
-     * @version 1.0
-     */
-    class LcioGeneratorAction : public Simulation::Geant4GeneratorAction {
-    public:
-      typedef EVENT::MCParticle     MCParticle;
-      typedef IMPL::MCParticleImpl  Particle;
-      typedef IMPL::LCCollectionVec Particles;
-      typedef std::set<MCParticle*>                    LCPrimarySet;
-      typedef std::set<G4PrimaryParticle*>             G4PrimarySet;
-      typedef std::map<MCParticle*,G4PrimaryParticle*> G4ParticleMap;
-    protected:
-      /// Property: input file
-      std::string   m_input;
-      /// Property: spread of primary vertex in Z
-      double        m_primaryVertexSpreadZ;
-      /// Property: lorentz transformation angle
-      double        m_lorentzTransformationAngle;
-      /// Property: SYNCEVT
-      int           m_SYNCEVT;
-      /// map of partciles already import to Geant4 event
-      G4ParticleMap m_g4ParticleMap;
-      /// Set of LCIO particles already converted
-      LCPrimarySet  m_convertedParticles;
-      /// Event reader object
-      EventReader*  m_reader;
-
-      /// Read an event and return a LCCollectionVec of MCParticles.
-      Particles*    readEvent(int which);
-    public:
-      /// Standard constructor
-      LcioGeneratorAction(Simulation::Geant4Context* context, const std::string& name);
-      /// Default destructor
-      virtual ~LcioGeneratorAction();
-      /// Callback to generate primary particles
-      virtual void operator()(G4Event*);
-      G4PrimarySet getRelevantParticles(MCParticle* p);
-    };
-  }     /* End namespace lcio   */
-}       /* End namespace DD4hep */
-
-#include "DD4hep/Plugins.h"
-namespace {
-  /// Factory to create Geant4 physics constructions
-  template <typename P> class Factory<P, DD4hep::lcio::EventReader*(std::string, int)> {  public:
-    static void Func(void *ret, void*, const std::vector<void*>& a, void*) 
-    { *(DD4hep::lcio::EventReader**)ret = (DD4hep::lcio::EventReader*)new P(*(std::string*)a[0],*(int*)a[1]);}
-  };
-}
-/// Plugin defintion to create event reader objects
-#define DECLARE_LCIO_EVENT_READER(name)					\
-  PLUGINSVC_FACTORY_WITH_ID(name,std::string(#name),DD4hep::lcio::EventReader*(std::string,int))
-
-/// Plugin defintion to create event reader objects
-#define DECLARE_LCIO_EVENT_READER_NS(ns,name) typedef ns::name __##name##__; \
-  PLUGINSVC_FACTORY_WITH_ID(__##name##__,std::string(#name),DD4hep::lcio::EventReader*(std::string,int))
-
-#endif  /* DD4HEP_DDG4_LCIO_EVENTREADER_H  */
diff --git a/DDG4/lcio/Geant4Output2LCIO.cpp b/DDG4/lcio/Geant4Output2LCIO.cpp
index 46019dfa9..ebad8b6a9 100644
--- a/DDG4/lcio/Geant4Output2LCIO.cpp
+++ b/DDG4/lcio/Geant4Output2LCIO.cpp
@@ -39,7 +39,6 @@ namespace DD4hep {
      */
     class Geant4Output2LCIO : public Geant4OutputAction  {
     protected:
-      Geometry::VolumeManager m_volMgr;
       lcio::LCWriter*  m_file;
       int              m_runNo;
       
@@ -84,6 +83,8 @@ namespace DD4hep {
 #include "DDG4/Geant4HitCollection.h"
 #include "DDG4/Geant4DataConversion.h"
 #include "DDG4/Geant4Context.h"
+#include "DDG4/Geant4Particle.h"
+#include "DDG4/Geant4Data.h"
 
 //#include "DDG4/Geant4Output2LCIO.h"
 #include "G4Event.hh"
@@ -99,14 +100,13 @@ using namespace DD4hep::Simulation;
 using namespace DD4hep;
 using namespace std;
 
-
 #include "DDG4/Factories.h"
 DECLARE_GEANT4ACTION(Geant4Output2LCIO)
 
 
 /// Standard constructor
 Geant4Output2LCIO::Geant4Output2LCIO(Geant4Context* ctxt, const string& nam)
-: Geant4OutputAction(ctxt,nam), m_volMgr(), m_file(0), m_runNo(0)
+: Geant4OutputAction(ctxt,nam), m_file(0), m_runNo(0)
 {
   InstanceCount::increment(this);
 }
@@ -125,9 +125,6 @@ void Geant4Output2LCIO::beginRun(const G4Run* )  {
   if ( 0 == m_file && !m_output.empty() )   {
     m_file = lcio::LCFactory::getInstance()->createLCWriter();
     m_file->open(m_output,lcio::LCIO::WRITE_NEW);
-    // Get the volume manager here: 
-    // in the constructor the geometry may not yet be built!
-    m_volMgr = context()->lcdd().volumeManager();
   }
 }
 
@@ -159,7 +156,6 @@ void Geant4Output2LCIO::begin(const G4Event* /* event */)  {
   context()->event().addExtension<lcio::LCEventImpl>( e );
 }
 
-
 /// Callback to store the Geant4 event
 void Geant4Output2LCIO::saveEvent(OutputContext<G4Event>& ctxt)  {
   lcio::LCEventImpl* e = context()->event().extension<lcio::LCEventImpl>();
@@ -167,19 +163,31 @@ void Geant4Output2LCIO::saveEvent(OutputContext<G4Event>& ctxt)  {
   e->setEventNumber(ctxt.context->GetEventID());
   e->setDetectorName(context()->lcdd().header().name());
   e->setRunNumber(m_runNo);
-
+  lcio::LCEventImpl* evt = context()->event().extension<lcio::LCEventImpl>();
+  Geant4ParticleMap* part_map = context()->event().extension<Geant4ParticleMap>(false);
+  if ( part_map )   {
+    print("+++ Saving %d LCIO particles....",int(part_map->particleMap.size()));
+    if ( part_map->particleMap.size() > 0 )  {
+      typedef pair<const Geant4Context*,const Geant4ParticleMap*> _Args;
+      typedef Geant4Conversion<lcio::LCCollectionVec,_Args> _C;
+      const _C& cnv = _C::converter(typeid(Geant4ParticleMap));
+      lcio::LCCollectionVec* col = cnv(_Args(context(),part_map));
+      evt->addCollection(col,"McParticles");
+    }
+  }
 }
 
 /// Callback to store each Geant4 hit collection
 void Geant4Output2LCIO::saveCollection(OutputContext<G4Event>& /* ctxt */, G4VHitsCollection* collection)  {
   size_t nhits = collection->GetSize();
   std::string hc_nam = collection->GetName();
+  print("+++ Saving LCIO collection %s with %d entries....",hc_nam.c_str(),int(nhits));
   if ( nhits > 0 )   {
-    typedef pair<Geometry::VolumeManager,G4VHitsCollection*> _Args;
+    typedef pair<const Geant4Context*,G4VHitsCollection*> _Args;
     typedef Geant4Conversion<lcio::LCCollectionVec,_Args> _C;
     const _C& cnv = _C::converter(typeid(Geant4HitCollection));
     lcio::LCEventImpl* evt = context()->event().extension<lcio::LCEventImpl>();
-    lcio::LCCollectionVec* col = cnv(_Args(m_volMgr,collection));
+    lcio::LCCollectionVec* col = cnv(_Args(context(),collection));
     evt->addCollection(col,hc_nam);
   }
 }
diff --git a/DDG4/lcio/HepEventReader.cpp b/DDG4/lcio/HepEventReader.cpp
index 3548c10df..60596e130 100644
--- a/DDG4/lcio/HepEventReader.cpp
+++ b/DDG4/lcio/HepEventReader.cpp
@@ -6,7 +6,7 @@
 //====================================================================
 
 // Framework include files
-#include "EventReader.h"
+#include "LCIOEventReader.h"
 
 // C/C++ include files
 #include <fstream>
@@ -18,7 +18,7 @@ namespace DD4hep   {
   /*
    *   lcio namespace declaration
    */
-  namespace lcio {
+  namespace Simulation {
 
     /** @class HepEventReader HepEventReader.h DDG4/HepEventReader.h
      * 
@@ -29,7 +29,7 @@ namespace DD4hep   {
      * @author  M.Frank  (code reshuffeling into new DDG4 scheme)
      * @version 1.0
      */
-    struct HepEventReader : public EventReader  {
+    struct HepEventReader : public LCIOEventReader  {
     protected:
       std::ifstream m_input;
       int m_format;
@@ -39,7 +39,7 @@ namespace DD4hep   {
       /// Default destructor
       virtual ~HepEventReader();
       /// Read an event and return a LCCollectionVec of MCParticles.
-      virtual Particles *readEvent();
+      virtual EVENT::LCCollection *readParticles();
     };
   }     /* End namespace lcio   */
 }       /* End namespace DD4hep */
@@ -51,15 +51,15 @@ namespace DD4hep   {
 #include "lcio.h"
 using namespace IMPL;
 using namespace EVENT;
+using namespace DD4hep::Simulation;
 #define HEPEvt 1
 
 // Factory entry
-typedef DD4hep::lcio::HepEventReader HepEventReader;
 DECLARE_LCIO_EVENT_READER(HepEventReader)
 
 /// Initializing constructor
 HepEventReader::HepEventReader(const std::string& nam, int fmt) 
-: EventReader(nam), m_format(fmt)
+: LCIOEventReader(nam), m_format(fmt)
 {
 }
 
@@ -74,7 +74,7 @@ MCParticleImpl* cast_particle(LCObject* obj)  {
 }
 
 /// Read an event and return a LCCollectionVec of MCParticles.
-HepEventReader::Particles *HepEventReader::readEvent()   {
+EVENT::LCCollection *HepEventReader::readParticles()   {
   static const double c_light = 299.792;// mm/ns
   //
   //  Read the event, check for errors
diff --git a/DDG4/lcio/LCIOConversions.cpp b/DDG4/lcio/LCIOConversions.cpp
index 0cd2b1b1e..0e3a6515e 100644
--- a/DDG4/lcio/LCIOConversions.cpp
+++ b/DDG4/lcio/LCIOConversions.cpp
@@ -13,11 +13,14 @@
 #include "DD4hep/Printout.h"
 #include "DDG4/Geant4HitCollection.h"
 #include "DDG4/Geant4DataConversion.h"
+#include "DDG4/Geant4Context.h"
+#include "DDG4/Geant4Primary.h"
 #include "DDG4/Geant4Data.h"
 
 // LCIO includes
 #include "IMPL/LCCollectionVec.h"
 //
+#include "IMPL/LCEventImpl.h"
 #include "IMPL/ClusterImpl.h"
 #include "IMPL/SimTrackerHitImpl.h"
 #include "IMPL/SimCalorimeterHitImpl.h"
@@ -38,6 +41,7 @@ namespace DD4hep {
   namespace Simulation   {
 
     typedef Geometry::VolumeManager VolMgr;
+    typedef Geometry::IDDescriptor  IDDescriptor;
 
     /// Data conversion interface calling lower level explicit convetrers
     /**
@@ -46,7 +50,7 @@ namespace DD4hep {
      */
     template <> lcio::LCCollectionVec*
     Geant4DataConversion<lcio::LCCollectionVec,
-			 pair<VolMgr,G4VHitsCollection*>,
+			 pair<const Geant4Context*,G4VHitsCollection*>,
 			 Geant4HitCollection>::operator()(const arg_t& args)  const {
       G4VHitsCollection* c = args.second;
       Geant4HitCollection* coll = dynamic_cast<Geant4HitCollection*>(c);
@@ -60,10 +64,10 @@ namespace DD4hep {
 				 "Cannot save the collection entries of:"+c->GetName());
     }
 
-    /// Data conversion interface creating lcio::SimTrackerHitImpl from SimpleTracker::Hit structures
+    /// Data conversion interface creating lcio::SimTrackerHitImpl from Geant4Tracker::Hit structures
     /**
      *  This converter is to be used, when the sensitive detectors create fill collections
-     *  of type Geant4HitCollection with objects of type **SimpleTracker::Hit**.
+     *  of type Geant4HitCollection with objects of type **Geant4Tracker::Hit**.
      *  The original objects are untouched and are automatically when the hosting
      *  Geant4HitCollection object is released.
      *
@@ -72,38 +76,43 @@ namespace DD4hep {
      */
     template <> lcio::LCCollectionVec* 
     Geant4DataConversion<lcio::LCCollectionVec,
-			 pair<VolMgr,Geant4HitCollection*>,
-			 SimpleTracker::Hit>::operator()(const arg_t& args)  const   {
-
-      Geant4HitCollection* coll = args.second;
-      size_t     nhits = coll->GetSize();
+			 pair<const Geant4Context*,Geant4HitCollection*>,
+			 Geant4Tracker::Hit>::operator()(const arg_t& args)  const   {
+
+      Geant4HitCollection* coll  = args.second;
+      size_t               nhits = coll->GetSize();
+      string               dsc   = encoding(coll->sensitiveDetector());
+      Geant4ParticleMap*   pm    = args.first->event().extension<Geant4ParticleMap>();
+      lcio::LCEventImpl*   lc_evt    = args.first->event().extension<lcio::LCEventImpl>();
+      EVENT::LCCollection* lc_part   = lc_evt->getCollection("McParticles");
       lcio::LCCollectionVec* lc_coll = new lcio::LCCollectionVec(lcio::LCIO::SIMTRACKERHIT);
+      UTIL::CellIDEncoder<SimTrackerHit> decoder(dsc,lc_coll);  
       lc_coll->reserve(nhits);
-      if ( nhits > 0 )  {
-	SimpleHit* hit   = coll->hit(0);
-	string     dsc   = encoding(args.first, hit->cellID);
-	UTIL::CellIDEncoder<SimTrackerHit> decoder(dsc,lc_coll);  
-	for(size_t i=0; i<nhits; ++i)   {
-	  const SimpleTracker::Hit* g4_hit = coll->hit(i);
-	  double pos[3] = {g4_hit->position.x(), g4_hit->position.y(), g4_hit->position.z()};
-	  lcio::SimTrackerHitImpl* lc_hit = new lcio::SimTrackerHitImpl;  
-	  lc_hit->setCellID0( (g4_hit->cellID >>    0          ) & 0xFFFFFFFF); 
-	  lc_hit->setCellID1( (g4_hit->cellID >> sizeof( int ) ) & 0xFFFFFFFF);
-	  lc_hit->setPosition(pos);
-	  lc_hit->setEDep(g4_hit->energyDeposit);
-	  lc_hit->setTime(g4_hit->truth.time);
-	  lc_hit->setMomentum( g4_hit->momentum.x(), g4_hit->momentum.y() , g4_hit->momentum.z() );
-	  lc_hit->setPathLength( g4_hit->length);
-	  lc_coll->addElement(lc_hit);
-	}
+      for(size_t i=0; i<nhits; ++i)   {
+	const Geant4Tracker::Hit* hit = coll->hit(i);
+	const Geant4Tracker::Hit::Contribution& t = hit->truth;
+	int trackID = pm->particleID(t.trackID);
+	EVENT::MCParticle* lc_mcp = (EVENT::MCParticle*)lc_part->getElementAt(trackID);
+	double pos[3] = {hit->position.x(), hit->position.y(), hit->position.z()};
+	float  mom[3] = {hit->momentum.x(), hit->momentum.y(), hit->momentum.z()};
+	lcio::SimTrackerHitImpl* lc_hit = new lcio::SimTrackerHitImpl;  
+	lc_hit->setCellID0( (hit->cellID >>    0          ) & 0xFFFFFFFF); 
+	lc_hit->setCellID1( (hit->cellID >> sizeof( int ) ) & 0xFFFFFFFF);
+	lc_hit->setEDep(hit->energyDeposit);
+	lc_hit->setPathLength(hit->length);
+	lc_hit->setTime(hit->truth.time);
+	lc_hit->setMCParticle(lc_mcp);
+	lc_hit->setPosition(pos);
+	lc_hit->setMomentum(mom);
+	lc_coll->addElement(lc_hit);
       }
       return lc_coll;
     }
 
-    /// Data conversion interface creating lcio::SimCalorimeterHitImpl from SimpleCalorimeter::Hit structures
+    /// Data conversion interface creating lcio::SimCalorimeterHitImpl from Geant4Calorimeter::Hit structures
     /**
      *  This converter is to be used, when the sensitive detectors create fill collections
-     *  of type Geant4HitCollection with objects of type **SimpleCalorimeter::Hit**.
+     *  of type Geant4HitCollection with objects of type **Geant4Calorimeter::Hit**.
      *  The original objects are untouched and are automatically when the hosting
      *  Geant4HitCollection object is released.
      *
@@ -112,32 +121,43 @@ namespace DD4hep {
      */
     template <> lcio::LCCollectionVec* 
     Geant4DataConversion<lcio::LCCollectionVec,
-			 pair<VolMgr,Geant4HitCollection*>,
-			 SimpleCalorimeter::Hit>::operator()(const arg_t& args)  const  {
+			 pair<const Geant4Context*,Geant4HitCollection*>,
+			 Geant4Calorimeter::Hit>::operator()(const arg_t& args)  const  {
+      typedef Geant4HitData::Contributions Contributions;
       Geant4HitCollection* coll = args.second;
-      size_t     nhits = coll->GetSize();
+      size_t nhits = coll->GetSize();
+      string   dsc = encoding(coll->sensitiveDetector());
+      Geant4ParticleMap*   pm        = args.first->event().extension<Geant4ParticleMap>();
+      lcio::LCEventImpl*   lc_evt    = args.first->event().extension<lcio::LCEventImpl>();
+      EVENT::LCCollection* lc_parts  = lc_evt->getCollection("McParticles");
       lcio::LCCollectionVec* lc_coll = new lcio::LCCollectionVec(lcio::LCIO::SIMCALORIMETERHIT);	
+      UTIL::CellIDEncoder<SimCalorimeterHit> decoder(dsc,lc_coll);
       lc_coll->setFlag(UTIL::make_bitset32(LCIO::CHBIT_LONG,LCIO::CHBIT_STEP,LCIO::CHBIT_ID1)); 
       lc_coll->reserve(nhits);
-      if ( nhits > 0 )   {
-	SimpleHit* hit   = coll->hit(0);
-	string     dsc   = encoding(args.first, hit->cellID);
-	UTIL::CellIDEncoder<SimCalorimeterHit> decoder(dsc,lc_coll);
-	for(size_t i=0; i<nhits; ++i)   {
-	  const SimpleCalorimeter::Hit* g4_hit = coll->hit(i);
-	  float pos[3] = {g4_hit->position.x(), g4_hit->position.y(), g4_hit->position.z()};
-	  lcio::SimCalorimeterHitImpl*  lc_hit = new lcio::SimCalorimeterHitImpl;
-	  lc_hit->setCellID0( ( g4_hit->cellID >>    0          ) & 0xFFFFFFFF ); 
-	  lc_hit->setCellID1( ( g4_hit->cellID >> sizeof( int ) ) & 0xFFFFFFFF );
-	  lc_hit->setPosition(pos);
-	  lc_hit->setEnergy( g4_hit->energyDeposit );
-	  lc_coll->addElement(lc_hit);
+      for(size_t i=0; i<nhits; ++i)   {
+	const Geant4Calorimeter::Hit* hit = coll->hit(i);
+	float pos[3] = {hit->position.x(), hit->position.y(), hit->position.z()};
+	lcio::SimCalorimeterHitImpl*  lc_hit = new lcio::SimCalorimeterHitImpl;
+	lc_hit->setCellID0(( hit->cellID >>    0       ) & 0xFFFFFFFF); 
+	lc_hit->setCellID1(( hit->cellID >> sizeof(int)) & 0xFFFFFFFF); // ???? 
+	lc_hit->setPosition(pos);
+	lc_hit->setEnergy( hit->energyDeposit );
+	lc_coll->addElement(lc_hit);
+	/// Now add the individual track contributions to the LCIO hit structure
+	for(Contributions::const_iterator j=hit->truth.begin(); j!=hit->truth.end(); ++j)   {
+	  const Geant4HitData::Contribution& c = *j;
+	  int trackID = pm->particleID(c.trackID);
+	  EVENT::MCParticle* lc_mcp = (EVENT::MCParticle*)lc_parts->getElementAt(trackID);
+	  lc_hit->addMCParticleContribution(lc_mcp,c.deposit,c.time);
 	}
       }
       return lc_coll;
     }
 
-    template <typename T> lcio::LCCollectionVec* moveEntries(Geant4HitCollection* coll, lcio::LCCollectionVec* lc_coll)  {
+    template <typename T> 
+    lcio::LCCollectionVec* moveEntries(Geant4HitCollection* coll,
+				       lcio::LCCollectionVec* lc_coll)
+    {
       size_t nhits = coll->GetSize();
       lc_coll->reserve(nhits);
       for(size_t i=0; i<nhits; ++i)   {
@@ -165,17 +185,13 @@ namespace DD4hep {
      */
     template <> lcio::LCCollectionVec* 
     Geant4DataConversion<lcio::LCCollectionVec,
-			 pair<VolMgr,Geant4HitCollection*>,
-			 lcio::SimTrackerHitImpl>::operator()(const arg_t& args)  const 
+			 pair<const Geant4Context*,Geant4HitCollection*>,
+			 lcio::SimTrackerHitImpl>::operator()(const arg_t& args)  const
     {
-      Geant4HitCollection* coll = args.second;
-      lcio::SimTrackerHitImpl* hit = coll->hit(0);
-      long long int id1 = hit->getCellID1(), id0=hit->getCellID0();
-      long long int cellID = (((id1<<32)&0xFFFFFFFF00000000)|(id0&0xFFFFFFFF));
-      string dsc = encoding(args.first, cellID);
-      lcio::LCCollectionVec* lc_coll = new lcio::LCCollectionVec(lcio::LCIO::SIMTRACKERHIT);
-      UTIL::CellIDEncoder<SimTrackerHit> decoder(dsc,lc_coll);  
-      return moveEntries<lcio::SimTrackerHitImpl>(args.second,lc_coll);
+      string    dsc = encoding(args.second->sensitiveDetector());
+      output_t* lc  = new lcio::LCCollectionVec(lcio::LCIO::SIMTRACKERHIT);
+      UTIL::CellIDEncoder<SimTrackerHit> decoder(dsc,lc);
+      return moveEntries<lcio::SimTrackerHitImpl>(args.second,lc);
     }
 
     /// Data conversion interface moving lcio::SimCalorimeterHitImpl objects from a Geant4HitCollection to a LCCollectionVec
@@ -193,15 +209,11 @@ namespace DD4hep {
      */
     template <> lcio::LCCollectionVec* 
     Geant4DataConversion<lcio::LCCollectionVec,
-			 pair<VolMgr,Geant4HitCollection*>,
+			 pair<const Geant4Context*,Geant4HitCollection*>,
 			 lcio::SimCalorimeterHitImpl>::operator()(const arg_t& args)  const 
     {
-      Geant4HitCollection* coll = args.second;
-      lcio::SimCalorimeterHitImpl* hit = coll->hit(0);
-      output_t* lc = new lcio::LCCollectionVec(lcio::LCIO::SIMCALORIMETERHIT);
-      long long int id1 = hit->getCellID1(), id0=hit->getCellID0();
-      long long int cellID = (((id1<<32)&0xFFFFFFFF00000000)|(id0&0xFFFFFFFF));
-      string dsc = encoding(args.first, cellID);
+      string    dsc = encoding(args.second->sensitiveDetector());
+      output_t* lc  = new lcio::LCCollectionVec(lcio::LCIO::SIMCALORIMETERHIT);
       UTIL::CellIDEncoder<SimCalorimeterHit> decoder(dsc,lc);
       lc->setFlag(UTIL::make_bitset32(LCIO::CHBIT_LONG,LCIO::CHBIT_STEP,LCIO::CHBIT_ID1)); 
       return moveEntries<tag_t>(args.second,lc);
@@ -215,41 +227,26 @@ namespace DD4hep {
      */
     template <> lcio::LCCollectionVec* 
     Geant4DataConversion<lcio::LCCollectionVec,
-			 pair<VolMgr,Geant4HitCollection*>,
+			 pair<const Geant4Context*,Geant4HitCollection*>,
 			 lcio::ClusterImpl>::operator()(const arg_t& args)  const 
     {
       output_t* lc = new lcio::LCCollectionVec(lcio::LCIO::CLUSTER);
       return moveEntries<tag_t>(args.second,lc);
     }
-    /// Data conversion interface moving lcio::MCParticleImpl objects from a Geant4HitCollection to a LCCollectionVec
-    /** Same comments apply as for the data mover for lcio::SimCalorimeterHitImpl and lcio::SimTrackerHitImpl
-     *
-     *  @author M.Frank
-     *  @version 1.0
-     */
-    template <> lcio::LCCollectionVec* 
-    Geant4DataConversion<lcio::LCCollectionVec,
-			 pair<VolMgr,Geant4HitCollection*>,
-			 lcio::MCParticleImpl>::operator()(const arg_t& args)  const 
-    {
-      output_t* lc = new lcio::LCCollectionVec(lcio::LCIO::MCPARTICLE);
-      return moveEntries<tag_t>(args.second,lc);
-    }
 
-    typedef pair<VolMgr,G4VHitsCollection*> RAW_CONVERSION_ARGS;
-    typedef pair<VolMgr,Geant4HitCollection*> CONVERSION_ARGS;
+    typedef pair<const Geant4Context*,G4VHitsCollection*> RAW_CONVERSION_ARGS;
+    typedef pair<const Geant4Context*,Geant4HitCollection*> CONVERSION_ARGS;
     template class Geant4Conversion<lcio::LCCollectionVec,RAW_CONVERSION_ARGS>;
     DECLARE_GEANT4_HITCONVERTER(lcio::LCCollectionVec,RAW_CONVERSION_ARGS,Geant4HitCollection)
 
     template class Geant4Conversion<lcio::LCCollectionVec,CONVERSION_ARGS>;
     // Hit converters for simple Geant4Data objects
-    DECLARE_GEANT4_HITCONVERTER(lcio::LCCollectionVec,CONVERSION_ARGS,SimpleTracker::Hit)
-    DECLARE_GEANT4_HITCONVERTER(lcio::LCCollectionVec,CONVERSION_ARGS,SimpleCalorimeter::Hit)
+    DECLARE_GEANT4_HITCONVERTER(lcio::LCCollectionVec,CONVERSION_ARGS,Geant4Tracker::Hit)
+    DECLARE_GEANT4_HITCONVERTER(lcio::LCCollectionVec,CONVERSION_ARGS,Geant4Calorimeter::Hit)
     // Hit converters for standard LCIO objects
     DECLARE_GEANT4_HITCONVERTER(lcio::LCCollectionVec,CONVERSION_ARGS,lcio::SimTrackerHitImpl)
     DECLARE_GEANT4_HITCONVERTER(lcio::LCCollectionVec,CONVERSION_ARGS,lcio::SimCalorimeterHitImpl)
     DECLARE_GEANT4_HITCONVERTER(lcio::LCCollectionVec,CONVERSION_ARGS,lcio::ClusterImpl)
-    DECLARE_GEANT4_HITCONVERTER(lcio::LCCollectionVec,CONVERSION_ARGS,lcio::MCParticleImpl)
   }    // End namespace Simulation
 }      // End namespace DD4hep
 
diff --git a/DDG4/lcio/LCIOEventReader.cpp b/DDG4/lcio/LCIOEventReader.cpp
new file mode 100644
index 000000000..a4ffa7f2e
--- /dev/null
+++ b/DDG4/lcio/LCIOEventReader.cpp
@@ -0,0 +1,20 @@
+// $Id: Geant4Converter.cpp 603 2013-06-13 21:15:14Z markus.frank $
+//====================================================================
+//  AIDA Detector description implementation for LCD
+//--------------------------------------------------------------------
+//
+// @author  P.Kostka (main author)
+// @author  M.Frank  (code reshuffeling into new DDG4 scheme)
+//
+//====================================================================
+
+// Framework include files
+#include "LCIOEventReader.h"
+
+/// Initializing constructor
+DD4hep::Simulation::LCIOEventReader::LCIOEventReader(const std::string& nam) : m_name(nam)   {
+}
+
+/// Default destructor
+DD4hep::Simulation::LCIOEventReader::~LCIOEventReader()   {
+}
diff --git a/DDG4/lcio/LCIOEventReader.h b/DDG4/lcio/LCIOEventReader.h
new file mode 100644
index 000000000..b7b2a5eaf
--- /dev/null
+++ b/DDG4/lcio/LCIOEventReader.h
@@ -0,0 +1,82 @@
+// $Id: Geant4Converter.cpp 603 2013-06-13 21:15:14Z markus.frank $
+//====================================================================
+//  AIDA Detector description implementation for LCD
+//--------------------------------------------------------------------
+//
+//====================================================================
+#ifndef DD4HEP_DDG4_LCIOEVENTREADER_H
+#define DD4HEP_DDG4_LCIOEVENTREADER_H
+
+// C/C++ include files
+#include <string>
+
+// Forward declarations
+class G4Event;
+namespace IO    { class LCReader;        }
+namespace UTIL  { class LCStdHepRdr;     }
+namespace EVENT { class MCParticle;      }
+namespace EVENT { class LCCollection;    }
+namespace IMPL  { class MCParticleImpl;  }
+namespace IMPL  { class LCCollectionVec; }
+
+
+/*
+ *   DD4hep namespace declaration
+ */
+namespace DD4hep  {
+
+  /*
+   *   Simulation namespace declaration
+   */
+  namespace Simulation  {
+
+    // Forward declarations
+    class Geant4Particle;
+
+    /** @class EventReader EventReader.h DDG4/EventReader.h
+     * 
+     * Base class to read lcio files.
+     *
+     * @author  P.Kostka (main author)
+     * @author  M.Frank  (code reshuffeling into new DDG4 scheme)
+     * @version 1.0
+     */
+    class LCIOEventReader  {
+
+    public:
+      typedef Geant4Particle Particle;
+    protected:
+      /// File name
+      std::string m_name;
+
+    public:
+      /// Initializing constructor
+      LCIOEventReader(const std::string& nam);
+      /// Default destructor
+      virtual ~LCIOEventReader();
+      /// File name
+      const std::string& name()  const   {  return m_name;   }
+      /// Read an event and return a LCCollectionVec of MCParticles.
+      virtual EVENT::LCCollection *readParticles() = 0;
+    };
+
+  }     /* End namespace Simulation   */
+}       /* End namespace DD4hep */
+
+#include "DD4hep/Plugins.h"
+namespace {
+  /// Factory to create Geant4 physics constructions
+  template <typename P> class Factory<P, DD4hep::Simulation::LCIOEventReader*(std::string, int)> {  public:
+    static void Func(void *ret, void*, const std::vector<void*>& a, void*) 
+    { *(DD4hep::Simulation::LCIOEventReader**)ret = (DD4hep::Simulation::LCIOEventReader*)new P(*(std::string*)a[0],*(int*)a[1]);}
+  };
+}
+/// Plugin defintion to create event reader objects
+#define DECLARE_LCIO_EVENT_READER(name)					\
+  PLUGINSVC_FACTORY_WITH_ID(name,std::string(#name),DD4hep::Simulation::LCIOEventReader*(std::string,int))
+
+/// Plugin defintion to create event reader objects
+#define DECLARE_LCIO_EVENT_READER_NS(ns,name) typedef ns::name __##name##__; \
+  PLUGINSVC_FACTORY_WITH_ID(__##name##__,std::string(#name),DD4hep::Simulation::LCIOEventReader*(std::string,int))
+
+#endif  /* DD4HEP_DDG4_LCIOEVENTREADER_H  */
diff --git a/DDG4/lcio/LcioEventReader.cpp b/DDG4/lcio/LCIOFileReader.cpp
similarity index 66%
rename from DDG4/lcio/LcioEventReader.cpp
rename to DDG4/lcio/LCIOFileReader.cpp
index 25e4bbf89..dfa955cfb 100644
--- a/DDG4/lcio/LcioEventReader.cpp
+++ b/DDG4/lcio/LCIOFileReader.cpp
@@ -6,7 +6,7 @@
 //====================================================================
 
 // Framework include files
-#include "EventReader.h"
+#include "LCIOEventReader.h"
 
 /*
  *   DD4hep namespace declaration
@@ -15,7 +15,7 @@ namespace DD4hep   {
   /*
    *   lcio namespace declaration
    */
-  namespace lcio {
+  namespace Simulation {
 
     /** @class LcioEventReader LcioEventReader.h DDG4/LcioEventReader.h
      * 
@@ -25,52 +25,52 @@ namespace DD4hep   {
      * @author  M.Frank  (code reshuffeling into new DDG4 scheme)
      * @version 1.0
      */
-    struct LcioEventReader : public EventReader  {
+    struct LCIOFileReader : public LCIOEventReader  {
     protected:
       /// Reference to reader object
       IO::LCReader* m_reader;
     public:
       /// Initializing constructor
-      LcioEventReader(const std::string& nam, int);
+      LCIOFileReader(const std::string& nam, int);
       /// Default destructor
-      virtual ~LcioEventReader();
+      virtual ~LCIOFileReader();
       /// Read an event and return a LCCollectionVec of MCParticles.
-      virtual Particles *readEvent();
+      virtual EVENT::LCCollection *readParticles();
     };
   }
 }
 
 #include "DD4hep/Printout.h"
+#include "DD4hep/Primitives.h"
 #include "lcio.h"
 #include "EVENT/LCIO.h"
 #include "IO/LCReader.h"
 
 using namespace EVENT;
+using namespace DD4hep::Simulation;
 
 // Factory entry
-typedef DD4hep::lcio::LcioEventReader LcioEventReader;
-DECLARE_LCIO_EVENT_READER(LcioEventReader)
+DECLARE_LCIO_EVENT_READER(LCIOFileReader)
 
 /// Initializing constructor
-LcioEventReader::LcioEventReader(const std::string& nam, int /* arg */) 
-: EventReader(nam)
+LCIOFileReader::LCIOFileReader(const std::string& nam, int /* arg */) 
+: LCIOEventReader(nam)
 {
   m_reader = ::lcio::LCFactory::getInstance()->createLCReader();
-  printout(INFO,"LcioEventReader","Created file reader. Try to open input %s",nam.c_str());
+  printout(INFO,"LCIOFileReader","Created file reader. Try to open input %s",nam.c_str());
   m_reader->open(nam);
 }
 
 /// Default destructor
-LcioEventReader::~LcioEventReader()    {
-  deletePtr(m_reader);
+LCIOFileReader::~LCIOFileReader()    {
+  DD4hep::deletePtr(m_reader);
 }
 
 /// Read an event and return a LCCollectionVec of MCParticles.
-DD4hep::lcio::EventReader::Particles *LcioEventReader::readEvent()   {
+EVENT::LCCollection *LCIOFileReader::readParticles()   {
   ::lcio::LCEvent* evt = m_reader->readNextEvent();
   if ( evt ) {
-    Particles* mcVec = (Particles*)evt->getCollection(LCIO::MCPARTICLE);
-    return mcVec;
+    return evt->getCollection(LCIO::MCPARTICLE);
   }
   return 0;
 }
diff --git a/DDG4/lcio/LCIOInputAction.cpp b/DDG4/lcio/LCIOInputAction.cpp
new file mode 100644
index 000000000..697a6f705
--- /dev/null
+++ b/DDG4/lcio/LCIOInputAction.cpp
@@ -0,0 +1,344 @@
+// $Id: Geant4Converter.cpp 603 2013-06-13 21:15:14Z markus.frank $
+//====================================================================
+//  AIDA Detector description implementation for LCD
+//--------------------------------------------------------------------
+//
+// @author  P.Kostka (main author)
+// @author  M.Frank  (code reshuffeling into new DDG4 scheme)
+//
+//====================================================================
+
+// Framework include files
+#include "LCIOInputAction.h"
+#include "LCIOEventReader.h"
+#include "DD4hep/Printout.h"
+#include "DDG4/Geant4Primary.h"
+#include "DDG4/Geant4Context.h"
+#include "G4ParticleTable.hh"
+#include "G4Event.hh"
+#include "EVENT/MCParticle.h"
+#include "EVENT/LCCollection.h"
+#include "Randomize.hh"
+
+using namespace std;
+using namespace DD4hep::Simulation;
+
+typedef DD4hep::ReferenceBitMask<int> PropertyMask;
+
+/// Standard constructor
+LCIOInputAction::LCIOInputAction(Geant4Context* context, const string& name)
+  : Geant4GeneratorAction(context,name), m_reader(0)
+{
+  declareProperty("Input",          m_input);
+  declareProperty("Sync",           m_SYNCEVT=0);
+  declareProperty("Mask",           m_mask = 0);
+  declareProperty("MomentumScale",  m_momScale = 1.0);
+  m_needsControl = true;
+}
+
+/// Default destructor
+LCIOInputAction::~LCIOInputAction()   {
+}
+
+/// helper to report Geant4 exceptions
+string LCIOInputAction::issue(int i)  const  {
+  stringstream str;
+  str << "LCIOInputAction[" << name() << "]: Event " << i << " ";
+  return str.str();
+}
+
+/// Read an event and return a LCCollection of MCParticles.
+EVENT::LCCollection* LCIOInputAction::readParticles(int which)  {
+  int evid = which + m_SYNCEVT;
+  if ( 0 == m_reader )  {
+    if ( m_input.empty() )  {
+      throw runtime_error("InputAction: No inoput file declared!");
+    }
+    string err;
+    TypeName tn = TypeName::split(m_input,"|");
+    try  {
+      m_reader = PluginService::Create<LCIOEventReader*>(tn.first,tn.second,int(0));
+      if ( 0 == m_reader )   {
+	abortRun(issue(evid)+"Error creating reader plugin.",
+		 "Failed to create file reader of type %s. Cannot open dataset %s",
+		 tn.first.c_str(),tn.second.c_str());
+	return 0;
+      }
+    }
+    catch(const std::exception& e)  {
+      err = e.what();
+    }
+    if ( !err.empty() )  {
+      abortRun(issue(evid)+err,"Error when reading file %s",m_input.c_str());
+      return 0;
+    }
+  }
+  EVENT::LCCollection* parts = m_reader->readParticles();
+  if ( 0 == parts )  {
+    abortRun(issue(evid)+"Error when reading file - may be end of file.",
+	     "Error when reading file %s",m_input.c_str());
+  }
+  return parts;
+}
+
+namespace {
+  inline int GET_ENTRY(const map<EVENT::MCParticle*,int>& mcparts, EVENT::MCParticle* part)  {
+    map<EVENT::MCParticle*,int>::const_iterator ip=mcparts.find(part);
+    if ( ip == mcparts.end() )  {
+      throw runtime_error("Unknown particle identifier look-up!");
+    }
+    return (*ip).second;
+  }
+  struct FindVertex {
+    double x,y,z,t;
+    FindVertex(double xx, double yy, double zz, double tt) { x=xx; y=yy; z=zz; t=tt; }
+    bool operator()(const Geant4Vertex* o)   const  {
+      if ( fabs(o->x - x) > numeric_limits<double>::epsilon() ) return false;
+      if ( fabs(o->y - y) > numeric_limits<double>::epsilon() ) return false;
+      if ( fabs(o->z - z) > numeric_limits<double>::epsilon() ) return false;
+      if ( fabs(o->time - t) > numeric_limits<double>::epsilon() ) return false;
+      return true;
+    }
+  };
+}
+
+/// Callback to generate primary particles
+void LCIOInputAction::operator()(G4Event* event)   {
+  Geant4Event& evt = context()->event();
+  Geant4PrimaryEvent* prim = evt.extension<Geant4PrimaryEvent>();
+  Geant4PrimaryInteraction* inter = new Geant4PrimaryInteraction();
+  EVENT::LCCollection* primaries = readParticles(event->GetEventID());
+  map<EVENT::MCParticle*,int> mcparts;
+  vector<EVENT::MCParticle*> mcpcoll;
+  vector<Particle*> col;
+
+  prim->add(m_mask, inter);
+  // check if there is at least one particle
+  if ( 0 == primaries ) return;
+
+  int NHEP = primaries->getNumberOfElements();
+  // check if there is at least one particle
+  if ( NHEP == 0 ) return;
+
+  col.resize(NHEP,0);
+  mcpcoll.resize(NHEP,0);
+  for(int i=0; i<NHEP; ++i ) {
+    EVENT::MCParticle* p=dynamic_cast<EVENT::MCParticle*>(primaries->getElementAt(i));
+    mcparts[p] = i;
+    mcpcoll[i] = p;
+    col[i] = new Particle(i);
+  }
+
+  print("+++ Particle interaction with %d generator particles ++++++++++++++++++++++++",NHEP);
+  // build collection of MCParticles
+  G4ParticleTable*      tab = G4ParticleTable::GetParticleTable();
+  for(int i=0; i<NHEP; ++i )   {
+    EVENT::MCParticle* mcp = mcpcoll[i];
+    Geant4ParticleHandle p(col[i]);
+    const double mom_scale = m_momScale;
+    const double *mom   = mcp->getMomentum();
+    const double *vsx   = mcp->getVertex();
+    const double *vex   = mcp->getEndpoint();
+    const float  *spin  = mcp->getSpin();
+    const int    *color = mcp->getColorFlow();
+    G4ParticleDefinition* def = tab->FindParticle(mcp->getPDG());
+    PropertyMask status(p->status);
+
+    p->reason       = 0;
+    p->usermask     = 0;
+    p->pdgID        = mcp->getPDG();
+    p->psx          = mom_scale*mom[0]*GeV;
+    p->psy          = mom_scale*mom[1]*GeV;
+    p->psz          = mom_scale*mom[2]*GeV;
+    p->time         = mcp->getTime()*ns;
+    p->properTime   = mcp->getTime()*ns;
+    p->vsx          = vsx[0]*mm;
+    p->vsy          = vsx[1]*mm;
+    p->vsz          = vsx[2]*mm;
+    p->vex          = vex[0]*mm;
+    p->vey          = vex[1]*mm;
+    p->vez          = vex[2]*mm;
+    p->definition   = def;
+    p->process      = 0;
+    p->spin[0]      = spin[0];
+    p->spin[1]      = spin[1];
+    p->spin[2]      = spin[2];
+    p->colorFlow[0] = color[0];
+    p->colorFlow[0] = color[1];
+    p->mass         = mcp->getMass()*GeV;
+    const EVENT::MCParticleVec &par = mcp->getParents(), &dau=mcp->getDaughters();
+    for(int num=dau.size(),k=0; k<num; ++k)
+      p->daughters.insert(GET_ENTRY(mcparts,dau[k]));
+    for(int num=par.size(),k=0; k<num; ++k)
+      p->parents.insert(GET_ENTRY(mcparts,par[k]));
+
+    int genStatus = mcp->getGeneratorStatus();
+    status.set(G4PARTICLE_GEN_CREATED);
+    if ( genStatus == 0 ) status.set(G4PARTICLE_GEN_EMPTY);
+    if ( genStatus == 1 ) status.set(G4PARTICLE_GEN_STABLE); 
+    if ( genStatus == 2 ) status.set(G4PARTICLE_GEN_DECAYED);
+    if ( genStatus == 3 ) status.set(G4PARTICLE_GEN_DOCUMENTATION);
+    if ( mcp->isCreatedInSimulation() )       status.set(G4PARTICLE_SIM_CREATED);
+    if ( mcp->isBackscatter() )               status.set(G4PARTICLE_SIM_BACKSCATTER);
+    if ( mcp->vertexIsNotEndpointOfParent() ) status.set(G4PARTICLE_SIM_PARENT_RADIATED);
+    if ( mcp->isDecayedInTracker() )          status.set(G4PARTICLE_SIM_DECAY_TRACKER);
+    if ( mcp->isDecayedInCalorimeter() )      status.set(G4PARTICLE_SIM_DECAY_CALO);
+    if ( mcp->hasLeftDetector() )             status.set(G4PARTICLE_SIM_LEFT_DETECTOR);
+    if ( mcp->isStopped() )                   status.set(G4PARTICLE_SIM_STOPPED);
+    if ( mcp->isOverlay() )                   status.set(G4PARTICLE_SIM_OVERLAY);
+    inter->particles.insert(make_pair(p->id,p));
+    p.dump3(outputLevel()-1,name(),"+->");
+  }
+
+  // put initial particles to the vertex
+  vector<Geant4Vertex*> vertices;
+  double time_end = 0.0;
+
+  for( size_t i=0; i< col.size(); i++ )  {
+    Particle* p = col[i];
+    if ( p->time > time_end ) time_end = p->time;
+  }
+
+  // Create Primary Vertex object
+  set<int> missing;
+  for( size_t i=0; i< col.size(); i++ )  {
+    Geant4ParticleHandle p(col[i]);
+    PropertyMask reason(p->reason);
+    PropertyMask status(p->status);
+    bool empty   = status.isSet(G4PARTICLE_GEN_EMPTY);
+    bool stable  = status.isSet(G4PARTICLE_GEN_STABLE);
+    bool decayed = status.isSet(G4PARTICLE_GEN_DECAYED);
+    bool docu    = status.isSet(G4PARTICLE_GEN_DOCUMENTATION);
+
+    if ( docu || empty || decayed )   {
+      status.set(G4PARTICLE_GEN_HISTORY);
+    }
+    else if ( stable )   {
+      missing.insert(i);
+      reason.set(G4PARTICLE_PRIMARY);
+    }
+    else if ( !stable )  {
+      double ene = p.energy();
+      double proper_time = std::fabs((time_end - p->time) * p->mass) / ene;
+      double precision   = std::pow(10E0,-DBL_DIG)*std::max(time_end,p->time)*p->mass/ene;
+      if ( proper_time >= precision )  {
+	p->properTime = proper_time;
+      }
+      reason.set(G4PARTICLE_PRIMARY);
+      missing.insert(i);
+    }
+    else  { // Catchall: will not make it to the primary record.....
+      status.set(G4PARTICLE_GEN_HISTORY);
+    }
+  }
+  set<Geant4Particle*> missing_def;
+  for(set<int>::iterator i=missing.begin(); i != missing.end(); ++i)   {
+    Geant4ParticleHandle p(col[*i]);
+    Geant4Vertex* vtx = 0;
+    PropertyMask reason(p->reason);
+
+    if ( 0 == p->definition ) {
+      missing_def.insert(p);
+      continue;
+    }
+    vector<Geant4Vertex*>::iterator iv=find_if(vertices.begin(),vertices.end(),
+					       FindVertex(p->vsx,p->vsy,p->vsz,p->time));
+    if ( iv == vertices.end() )  {
+      vtx = new Geant4Vertex();
+      vtx->x = p->vsx;
+      vtx->y = p->vsy;
+      vtx->z = p->vsz;
+      vtx->time = p->time;
+      vertices.push_back(vtx);
+      inter->vertices.insert(make_pair(inter->vertices.size(),vtx));
+      vtx->out.insert(*i);
+    }
+    else  {
+      (*iv)->out.insert(*i);
+    }
+  }
+  if ( missing_def.size() > 0 )  {
+    for(set<Geant4Particle*>::const_iterator i=missing_def.begin(); i!= missing_def.end(); ++i)
+      Geant4ParticleHandle(*i).dump1(WARNING,name(),"!!!! Missing definition");
+    //abortRun(issue(event->GetEventID()),"Error creating primary particles.",
+    // "+++ Missing particle definitions for primary particles. Geant4 cannot handle this!");
+  }
+
+#if 0
+  // put initial particles to the vertex
+  for( size_t i=0; i< col.size(); i++ )  {
+    Particle* p = col[i];
+    if ( p->parents.size()==0 )   {
+      set<int> outgoing = relevantParticles(col, p);
+      prim_vtx->out.insert(outgoing.begin(),outgoing.end());
+    }
+  }
+#endif
+}
+
+set<int> LCIOInputAction::relevantParticles(const vector<Particle*>& particles, Geant4ParticleHandle p) const    {
+  set<int> result;
+  PropertyMask mask(p->status);
+  // CASE1: if p is a stable particle: search for it in G4ParticleMap
+  // if it is already there: get G4PrimaryParticle version of p from G4ParticleMap
+  // else: create G4PrimaryParticle version of p and write it to G4ParticleMap
+  // in the end: insert this single G4PrimaryParticle verion of p to the 
+  // relevant particle list and return this "list".
+  if ( mask.isSet(G4PARTICLE_GEN_STABLE) )  {
+    result.insert(p->id);
+    return result;
+  }
+
+  if ( p->daughters.size() > 0 )   {
+    // calculate proper time
+    Particle::Particles::iterator id;
+    int idau = *p->daughters.begin();
+    Particle* dp = particles[idau];
+    double ten = 10;
+    double mass = p->definition->GetPDGMass();
+    double proper_time = std::fabs((dp->time - p->time) * mass) / p.energy();
+    double aPrecision = dp->time * mass / p.energy();
+    double bPrecision =  p->time * mass / p.energy();
+    double proper_time_precision = std::pow(ten,-DBL_DIG)
+      * std::max(std::fabs(aPrecision),std::fabs(bPrecision));
+    bool isProperTimeZero = ( proper_time <= proper_time_precision );
+
+    // CASE2: if p is not stable: get first decay daughter and calculate the proper time of p
+    // if proper time is not zero: particle is "relevant", since it carries vertex information
+    // if p is already in G4ParticleMap: take it
+    // otherwise: create G4PrimaryParticle version of p and write it to G4ParticleMap
+    // now collect all relevant particles of all daughters and setup "relevant mother-
+    // daughter-relations" between relevant decay particles and G4PrimaryParticle version of p
+    // in the end: insert only the G4PrimaryParticle version of p to the
+    // relevant particle list and return this "list". The added particle has now the correct pre-assigned
+    // decay products and (hopefully) the right lifetime.
+    if ( isProperTimeZero == false ) {
+      result.insert(p->id);
+      p->properTime = proper_time;
+      for (id=p->daughters.begin(); id!=p->daughters.end(); ++id)  {
+	int pid = *id;
+	dp = particles[pid];
+	set<int> dau = relevantParticles(particles,dp);
+	result.insert(pid);
+	result.insert(dau.begin(),dau.end());
+      }
+      return result;
+    }
+    // CASE3: if p is not stable AND has zero lifetime: forget about p and retrieve all relevant
+    // decay particles of all daughters of p. In this case this step of recursion is just there for
+    // collecting all relevant decay products of daughters (and return them).
+    for (id=p->daughters.begin(); id!=p->daughters.end(); ++id)  {
+      int pid = *id;
+      dp = particles[pid];
+      set<int> dau = relevantParticles(particles,dp);
+      result.insert(dau.begin(),dau.end());
+    }
+  }
+  // This logic sucks!
+  // - What happens to decayed beauty particles with a displaced vertex, which are stable?
+  // - What happend to anything stable comping NOT from the very primary vertex.....
+  return result;
+}
+
+#include "DDG4/Factories.h"
+DECLARE_GEANT4ACTION(LCIOInputAction)
diff --git a/DDG4/lcio/LCIOInputAction.h b/DDG4/lcio/LCIOInputAction.h
new file mode 100644
index 000000000..9014f266c
--- /dev/null
+++ b/DDG4/lcio/LCIOInputAction.h
@@ -0,0 +1,87 @@
+// $Id: Geant4Converter.cpp 603 2013-06-13 21:15:14Z markus.frank $
+//====================================================================
+//  AIDA Detector description implementation for LCD
+//--------------------------------------------------------------------
+//
+//====================================================================
+#ifndef DD4HEP_DDG4_LCIOINPUTACTION_H
+#define DD4HEP_DDG4_LCIOINPUTACTION_H
+
+// Framework include files
+#include "DD4hep/Primitives.h"
+#include "DDG4/Geant4Particle.h"
+#include "DDG4/Geant4GeneratorAction.h"
+
+// C/C++ include files
+#include <set>
+#include <map>
+#include <vector>
+
+// Forward declarations
+class G4Event;
+namespace IO    { class LCReader;        }
+namespace UTIL  { class LCStdHepRdr;     }
+namespace EVENT { class MCParticle;      }
+namespace EVENT { class LCCollection;    }
+namespace IMPL  { class MCParticleImpl;  }
+namespace IMPL  { class LCCollectionVec; }
+
+/*
+ *   DD4hep namespace declaration
+ */
+namespace DD4hep  {
+
+  /*
+   *   Simulation namespace declaration
+   */
+  namespace Simulation  {
+
+    // Forward declarations
+    class Geant4Particle;
+    class LCIOEventReader;
+
+    /** @class InputAction Geant4GeneratorAction.h DDG4/Geant4GeneratorAction.h
+     *
+     * Concrete implementation of the Geant4 generator action base class
+     * populating Geant4 primaries from LCIO and HepStd files.
+     *
+     * @author  P.Kostka (main author)
+     * @author  M.Frank  (code reshuffeling into new DDG4 scheme)
+     * @version 1.0
+     */
+    class LCIOInputAction : public Simulation::Geant4GeneratorAction {
+
+    public:
+      typedef Geant4Particle Particle;
+
+    protected:
+      /// Property: input file
+      std::string       m_input;
+      /// Property: SYNCEVT
+      int               m_SYNCEVT;
+      /// Property; interaction mask
+      int               m_mask;
+      /// Property: Momentum downscaler for debugging
+      double            m_momScale;
+      /// Event reader object
+      LCIOEventReader*  m_reader;
+
+      /// Read an event and return a LCCollectionVec of MCParticles.
+      EVENT::LCCollection* readParticles(int which);
+      /// helper to report Geant4 exceptions
+      std::string issue(int i) const;
+
+    public:
+      /// Standard constructor
+      LCIOInputAction(Simulation::Geant4Context* context, const std::string& name);
+      /// Default destructor
+      virtual ~LCIOInputAction();
+      /// Callback to generate primary particles
+      virtual void operator()(G4Event*);
+
+      std::set<int> relevantParticles(const std::vector<Particle*>& particles, Geant4ParticleHandle p) const;
+    };
+  }     /* End namespace lcio   */
+}       /* End namespace DD4hep */
+
+#endif  /* DD4HEP_DDG4_LCIOINPUTACTION_H  */
diff --git a/DDG4/lcio/LCIOMCParticles.cpp b/DDG4/lcio/LCIOMCParticles.cpp
new file mode 100644
index 000000000..709283155
--- /dev/null
+++ b/DDG4/lcio/LCIOMCParticles.cpp
@@ -0,0 +1,150 @@
+// $Id: Geant4Converter.cpp 603 2013-06-13 21:15:14Z markus.frank $
+//====================================================================
+//  AIDA Detector description implementation for LCD
+//--------------------------------------------------------------------
+//
+//  Author     : M.Frank
+//
+//====================================================================
+
+// Framework include files
+#define DDG4_MAKE_INSTANTIATIONS
+#include "DD4hep/LCDD.h"
+#include "DD4hep/Printout.h"
+#include "DDG4/Geant4Particle.h"
+#include "DDG4/Geant4HitCollection.h"
+#include "DDG4/Geant4DataConversion.h"
+#include "DDG4/Geant4MonteCarloTruth.h"
+
+// LCIO includes
+#include "IMPL/LCCollectionVec.h"
+//
+#include "IMPL/ClusterImpl.h"
+#include "IMPL/SimTrackerHitImpl.h"
+#include "IMPL/SimCalorimeterHitImpl.h"
+#include "IMPL/MCParticleImpl.h"
+#include "UTIL/ILDConf.h"
+
+// Geant4 include files
+#include "G4ParticleDefinition.hh"
+#include "G4VProcess.hh"
+
+using namespace std;
+
+
+/*
+ *   DD4hep namespace declaration
+ */
+namespace DD4hep {
+
+  typedef ReferenceBitMask<const int> PropertyMask;
+
+  /*
+   *   Simulation namespace declaration
+   */
+  namespace Simulation   {
+
+    // Forward declarations
+    typedef Geant4Particle Particle;
+
+    /// Data conversion interface for MC particles to LCIO format
+    /**
+     *  @author M.Frank
+     *  @version 1.0
+     */
+    template <> lcio::LCCollectionVec*
+    Geant4DataConversion<lcio::LCCollectionVec,
+			 pair<const Geant4Context*,const Geant4ParticleMap*>,
+			 Geant4ParticleMap>::operator()(const arg_t& args)  const {
+      typedef MCParticleImpl MYParticleImpl;
+      typedef Geant4Conversion<output_t,pair<arg_t::first_type,arg_t::second_type> > _C;
+      typedef Geant4ParticleMap::ParticleMap ParticleMap;
+      const ParticleMap& pm = args.second->particleMap;
+      size_t nparts = pm.size();
+      lcio::LCCollectionVec* lc_coll = new lcio::LCCollectionVec(lcio::LCIO::MCPARTICLE);
+      lc_coll->reserve(nparts);
+      if ( nparts > 0 )  {
+	size_t cnt = 0;
+	map<int,int> p_ids;
+	vector<const Particle*> p_part(pm.size(),0);
+	vector<MYParticleImpl*> p_lcio(pm.size(),0);
+	// First create the particles
+	for(ParticleMap::const_iterator i=pm.begin(); i!=pm.end();++i, ++cnt)   {
+	  int id = (*i).first;
+	  const Particle* p = (*i).second;
+	  PropertyMask mask(p->status);
+	  const G4ParticleDefinition* def = p->definition;
+	  MYParticleImpl* q = (MYParticleImpl*)new lcio::MCParticleImpl();
+	  q->setPDG(p->pdgID);
+	  q->setMomentum(&p->psx);
+	  q->setVertex(&p->vsx);
+	  q->setEndpoint(&p->vex);
+	  q->setTime(p->time);
+	  q->setMass(p->mass);
+	  q->setCharge(def ? def->GetPDGCharge()/3.0 : 0); // Charge(e+) = 1 !
+
+	  // Set generator status
+	  if ( mask.isSet(G4PARTICLE_GEN_EMPTY) ) q->setGeneratorStatus(0);
+	  else if ( mask.isSet(G4PARTICLE_GEN_STABLE) ) q->setGeneratorStatus(1);
+	  else if ( mask.isSet(G4PARTICLE_GEN_DECAYED) ) q->setGeneratorStatus(2);
+	  else if ( mask.isSet(G4PARTICLE_GEN_DOCUMENTATION) ) q->setGeneratorStatus(3);
+
+	  // Set simulation status
+	  q->setCreatedInSimulation(         mask.isSet(G4PARTICLE_SIM_CREATED) );
+	  q->setBackscatter(                 mask.isSet(G4PARTICLE_SIM_BACKSCATTER) );
+	  q->setVertexIsNotEndpointOfParent( mask.isSet(G4PARTICLE_SIM_PARENT_RADIATED) );
+	  q->setDecayedInTracker(            mask.isSet(G4PARTICLE_SIM_DECAY_TRACKER) );
+	  q->setDecayedInCalorimeter(        mask.isSet(G4PARTICLE_SIM_DECAY_CALO) );
+	  q->setHasLeftDetector(             mask.isSet(G4PARTICLE_SIM_LEFT_DETECTOR) );
+	  q->setStopped(                     mask.isSet(G4PARTICLE_SIM_STOPPED) );
+	  q->setOverlay(                     false );
+
+	  q->setSpin(p->spin);
+	  q->setColorFlow(p->colorFlow);
+
+	  lc_coll->addElement(q);
+	  p_ids[id] = cnt;
+	  p_part[cnt] = p;
+	  p_lcio[cnt] = q;
+	}
+
+	// Now establish parent-daughter relationships
+	for(size_t i=0, n=p_ids.size(); i<n; ++i)   {
+	  map<int,int>::iterator k;
+	  const Particle* p = p_part[i];
+	  MYParticleImpl* q = p_lcio[i];
+	  const Particle::Particles& dau = p->daughters;
+	  for(Particle::Particles::const_iterator j=dau.begin(); j!=dau.end(); ++j)  {
+	    int idau = *j;
+	    if ( (k=p_ids.find(idau)) == p_ids.end() )  {  // Error!!!
+	      printout(FATAL,"Geant4Conversion","+++ Particle %d: FAILED to find daughter with ID:%d",p->id,idau);
+	      continue;
+	    }
+	    int iqdau = (*k).second;
+	    MYParticleImpl* qdau = p_lcio[iqdau];
+	    qdau->addParent(q);
+	  }
+	  const Particle::Particles& par = p->parents;
+	  for(Particle::Particles::const_iterator j=par.begin(); j!=par.end(); ++j)  {
+	    int ipar = *j; // A parent ID iof -1 means NO parent, because a base of 0 is perfectly leagal!
+	    if ( ipar>=0 && (k=p_ids.find(ipar)) == p_ids.end() )  {  // Error!!!
+	      printout(FATAL,"Geant4Conversion","+++ Particle %d: FAILED to find parent with ID:%d",p->id,ipar);
+	      continue;
+	    }
+	    int iqpar = (*k).second;
+	    MYParticleImpl* qpar = p_lcio[iqpar];
+	    q->addParent(qpar);
+	  }
+	}
+      }
+      return lc_coll;
+    }
+
+    typedef pair<const Geant4Context*,const Geant4ParticleMap*> CONVERSION_ARGS;
+    template class Geant4Conversion<lcio::LCCollectionVec,CONVERSION_ARGS>;
+    DECLARE_GEANT4_HITCONVERTER(lcio::LCCollectionVec,CONVERSION_ARGS,Geant4ParticleMap)
+  }    // End namespace Simulation
+}      // End namespace DD4hep
+
+
+
diff --git a/DDG4/lcio/LcioStdHepReader.cpp b/DDG4/lcio/LCIOStdHepReader.cpp
similarity index 62%
rename from DDG4/lcio/LcioStdHepReader.cpp
rename to DDG4/lcio/LCIOStdHepReader.cpp
index 0bf0b6b31..8da479885 100644
--- a/DDG4/lcio/LcioStdHepReader.cpp
+++ b/DDG4/lcio/LCIOStdHepReader.cpp
@@ -6,18 +6,18 @@
 //====================================================================
 
 // Framework include files
-#include "EventReader.h"
+#include "LCIOEventReader.h"
 
 /*
  *   DD4hep namespace declaration
  */
 namespace DD4hep   {
   /*
-   *   lcio namespace declaration
+   *   Simulation namespace declaration
    */
-  namespace lcio {
+  namespace Simulation {
 
-    /** @class StdHepReader StdHepReader.h DDG4/StdHepReader.h
+    /** @class LCIOStdHepReader LCIOStdHepReader.h DDG4/LCIOStdHepReader.h
      * 
      * Base class to read StdHep files with lcio
      *
@@ -25,17 +25,17 @@ namespace DD4hep   {
      * @author  M.Frank  (code reshuffeling into new DDG4 scheme)
      * @version 1.0
      */
-    struct StdHepReader : public EventReader  {
+    struct LCIOStdHepReader : public LCIOEventReader  {
     protected:
-      /// Reference to reader object
+      /// Reference to Reader object
       UTIL::LCStdHepRdr* m_reader;
     public:
       /// Initializing constructor
-      StdHepReader(const std::string& nam, int);
+      LCIOStdHepReader(const std::string& nam, int);
       /// Default destructor
-      virtual ~StdHepReader();
+      virtual ~LCIOStdHepReader();
       /// Read an event and return a LCCollectionVec of MCParticles.
-      virtual Particles *readEvent();
+      virtual EVENT::LCCollection *readParticles();
     };
   }     /* End namespace lcio   */
 }       /* End namespace DD4hep */
@@ -44,25 +44,26 @@ namespace DD4hep   {
 #include "lcio.h"
 #include "EVENT/LCIO.h"
 #include "UTIL/LCStdHepRdr.h"
+#include "DD4hep/Primitives.h"
+
+using namespace DD4hep::Simulation;
 
 // Factory entry
-typedef DD4hep::lcio::StdHepReader LcioStdHepReader;
-DECLARE_LCIO_EVENT_READER(LcioStdHepReader)
+DECLARE_LCIO_EVENT_READER(LCIOStdHepReader)
 
 /// Initializing constructor
-DD4hep::lcio::StdHepReader::StdHepReader(const std::string& nam, int) 
-  : EventReader(nam)
+LCIOStdHepReader::LCIOStdHepReader(const std::string& nam, int) 
+  : LCIOEventReader(nam)
 {
   m_reader = new ::lcio::LCStdHepRdr(m_name.c_str());
 }
 
 /// Default destructor
-DD4hep::lcio::StdHepReader::~StdHepReader()    {
-  deletePtr(m_reader);
+LCIOStdHepReader::~LCIOStdHepReader()    {
+  DD4hep::deletePtr(m_reader);
 }
 
 /// Read an event and return a LCCollectionVec of MCParticles.
-DD4hep::lcio::EventReader::Particles *DD4hep::lcio::StdHepReader::readEvent()   {
+EVENT::LCCollection *LCIOStdHepReader::readParticles()   {
   return m_reader->readEvent();
 }
-
diff --git a/DDG4/plugins/Geant4EscapeCounter.cpp b/DDG4/plugins/Geant4EscapeCounter.cpp
index 4b9a46ee3..a520ebd59 100644
--- a/DDG4/plugins/Geant4EscapeCounter.cpp
+++ b/DDG4/plugins/Geant4EscapeCounter.cpp
@@ -111,8 +111,9 @@ bool Geant4EscapeCounter::process(G4Step* step, G4TouchableHistory* /* history *
   coll->add(hit);
   mark(h.track);
  
-  print(name(),"+++ Track:%4d  %8.2f MeV [%s] %s Geant4 path:%s",
-	h.trkID(),h.trkEnergy()/MeV,th.name().c_str(),th.creatorName().c_str(),path.c_str());
+  print("+++ Track:%4d  %8.2f MeV [%s] %s Geant4 path:%s",
+	h.trkID(),h.trkEnergy()/MeV,th.name().c_str(),
+	th.creatorName().c_str(),path.c_str());
   // Kill track, so that it does no longer participate in the propagation
   h.track->SetTrackStatus(fStopAndKill);
   return true;
diff --git a/DDG4/plugins/Geant4Factories.cpp b/DDG4/plugins/Geant4Factories.cpp
index f517b8ea5..e4cfc7fa9 100644
--- a/DDG4/plugins/Geant4Factories.cpp
+++ b/DDG4/plugins/Geant4Factories.cpp
@@ -68,6 +68,28 @@ DECLARE_GEANT4ACTION(Geant4Output2ROOT)
 DECLARE_GEANT4ACTION(Geant4ParticleGun)
 
 //=============================
+#include "DDG4/Geant4GeneratorActionInit.h"
+DECLARE_GEANT4ACTION(Geant4GeneratorActionInit)
+
+//=============================
+#include "DDG4/Geant4IsotropeGenerator.h"
+DECLARE_GEANT4ACTION(Geant4IsotropeGenerator)
+
+//=============================
+#include "DDG4/Geant4InteractionVertexSmear.h"
+DECLARE_GEANT4ACTION(Geant4InteractionVertexSmear)
+
+//=============================
+#include "DDG4/Geant4InteractionVertexBoost.h"
+DECLARE_GEANT4ACTION(Geant4InteractionVertexBoost)
+
+//=============================
+#include "DDG4/Geant4InteractionMerger.h"
+DECLARE_GEANT4ACTION(Geant4InteractionMerger)
+
+//=============================
+#include "DDG4/Geant4PrimaryHandler.h"
+DECLARE_GEANT4ACTION(Geant4PrimaryHandler)
 
 //=============================
 #include "DDG4/Geant4TestActions.h"
diff --git a/DDG4/python/DDG4Dict.C b/DDG4/python/DDG4Dict.C
index 70ede136d..245d85783 100644
--- a/DDG4/python/DDG4Dict.C
+++ b/DDG4/python/DDG4Dict.C
@@ -10,6 +10,7 @@
 //
 //====================================================================
 // FRamework include files
+#include "DDG4/Geant4Particle.h"
 #include "DDG4/Geant4Data.h"
 #include <vector>
 
@@ -26,8 +27,12 @@ using namespace DD4hep::Simulation;
 #pragma link C++ class SimpleEvent+;
 //#pragma link C++ class SimpleEvent::Seeds+;
 #pragma link C++ class DataExtension+;
+#pragma link C++ class ParticleExtension+;
+#pragma link C++ class auto_ptr<DataExtension>+;
+#pragma link C++ class auto_ptr<ParticleExtension>+;
+
 #pragma link C++ class SimpleHit+;
-#pragma link C++ class Particle+;
+#pragma link C++ class Geant4Particle+;
 #pragma link C++ class std::vector<SimpleHit*>+;
 #pragma link C++ class SimpleHit::Contribution+;
 #pragma link C++ class SimpleHit::Contributions+;
@@ -37,7 +42,7 @@ using namespace DD4hep::Simulation;
 #pragma link C++ class SimpleCalorimeter+;
 #pragma link C++ class SimpleCalorimeter::Hit+;
 #pragma link C++ class std::vector<SimpleCalorimeter::Hit*>+;
-#pragma link C++ class std::vector<Particle*>+;
+#pragma link C++ class std::vector<Geant4Particle*>+;
 
 //#pragma link C++ class ;
 #endif
@@ -218,6 +223,7 @@ typedef DD4hep::Simulation::Geant4ActionCreation Geant4ActionCreation;
 #pragma link C++ class Geant4ActionCreation;
 #pragma link C++ class Geant4Action;
 #pragma link C++ class Geant4Kernel;
+#pragma link C++ class Geant4Kernel::PhaseSelector;
 #pragma link C++ class Geant4Context;
 #pragma link C++ class KernelHandle;
 
@@ -249,6 +255,7 @@ typedef DD4hep::Simulation::Geant4ActionCreation Geant4ActionCreation;
 #pragma link C++ class Geant4Sensitive;
 #pragma link C++ class Geant4SensDetActionSequence;
 #pragma link C++ class Geant4ActionPhase;
+
 #endif
 
 int Geant4Dict()  {
diff --git a/DDG4/src/Geant4Action.cpp b/DDG4/src/Geant4Action.cpp
index 5897c58fb..f98389b19 100644
--- a/DDG4/src/Geant4Action.cpp
+++ b/DDG4/src/Geant4Action.cpp
@@ -21,7 +21,7 @@ using namespace std;
 using namespace DD4hep;
 using namespace DD4hep::Simulation;
 
-TypeName TypeName::split(const string& type_name, const std::string& delim) {
+TypeName TypeName::split(const string& type_name, const string& delim) {
   size_t idx = type_name.find(delim);
   string typ = type_name, nam = type_name;
   if (idx != string::npos) {
@@ -75,10 +75,8 @@ long Geant4Action::addRef() {
 long Geant4Action::release() {
   long count = --m_refCount;
   if (m_refCount <= 0) {
-    cout << "Geant4Action: Deleting object " << name() 
-	 << " of type " << typeName(typeid(*this)) 
-	 << " Ptr:" << (void*)this
-	 << endl;
+    print("Geant4Action: Deleting object %s of type %s Pointer:%p",
+	  m_name.c_str(),typeName(typeid(*this)).c_str(),(void*)this);
     delete this;
   }
   return count;
@@ -98,12 +96,12 @@ Geant4Action& Geant4Action::setProperties(PropertyConfigurator& setup) {
 }
 
 /// Check property for existence
-bool Geant4Action::hasProperty(const std::string& name) const    {
+bool Geant4Action::hasProperty(const string& name) const    {
   return m_properties.exists(name);
 }
 
 /// Access single property
-Property& Geant4Action::property(const std::string& name)   {
+Property& Geant4Action::property(const string& name)   {
   return properties()[name];
 }
 
@@ -144,91 +142,94 @@ void Geant4Action::enableUI()   {
 }
 
 /// Support for messages with variable output level using output level
-void Geant4Action::print(const std::string& fmt, ...) const   {
-  if ( outputLevel() >= printLevel() )  {
+void Geant4Action::print(const char* fmt, ...) const   {
+  int level = outputLevel();
+  if ( level >= printLevel() )  {
     va_list args;
     va_start(args, fmt);
-    DD4hep::printout((PrintLevel)outputLevel(),m_name, fmt, args);
+    DD4hep::printout((PrintLevel)level, m_name.c_str(), fmt, args);
     va_end(args);
   }
 }
 
-/// Support for messages with variable output level using output level
-void Geant4Action::print(const std::string& tag, const std::string& fmt, ...) const  {
-  if ( outputLevel() >= printLevel() )  {
+/// Support for messages with variable output level using output level-1
+void Geant4Action::printM1(const char* fmt, ...) const   {
+  int level = max(outputLevel()-1,(int)VERBOSE);
+  if ( level >= printLevel() )  {
     va_list args;
     va_start(args, fmt);
-    DD4hep::printout((PrintLevel)outputLevel(),tag, fmt, args);
+    DD4hep::printout((PrintLevel)level, m_name.c_str(), fmt, args);
     va_end(args);
   }
 }
 
-/// Support of debug messages.
-void Geant4Action::debug(const string& fmt, ...) const {
-  va_list args;
-  va_start(args, fmt);
-  DD4hep::printout(DD4hep::DEBUG, "Geant4Action", fmt, args);
-  va_end(args);
+/// Support for messages with variable output level using output level-2
+void Geant4Action::printM2(const char* fmt, ...) const   {
+  int level = max(outputLevel()-2,(int)VERBOSE);
+  if ( level >= printLevel() )  {
+    va_list args;
+    va_start(args, fmt);
+    DD4hep::printout((PrintLevel)level, m_name.c_str(), fmt, args);
+    va_end(args);
+  }
 }
 
-/// Support for messages with variable output level using output level
-void Geant4Action::debug(const std::string& tag, const std::string& fmt, ...) const  {
-  va_list args;
-  va_start(args, fmt);
-  DD4hep::printout(DD4hep::DEBUG, tag, fmt, args);
-  va_end(args);
+/// Support for messages with variable output level using output level-1
+void Geant4Action::printP1(const char* fmt, ...) const   {
+  int level = min(outputLevel()+1,(int)FATAL);
+  if ( level >= printLevel() )  {
+    va_list args;
+    va_start(args, fmt);
+    DD4hep::printout((PrintLevel)level, m_name.c_str(), fmt, args);
+    va_end(args);
+  }
 }
 
-/// Support of info messages.
-void Geant4Action::info(const string& fmt, ...) const {
-  va_list args;
-  va_start(args, fmt);
-  DD4hep::printout(DD4hep::INFO, "Geant4Action", fmt, args);
-  va_end(args);
+/// Support for messages with variable output level using output level-2
+void Geant4Action::printP2(const char* fmt, ...) const   {
+  int level = min(outputLevel()+2,(int)FATAL);
+  if ( level >= printLevel() )  {
+    va_list args;
+    va_start(args, fmt);
+    DD4hep::printout((PrintLevel)level, m_name.c_str(), fmt, args);
+    va_end(args);
+  }
 }
 
-/// Support for messages with variable output level using output level
-void Geant4Action::info(const std::string& tag, const std::string& fmt, ...) const  {
+/// Support of debug messages.
+void Geant4Action::debug(const char* fmt, ...) const {
   va_list args;
   va_start(args, fmt);
-  DD4hep::printout(DD4hep::INFO, tag, fmt, args);
+  DD4hep::printout(DD4hep::DEBUG, "Geant4Action", fmt, args);
   va_end(args);
 }
 
-/// Support of warning messages.
-void Geant4Action::warning(const string& fmt, ...) const {
+/// Support of info messages.
+void Geant4Action::info(const char* fmt, ...) const {
   va_list args;
   va_start(args, fmt);
-  DD4hep::printout(DD4hep::WARNING, "Geant4Action", fmt, args);
+  DD4hep::printout(DD4hep::INFO, "Geant4Action", fmt, args);
   va_end(args);
 }
 
-/// Support for messages with variable output level using output level
-void Geant4Action::warning(const std::string& tag, const std::string& fmt, ...) const  {
+/// Support of warning messages.
+void Geant4Action::warning(const char* fmt, ...) const {
   va_list args;
   va_start(args, fmt);
-  DD4hep::printout(DD4hep::WARNING, tag, fmt, args);
+  DD4hep::printout(DD4hep::WARNING, "Geant4Action", fmt, args);
   va_end(args);
 }
 
 /// Action to support error messages.
-void Geant4Action::error(const string& fmt, ...) const {
+void Geant4Action::error(const char* fmt, ...) const {
   va_list args;
   va_start(args, fmt);
   DD4hep::printout(DD4hep::ERROR, "Geant4Action", fmt, args);
   va_end(args);
 }
 
-/// Support for messages with variable output level using output level
-void Geant4Action::error(const std::string& tag, const std::string& fmt, ...) const  {
-  va_list args;
-  va_start(args, fmt);
-  DD4hep::printout(DD4hep::ERROR, tag, fmt, args);
-  va_end(args);
-}
-
 /// Action to support error messages.
-bool Geant4Action::error(bool return_value, const string& fmt, ...) const {
+bool Geant4Action::error(bool return_value, const char* fmt, ...) const {
   va_list args;
   va_start(args, fmt);
   DD4hep::printout(DD4hep::ERROR, "Geant4Action", fmt, args);
@@ -237,7 +238,7 @@ bool Geant4Action::error(bool return_value, const string& fmt, ...) const {
 }
 
 /// Support of fatal messages. Throws exception if required.
-void Geant4Action::fatal(const string& fmt, ...) const {
+void Geant4Action::fatal(const char* fmt, ...) const {
   string err;
   va_list args;
   va_start(args, fmt);
@@ -245,16 +246,8 @@ void Geant4Action::fatal(const string& fmt, ...) const {
   va_end(args);
 }
 
-/// Support for messages with variable output level using output level
-void Geant4Action::fatal(const std::string& tag, const std::string& fmt, ...) const  {
-  va_list args;
-  va_start(args, fmt);
-  DD4hep::printout(DD4hep::FATAL, tag, fmt, args);
-  va_end(args);
-}
-
 /// Support of exceptions: Print fatal message and throw runtime_error.
-void Geant4Action::except(const string& fmt, ...) const {
+void Geant4Action::except(const char* fmt, ...) const {
   string err;
   va_list args;
   va_start(args, fmt);
@@ -264,16 +257,8 @@ void Geant4Action::except(const string& fmt, ...) const {
   throw runtime_error(err);
 }
 
-/// Support for messages with variable output level using output level
-void Geant4Action::except(const std::string& tag, const std::string& fmt, ...) const  {
-  va_list args;
-  va_start(args, fmt);
-  DD4hep::printout(DD4hep::FATAL, tag, fmt, args);
-  va_end(args);
-}
-
 /// Abort Geant4 Run by throwing a G4Exception with type RunMustBeAborted
-void Geant4Action::abortRun(const string& exception, const string& fmt, ...) const {
+void Geant4Action::abortRun(const string& exception, const char* fmt, ...) const {
   string desc, typ = typeName(typeid(*this));
   string issuer = name()+" ["+typ+"]";
   va_list args;
diff --git a/DDG4/src/Geant4Context.cpp b/DDG4/src/Geant4Context.cpp
index a31d4b3ab..a3dc1a652 100644
--- a/DDG4/src/Geant4Context.cpp
+++ b/DDG4/src/Geant4Context.cpp
@@ -29,8 +29,8 @@ Geant4Run::~Geant4Run()   {
 }
 
 /// Intializing constructor
-Geant4Event::Geant4Event(const G4Event* evt) 
-: ObjectExtensions(typeid(Geant4Event)), m_event(evt)  
+Geant4Event::Geant4Event(const G4Event* evt, Geant4Random* rnd) 
+  : ObjectExtensions(typeid(Geant4Event)), m_event(evt), m_random(rnd)
 {
   InstanceCount::increment(this);
 }
diff --git a/DDG4/src/Geant4Data.cpp b/DDG4/src/Geant4Data.cpp
index 0b1c79506..79f54cd37 100644
--- a/DDG4/src/Geant4Data.cpp
+++ b/DDG4/src/Geant4Data.cpp
@@ -8,10 +8,12 @@
 //====================================================================
 
 // Framework include files
+#include "DD4hep/Printout.h"
 #include "DD4hep/InstanceCount.h"
 #include "DDG4/Geant4Data.h"
 
 // Geant4 include files
+#include "G4Step.hh"
 #include "G4Allocator.hh"
 #include "G4OpticalPhoton.hh"
 
@@ -45,92 +47,19 @@ SimpleEvent::~SimpleEvent() {
 DataExtension::~DataExtension() {
 }
 
-/// Copy constructor
-Particle::Particle(const Particle& c)
-  : id(c.id), g4Parent(c.g4Parent), parent(c.parent), reason(c.reason), 
-    steps(c.steps), secondaries(c.secondaries), pdgID(c.pdgID),
-    vsx(c.vsx), vsy(c.vsy), vsz(c.vsz), 
-    vex(c.vex), vey(c.vey), vez(c.vez), 
-    psx(c.psx), psy(c.psy), psz(c.psz), 
-    pex(c.pex), pey(c.pey), pez(c.pez), 
-    energy(c.energy), time(c.time),
-    daughters(c.daughters), extension(),
-    process(c.process), definition(c.definition)
-{
-  InstanceCount::increment(this);
-}
-
-/// Default constructor
-Particle::Particle()
-  : id(0), g4Parent(0), parent(0), reason(0), 
-    steps(0), secondaries(0), pdgID(0),
-    vsx(0.0), vsy(0.0), vsz(0.0), 
-    vex(0.0), vey(0.0), vez(0.0), 
-    psx(0.0), psy(0.0), psz(0.0), 
-    pex(0.0), pey(0.0), pez(0.0), 
-    energy(0.0), time(0.0),
-    daughters(), extension(), process(0), definition(0)
-{
-  InstanceCount::increment(this);
-}
-
-/// Default destructor
-Particle::~Particle()  {
-  InstanceCount::decrement(this);
-}
-
-/// Assignment operator
-Particle& Particle::get_data(Particle& c)   {
-  if ( this != &c )  {
-    id = c.id; 
-    g4Parent = c.g4Parent;
-    parent = c.parent;
-    reason = c.reason; 
-    steps = c.steps; 
-    secondaries = c.secondaries;
-    pdgID = c.pdgID;
-    vsx = c.vsx;
-    vsy = c.vsy;
-    vsz = c.vsz; 
-    vex = c.vex;
-    vey = c.vey;
-    vez = c.vez; 
-    psx = c.psx;
-    psy = c.psy;
-    psz = c.psz; 
-    pex = c.pex;
-    pey = c.pey;
-    pez = c.pez; 
-    energy = c.energy;
-    time = c.time;
-    process = c.process; 
-    definition = c.definition;
-    daughters = c.daughters;
-    extension = c.extension;
-    //auto_ptr<DataExtension>(c.extension.release());
-  }
-  return *this;
-}
-
-/// Remove daughter from set
-void Particle::removeDaughter(int id_daughter)  {
-  set<int>::iterator j = daughters.find(id_daughter);
-  if ( j != daughters.end() ) daughters.erase(j);
-}
-
 /// Default constructor
-SimpleHit::SimpleHit()
+Geant4HitData::Geant4HitData()
     : cellID(0), extension() {
   InstanceCount::increment(this);
 }
 
 /// Default destructor
-SimpleHit::~SimpleHit() {
+Geant4HitData::~Geant4HitData() {
   InstanceCount::decrement(this);
 }
 
 /// Extract the MC contribution for a given hit from the step information
-SimpleHit::Contribution SimpleHit::extractContribution(G4Step* step) {
+Geant4HitData::Contribution Geant4HitData::extractContribution(G4Step* step) {
   G4Track* trk = step->GetTrack();
   double energy_deposit =
       (trk->GetDefinition() == G4OpticalPhoton::OpticalPhotonDefinition()) ?
@@ -140,24 +69,24 @@ SimpleHit::Contribution SimpleHit::extractContribution(G4Step* step) {
 }
 
 /// Default constructor
-SimpleTracker::Hit::Hit()
-  : SimpleHit(), position(), momentum(), length(0.0), truth(), energyDeposit(0.0) {
+Geant4Tracker::Hit::Hit()
+  : Geant4HitData(), position(), momentum(), length(0.0), truth(), energyDeposit(0.0) {
   InstanceCount::increment(this);
 }
 
 /// Standard initializing constructor
-SimpleTracker::Hit::Hit(int track_id, int pdg_id, double deposit, double time_stamp)
-  : SimpleHit(), position(), momentum(), length(0.0), truth(track_id, pdg_id, deposit, time_stamp), energyDeposit(deposit) {
+Geant4Tracker::Hit::Hit(int track_id, int pdg_id, double deposit, double time_stamp)
+  : Geant4HitData(), position(), momentum(), length(0.0), truth(track_id, pdg_id, deposit, time_stamp), energyDeposit(deposit) {
   InstanceCount::increment(this);
 }
 
 /// Default destructor
-SimpleTracker::Hit::~Hit() {
+Geant4Tracker::Hit::~Hit() {
   InstanceCount::decrement(this);
 }
 
 /// Assignment operator
-SimpleTracker::Hit& SimpleTracker::Hit::operator=(const Hit& c) {
+Geant4Tracker::Hit& Geant4Tracker::Hit::operator=(const Hit& c) {
   if ( &c != this )  {
     position = c.position;
     momentum = c.momentum;
@@ -168,7 +97,7 @@ SimpleTracker::Hit& SimpleTracker::Hit::operator=(const Hit& c) {
 }
 
 /// Clear hit content
-SimpleTracker::Hit& SimpleTracker::Hit::clear() {
+Geant4Tracker::Hit& Geant4Tracker::Hit::clear() {
   position.SetXYZ(0, 0, 0);
   momentum.SetXYZ(0, 0, 0);
   length = 0.0;
@@ -177,7 +106,7 @@ SimpleTracker::Hit& SimpleTracker::Hit::clear() {
 }
 
 /// Store Geant4 point and step information into tracker hit structure.
-SimpleTracker::Hit& SimpleTracker::Hit::storePoint(G4Step* step, G4StepPoint* pnt) {
+Geant4Tracker::Hit& Geant4Tracker::Hit::storePoint(G4Step* step, G4StepPoint* pnt) {
   G4Track* trk = step->GetTrack();
   G4ThreeVector pos = pnt->GetPosition();
   G4ThreeVector mom = pnt->GetMomentum();
@@ -193,18 +122,18 @@ SimpleTracker::Hit& SimpleTracker::Hit::storePoint(G4Step* step, G4StepPoint* pn
 }
 
 /// Default constructor (for ROOT)
-SimpleCalorimeter::Hit::Hit()
-    : SimpleHit(), position(), truth(), energyDeposit(0) {
+Geant4Calorimeter::Hit::Hit()
+    : Geant4HitData(), position(), truth(), energyDeposit(0) {
   InstanceCount::increment(this);
 }
 
 /// Standard constructor
-SimpleCalorimeter::Hit::Hit(const Position& pos)
-    : SimpleHit(), position(pos), truth(), energyDeposit(0) {
+Geant4Calorimeter::Hit::Hit(const Position& pos)
+    : Geant4HitData(), position(pos), truth(), energyDeposit(0) {
   InstanceCount::increment(this);
 }
 
 /// Default destructor
-SimpleCalorimeter::Hit::~Hit() {
+Geant4Calorimeter::Hit::~Hit() {
   InstanceCount::decrement(this);
 }
diff --git a/DDG4/src/Geant4DataConversion.cpp b/DDG4/src/Geant4DataConversion.cpp
index 99e68301c..0ca9c6a04 100644
--- a/DDG4/src/Geant4DataConversion.cpp
+++ b/DDG4/src/Geant4DataConversion.cpp
@@ -20,9 +20,21 @@ Geant4ConversionHelper::Geant4ConversionHelper() {
 Geant4ConversionHelper::~Geant4ConversionHelper() {
 }
 
+/// Access to the data encoding using the volume manager and a specified volume id
 std::string Geant4ConversionHelper::encoding(Geometry::VolumeManager vm, Geometry::VolumeManager::VolumeID vid) {
   Geometry::PlacedVolume pv = vm.lookupPlacement(vid);
   Geometry::SensitiveDetector sd = pv.volume().sensitiveDetector();
-  Geometry::IDDescriptor id = sd.readout().idSpec();
+  return encoding(sd);
+}
+
+/// Access to the hit encoding in this sensitive detector
+std::string Geant4ConversionHelper::encoding(Geometry::Handle<Geometry::SensitiveDetectorObject> sd)   {
+  Geometry::IDDescriptor id = Geometry::SensitiveDetector(sd).readout().idSpec();
+  return id.fieldDescription();
+}
+
+/// Access to the hit encoding in this readout object
+std::string Geant4ConversionHelper::encoding(Geometry::Readout ro)   {
+  Geometry::IDDescriptor id = ro.idSpec();
   return id.fieldDescription();
 }
diff --git a/DDG4/src/Geant4DataDump.cpp b/DDG4/src/Geant4DataDump.cpp
index 176dcdae3..ad55dfd1c 100644
--- a/DDG4/src/Geant4DataDump.cpp
+++ b/DDG4/src/Geant4DataDump.cpp
@@ -26,17 +26,18 @@ Geant4DataDump::~Geant4DataDump()  {
 }
 
 /// Print a single particle to the output logging using the specified print level
-void Geant4DataDump::print(PrintLevel level, const Particle* p)  const  {
+void Geant4DataDump::print(PrintLevel level, Geant4ParticleHandle p)  const  {
   PropertyMask mask(p->reason);
+  int parent = p->parents.empty() ? -1 : *p->parents.begin();
   printout(level, m_tag, "   +++ TrackID: %6d %12d %6d %-7s %3s %5d %6s %8.3g %-4s %-7s %-7s %-3s",
 	   p->id,
 	   p->pdgID,
-	   p->parent,
+	   parent,
 	   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,
+	   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)),
diff --git a/DDG4/src/Geant4Exec.cpp b/DDG4/src/Geant4Exec.cpp
index a37dbfa2b..d3d160a48 100644
--- a/DDG4/src/Geant4Exec.cpp
+++ b/DDG4/src/Geant4Exec.cpp
@@ -28,8 +28,9 @@
 #include "DDG4/Geant4StackingAction.h"
 #include "DDG4/Geant4GeneratorAction.h"
 #include "DDG4/Geant4PhysicsList.h"
-#include "DDG4/Geant4Kernel.h"
 #include "DDG4/Geant4UIManager.h"
+#include "DDG4/Geant4Kernel.h"
+#include "DDG4/Geant4Random.h"
 
 #include <memory>
 #include <stdexcept>
@@ -46,6 +47,7 @@ namespace DD4hep {
 
     namespace {
       Geant4Context* s_globalContext = 0;
+      Geant4Random*  s_globalRandom = 0;
     }
 
     Geant4Context* ddg4_globalContext()   {
@@ -98,7 +100,7 @@ namespace DD4hep {
 	}
       }
       void createClientContext(const G4Event* evt)   {
-	Geant4Event* e = new Geant4Event(evt);
+	Geant4Event* e = new Geant4Event(evt,s_globalRandom);
 	m_activeContext->setEvent(e);
 	setContextToClients();
       }
@@ -291,6 +293,8 @@ int Geant4Exec::configure(Geant4Kernel& kernel) {
   CLHEP::HepRandom::setTheEngine(new CLHEP::RanecuEngine);
   Geometry::LCDD& lcdd = kernel.lcdd();
   Geant4Context* ctx = s_globalContext = new Geant4Context(&kernel);
+  // For now do this:
+  /* Geant4Random* rnd = */ s_globalRandom = new Geant4Random();
 
   // Construct the default run manager
   G4RunManager& runManager = kernel.runManager();
diff --git a/DDG4/src/Geant4GeneratorActionInit.cpp b/DDG4/src/Geant4GeneratorActionInit.cpp
new file mode 100644
index 000000000..cb3560d83
--- /dev/null
+++ b/DDG4/src/Geant4GeneratorActionInit.cpp
@@ -0,0 +1,81 @@
+// $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 "DD4hep/Printout.h"
+#include "DD4hep/InstanceCount.h"
+#include "DDG4/Geant4Kernel.h"
+#include "DDG4/Geant4Primary.h"
+#include "DDG4/Geant4RunAction.h"
+#include "DDG4/Geant4GeneratorActionInit.h"
+
+#include "G4Run.hh"
+
+using namespace DD4hep::Simulation;
+
+/// Standard constructor
+Geant4GeneratorActionInit::Geant4GeneratorActionInit(Geant4Context* context, const std::string& nam)
+  : Geant4GeneratorAction(context,nam), m_run(0), m_evtTotal(0), m_evtRun(0)
+{
+  InstanceCount::increment(this);
+  context->kernel().runAction().callAtEnd(this,&Geant4GeneratorActionInit::end);
+  context->kernel().runAction().callAtBegin(this,&Geant4GeneratorActionInit::begin);
+}
+
+/// Default destructor
+Geant4GeneratorActionInit::~Geant4GeneratorActionInit()  {
+  InstanceCount::decrement(this);
+}
+
+/// Begin-run action callback
+void Geant4GeneratorActionInit::begin(const G4Run* run)   {
+  m_evtRun = 0;
+  m_run = run->GetRunID();
+}
+
+/// End-run action callback
+void Geant4GeneratorActionInit::end(const G4Run* /* run */)   {
+  printP1("+++ Funished run %d after %d events (% events in total)",m_run,m_evtRun,m_evtTotal);
+  m_evtRun = 0;
+  m_run = 0;
+}
+
+/// Event generation action callback
+void Geant4GeneratorActionInit::operator()(G4Event* /* event */)  {
+  /// Update event counters
+  ++m_evtTotal;
+  ++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);
+}
diff --git a/DDG4/src/Geant4HitCollection.cpp b/DDG4/src/Geant4HitCollection.cpp
index b1a1b4604..b8e110c07 100644
--- a/DDG4/src/Geant4HitCollection.cpp
+++ b/DDG4/src/Geant4HitCollection.cpp
@@ -75,6 +75,16 @@ Geant4HitCollection::~Geant4HitCollection() {
   InstanceCount::decrement(this);
 }
 
+/// Set the sensitive detector
+void Geant4HitCollection::setSensitiveDetector(SensitiveDetector detector)   {
+  m_detector = detector;
+}
+
+/// Access the sensitive detector
+Geant4HitCollection::SensitiveDetector Geant4HitCollection::sensitiveDetector() const  {
+  return m_detector;
+}
+
 /// Type information of the object stored
 const ComponentCast& Geant4HitCollection::type() const {
   return m_manipulator->cast;
diff --git a/DDG4/src/Geant4InteractionMerger.cpp b/DDG4/src/Geant4InteractionMerger.cpp
new file mode 100644
index 000000000..e8b4489ae
--- /dev/null
+++ b/DDG4/src/Geant4InteractionMerger.cpp
@@ -0,0 +1,93 @@
+// $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 "DD4hep/Printout.h"
+#include "DD4hep/InstanceCount.h"
+#include "DDG4/Geant4Primary.h"
+#include "DDG4/Geant4InteractionMerger.h"
+
+#include <stdexcept>
+
+using namespace std;
+using namespace DD4hep;
+using namespace DD4hep::Simulation;
+
+/// Standard constructor
+Geant4InteractionMerger::Geant4InteractionMerger(Geant4Context* context, const std::string& nam)
+  : Geant4GeneratorAction(context,nam)
+{
+  InstanceCount::increment(this);
+}
+
+/// Default destructor
+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);
+  }
+}
+
+void 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 iv, ivend;
+  for( iv=input->vertices.begin(), ivend=input->vertices.end(); iv != ivend; ++iv )
+    output->vertices.insert(make_pair(output->vertices.size(),(*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, vertex_offset = 0;
+
+  for(Interactions::const_iterator i=inter.begin(); i != inter.end(); ++i)  {
+    Interaction* interaction = *i;
+    vertex_offset = particle_offset;
+    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");
+}
diff --git a/DDG4/src/Geant4InteractionVertexBoost.cpp b/DDG4/src/Geant4InteractionVertexBoost.cpp
new file mode 100644
index 000000000..d9b889cd1
--- /dev/null
+++ b/DDG4/src/Geant4InteractionVertexBoost.cpp
@@ -0,0 +1,99 @@
+// $Id: Geant4Converter.cpp 603 2013-06-13 21:15:14Z markus.frank $
+//====================================================================
+//  AIDA Detector description implementation for LCD
+//--------------------------------------------------------------------
+//
+//  Author     : M.Frank
+//
+//====================================================================
+
+// 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/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)
+  : Geant4GeneratorAction(context, name)
+{
+  InstanceCount::increment(this);
+  declareProperty("Angle", m_angle = 0);
+  declareProperty("Mask",  m_mask = 0);
+  m_needsControl = true;
+}
+
+/// Default destructor
+Geant4InteractionVertexBoost::~Geant4InteractionVertexBoost() {
+  InstanceCount::decrement(this);
+}
+
+/// 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);
+
+  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;
+      }
+    }
+  }
+}
diff --git a/DDG4/src/Geant4InteractionVertexSmear.cpp b/DDG4/src/Geant4InteractionVertexSmear.cpp
new file mode 100644
index 000000000..6a2c562f0
--- /dev/null
+++ b/DDG4/src/Geant4InteractionVertexSmear.cpp
@@ -0,0 +1,84 @@
+// $Id: Geant4Converter.cpp 603 2013-06-13 21:15:14Z markus.frank $
+//====================================================================
+//  AIDA Detector description implementation for LCD
+//--------------------------------------------------------------------
+//
+//  Author     : M.Frank
+//
+//====================================================================
+
+// 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/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)
+  : Geant4GeneratorAction(context, name)
+{
+  InstanceCount::increment(this);
+  declareProperty("Offset", m_offset);
+  declareProperty("Sigma",  m_sigma);
+  declareProperty("Mask",   m_mask = 0);
+  m_needsControl = true;
+}
+
+/// Default destructor
+Geant4InteractionVertexSmear::~Geant4InteractionVertexSmear() {
+  InstanceCount::decrement(this);
+}
+
+/// Callback to generate primary particles
+void Geant4InteractionVertexSmear::operator()(G4Event*) {
+  typedef Geant4PrimaryEvent::Interaction Interaction;
+  typedef Geant4Particle Particle;
+  typedef Geant4Particle Vertex;
+  Geant4Random& rndm = context()->event().random();
+  Geant4PrimaryEvent* evt = context()->event().extension<Geant4PrimaryEvent>();
+  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 by (%+.2e mm, %+.2e mm, %+.2e mm, %+.2e ns)",m_mask,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;
+    }
+  }
+  else  {
+    print("+++ No interaction of type %d present.",m_mask);
+  }
+}
diff --git a/DDG4/src/Geant4IsotropeGenerator.cpp b/DDG4/src/Geant4IsotropeGenerator.cpp
new file mode 100644
index 000000000..bd6d4ef64
--- /dev/null
+++ b/DDG4/src/Geant4IsotropeGenerator.cpp
@@ -0,0 +1,92 @@
+// $Id: Geant4Converter.cpp 603 2013-06-13 21:15:14Z markus.frank $
+//====================================================================
+//  AIDA Detector description implementation for LCD
+//--------------------------------------------------------------------
+//
+//  Author     : M.Frank
+//
+//====================================================================
+
+// 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/Geant4IsotropeGenerator.h"
+#include "CLHEP/Units/SystemOfUnits.h"
+
+#include "G4ParticleTable.hh"
+#include "G4ParticleDefinition.hh"
+
+// C/C++ include files
+#include <stdexcept>
+#include <cmath>
+
+using namespace std;
+using namespace DD4hep::Simulation;
+
+/// Standard constructor
+Geant4IsotropeGenerator::Geant4IsotropeGenerator(Geant4Context* context, const string& name)
+  : Geant4GeneratorAction(context, name), m_particle(0)
+{
+  InstanceCount::increment(this);
+  m_needsControl = true;
+  declareProperty("particle",      m_particleName = "e-");
+  declareProperty("energy",        m_energy = 50 * MeV);
+  declareProperty("multiplicity",  m_multiplicity = 1);
+  declareProperty("mask",          m_mask = 0);
+}
+
+/// Default destructor
+Geant4IsotropeGenerator::~Geant4IsotropeGenerator() {
+  InstanceCount::decrement(this);
+}
+
+/// Callback to generate primary particles
+void Geant4IsotropeGenerator::operator()(G4Event*) {
+  typedef Geant4Particle Particle;
+
+  if (0 == m_particle || m_particle->GetParticleName() != m_particleName.c_str()) {
+    G4ParticleTable* particleTable = G4ParticleTable::GetParticleTable();
+    m_particle = particleTable->FindParticle(m_particleName);
+    if (0 == m_particle) {
+      throw runtime_error("Geant4IsotropeGenerator: Bad particle type:"+m_particleName+"!");
+    }
+  }
+  Geant4Event& evt = context()->event();
+  Geant4Random& rnd = evt.random();
+  Geant4PrimaryEvent* prim = evt.extension<Geant4PrimaryEvent>();
+  Geant4PrimaryInteraction* inter = new Geant4PrimaryInteraction();
+  prim->add(m_mask, inter);
+
+  Geant4Vertex* vtx = new Geant4Vertex();
+  inter->vertices.insert(make_pair(inter->vertices.size(),vtx));
+  for(int i=0; i<m_multiplicity; ++i)   {
+    double phi = 2*M_PI*rnd.rndm();
+    double theta = M_PI*rnd.rndm();
+    double x1 = std::sin(theta)*std::cos(phi);
+    double x2 = std::sin(theta)*std::sin(phi);
+    double x3 = std::cos(theta);
+    double momentum = rnd.rndm()*m_energy;
+
+    Particle* p = new Particle();
+    p->id         = inter->nextPID();
+    p->reason    |= G4PARTICLE_PRIMARY;
+    p->status    |= G4PARTICLE_GEN_CREATED;
+    p->status    |= G4PARTICLE_GEN_STABLE;
+    p->usermask   = m_mask;
+    p->reason     = G4PARTICLE_PRIMARY;
+    p->pdgID      = m_particle->GetPDGEncoding();
+    p->definition = m_particle;
+    p->psx        = x1*momentum;
+    p->psy        = x2*momentum;
+    p->psz        = x3*momentum;
+    p->mass       = m_particle->GetPDGMass();
+    inter->particles.insert(make_pair(p->id,p));
+    vtx->out.insert(p->id);
+    printout(INFO,name(),"Particle [%d] %s %.3f GeV direction:(%6.3f %6.3f %6.3f)",
+	     p->id, m_particleName.c_str(), momentum/GeV, x1, x2, x3);
+
+  }
+}
diff --git a/DDG4/src/Geant4Output2ROOT.cpp b/DDG4/src/Geant4Output2ROOT.cpp
index 118465c28..85a933ad7 100644
--- a/DDG4/src/Geant4Output2ROOT.cpp
+++ b/DDG4/src/Geant4Output2ROOT.cpp
@@ -13,7 +13,7 @@
 #include "DD4hep/InstanceCount.h"
 #include "DDG4/Geant4HitCollection.h"
 #include "DDG4/Geant4Output2ROOT.h"
-#include "DDG4/Geant4MonteCarloTruth.h"
+#include "DDG4/Geant4Particle.h"
 #include "DDG4/Geant4Data.h"
 // Geant4 include files
 #include "G4HCofThisEvent.hh"
@@ -135,12 +135,12 @@ void Geant4Output2ROOT::commit(OutputContext<G4Event>& ctxt) {
 
 /// Callback to store the Geant4 event
 void Geant4Output2ROOT::saveEvent(OutputContext<G4Event>& /* ctxt */) {
-  Geant4MonteCarloTruth* truth = context()->event().extension<Geant4MonteCarloTruth>(false);
-  if ( truth )   {
+  Geant4ParticleMap* parts = context()->event().extension<Geant4ParticleMap>();
+  if ( parts )   {
     typedef Geant4HitWrapper::HitManipulator Manip;
-    typedef Geant4MonteCarloTruth::ParticleMap ParticleMap;
-    Manip* manipulator = Geant4HitWrapper::manipulator<Particle>();
-    const ParticleMap& pm = truth->particles();
+    typedef Geant4ParticleMap::ParticleMap ParticleMap;
+    Manip* manipulator = Geant4HitWrapper::manipulator<Geant4Particle>();
+    const ParticleMap& pm = parts->particles();
     vector<void*> particles;
     for(ParticleMap::const_iterator i=pm.begin(); i!=pm.end(); ++i)    {
       particles.push_back((ParticleMap::mapped_type*)(*i).second);
@@ -157,7 +157,7 @@ void Geant4Output2ROOT::saveCollection(OutputContext<G4Event>& /* ctxt */, G4VHi
   if (coll) {
     coll->getHitsUnchecked(hits);
     size_t nhits = coll->GetSize();
-    Geant4MonteCarloTruth* truth = context()->event().extension<Geant4MonteCarloTruth>(false);
+    Geant4ParticleMap* truth = context()->event().extension<Geant4ParticleMap>();
     if ( truth && nhits > 0 )   {
       try  {
 	for(size_t i=0; i<nhits; ++i)   {
diff --git a/DDG4/src/Geant4Particle.cpp b/DDG4/src/Geant4Particle.cpp
new file mode 100644
index 000000000..bd2953641
--- /dev/null
+++ b/DDG4/src/Geant4Particle.cpp
@@ -0,0 +1,315 @@
+// $Id: Geant4Hits.cpp 513 2013-04-05 14:31:53Z gaede $
+//====================================================================
+//  AIDA Detector description implementation for LCD
+//--------------------------------------------------------------------
+//
+//  Author     : M.Frank
+//
+//====================================================================
+
+// Framework include files
+#include "DD4hep/Printout.h"
+#include "DD4hep/Primitives.h"
+#include "DD4hep/InstanceCount.h"
+#include "DDG4/Geant4Particle.h"
+#include "TDatabasePDG.h"
+#include "TParticlePDG.h"
+#include "G4ParticleTable.hh"
+#include "G4ParticleDefinition.hh"
+#include "G4VProcess.hh"
+
+using namespace DD4hep;
+using namespace DD4hep::Simulation;
+
+/// Default destructor
+ParticleExtension::~ParticleExtension() {
+}
+
+/// Copy constructor
+Geant4Particle::Geant4Particle(const Geant4Particle& c)
+  : ref(1), id(c.id), g4Parent(c.g4Parent), reason(c.reason), usermask(c.usermask),
+    steps(c.steps), secondaries(c.secondaries), pdgID(c.pdgID),
+    status(c.status), charge(0),
+    vsx(c.vsx), vsy(c.vsy), vsz(c.vsz), 
+    vex(c.vex), vey(c.vey), vez(c.vez), 
+    psx(c.psx), psy(c.psy), psz(c.psz), 
+    pex(c.pex), pey(c.pey), pez(c.pez), 
+    mass(c.mass), time(c.time), properTime(c.properTime),
+    parents(c.parents), daughters(c.daughters), extension(),
+    process(c.process), definition(c.definition)
+{
+  InstanceCount::increment(this);
+  spin[0] = c.spin[0];
+  spin[1] = c.spin[1];
+  spin[2] = c.spin[2];
+  colorFlow[0] = c.colorFlow[0];
+  colorFlow[1] = c.colorFlow[1];
+}
+
+/// Default constructor
+Geant4Particle::Geant4Particle()
+  : ref(1), id(0), g4Parent(0), reason(0), usermask(0), 
+    steps(0), secondaries(0), pdgID(0),
+    status(0), charge(0),
+    vsx(0.0), vsy(0.0), vsz(0.0), 
+    vex(0.0), vey(0.0), vez(0.0), 
+    psx(0.0), psy(0.0), psz(0.0), 
+    pex(0.0), pey(0.0), pez(0.0), 
+    mass(0.0), time(0.0), properTime(0.0),
+    daughters(), extension(), process(0), definition(0)
+{
+  InstanceCount::increment(this);
+  spin[0] = spin[1] = spin[2] = 0;
+  colorFlow[0] = colorFlow[1] = 0;
+}
+
+/// Constructor with ID initialization
+Geant4Particle::Geant4Particle(int part_id)
+  : ref(1), id(part_id), g4Parent(0), reason(0), usermask(0), 
+    steps(0), secondaries(0), pdgID(0),
+    status(0), charge(0),
+    vsx(0.0), vsy(0.0), vsz(0.0), 
+    vex(0.0), vey(0.0), vez(0.0), 
+    psx(0.0), psy(0.0), psz(0.0), 
+    pex(0.0), pey(0.0), pez(0.0), 
+    mass(0.0), time(0.0), properTime(0.0),
+    daughters(), extension(), process(0), definition(0)
+{
+  InstanceCount::increment(this);
+  spin[0] = spin[1] = spin[2] = 0;
+  colorFlow[0] = colorFlow[1] = 0;
+}
+
+/// Default destructor
+Geant4Particle::~Geant4Particle()  {
+  InstanceCount::decrement(this);
+  //::printf("************ Delete Geant4Particle[%p]: ID:%d pdgID %d ref:%d\n",(void*)this,id,pdgID,ref);
+}
+
+void Geant4Particle::release()  {
+  //::printf("************ Release Geant4Particle[%p]: ID:%d pdgID %d ref:%d\n",(void*)this,id,pdgID,ref-1);
+  if ( --ref <= 0 )  {
+    delete this;
+  }
+}
+
+/// Assignment operator
+Geant4Particle& Geant4Particle::get_data(Geant4Particle& c)   {
+  if ( this != &c )  {
+    id = c.id; 
+    g4Parent    = c.g4Parent;
+    reason      = c.reason; 
+    usermask    = c.usermask;
+    status      = c.status;
+    charge      = c.charge;
+    steps       = c.steps; 
+    secondaries = c.secondaries;
+    pdgID       = c.pdgID;
+    vsx         = c.vsx;
+    vsy         = c.vsy;
+    vsz         = c.vsz; 
+    vex         = c.vex;
+    vey         = c.vey;
+    vez         = c.vez; 
+    psx         = c.psx;
+    psy         = c.psy;
+    psz         = c.psz; 
+    pex         = c.pex;
+    pey         = c.pey;
+    pez         = c.pez; 
+    mass        = c.mass;
+    time        = c.time;
+    properTime  = c.properTime;
+    process     = c.process; 
+    definition  = c.definition;
+    daughters   = c.daughters;
+    parents     = c.parents;
+    extension   = c.extension;
+    //auto_ptr<ParticleExtension>(c.extension.release());
+  }
+  return *this;
+}
+
+/// Remove daughter from set
+void Geant4Particle::removeDaughter(int id_daughter)  {
+  std::set<int>::iterator j = daughters.find(id_daughter);
+  if ( j != daughters.end() ) daughters.erase(j);
+}
+
+/// Access to the Geant4 particle name
+std::string Geant4ParticleHandle::particleName() const   {
+  if ( particle->definition ) return particle->definition->GetParticleName();
+  G4ParticleTable*      tab = G4ParticleTable::GetParticleTable();
+  G4ParticleDefinition* def = tab->FindParticle(particle->pdgID);
+  if ( def )   {
+    particle->definition = def;
+    return def->GetParticleName();
+  }
+#if 0
+  TDatabasePDG* db = TDatabasePDG::Instance();
+  TParticlePDG* pdef = db->GetParticle(particle->pdgID);
+  if ( pdef ) return pdef->GetName();
+#endif
+  char text[32];
+  ::snprintf(text,sizeof(text),"PDG:%d",particle->pdgID);
+  return text;
+}
+
+/// Access to the Geant4 particle type
+std::string Geant4ParticleHandle::particleType() const   {
+  if ( particle->definition ) return particle->definition->GetParticleType();
+  G4ParticleTable*      tab = G4ParticleTable::GetParticleTable();
+  G4ParticleDefinition* def = tab->FindParticle(particle->pdgID);
+  if ( def )   {
+    particle->definition = def;
+    return def->GetParticleType();
+  }
+#if 0
+  TDatabasePDG* db = TDatabasePDG::Instance();
+  TParticlePDG* pdef = db->GetParticle(particle->pdgID);
+  if ( pdef ) return pdef->ParticleClass();
+#endif
+  char text[32];
+  ::snprintf(text,sizeof(text),"PDG:%d",particle->pdgID);
+  return text;
+}
+
+/// Access to the creator process name
+std::string Geant4ParticleHandle::processName() const   {
+  if ( particle->process ) return particle->process->GetProcessName();
+  else if ( particle->reason&G4PARTICLE_PRIMARY ) return "Primary";
+  else if ( particle->status&G4PARTICLE_GEN_HISTORY ) return "Gen.History";
+  else if ( particle->status&G4PARTICLE_GEN_CREATED ) return "Generator";
+  return "???";
+}
+
+/// Access to the creator process type name
+std::string Geant4ParticleHandle::processTypeName() const   {
+  if ( particle->process )   {
+    return G4VProcess::GetProcessTypeName(particle->process->GetProcessType());
+  }
+  return "";
+}
+
+/// Offset all particle identifiers (id, parents, daughters) by a constant number
+void Geant4ParticleHandle::offset(int off)  const   {
+  std::set<int> temp;
+  Geant4Particle* p = particle;
+  p->id += off;
+
+  temp = p->daughters;
+  p->daughters.clear();
+  for(std::set<int>::iterator i=temp.begin(); i != temp.end(); ++i)
+    p->daughters.insert((*i)+off);
+
+  temp = p->parents;
+  p->parents.clear();
+  for(std::set<int>::iterator i=temp.begin(); i != temp.end(); ++i)
+    p->parents.insert((*i)+off);
+}
+
+/// Output type 1:+++ <tag>   10 def:0xde4eaa8 [gamma     ,   gamma] reason:      20 E:+1.017927e+03  #Par:  1/4    #Dau:  2
+void Geant4ParticleHandle::dump1(int level, const std::string& src, const char* tag) const   {
+  char text[256];
+  Geant4ParticleHandle p(*this);
+  text[0]=0;
+  if ( p->parents.size() == 1 ) 
+    ::snprintf(text,sizeof(text),"/%d",*(p->parents.begin()));
+  else if ( p->parents.size() >  1 )   {
+    text[0]='/';text[1]=0;
+    for(std::set<int>::const_iterator i=p->parents.begin(); i!=p->parents.end(); ++i)
+      ::snprintf(text+strlen(text),sizeof(text)-strlen(text),"%d ",*i);
+  }
+  printout((DD4hep::PrintLevel)level,src,
+	   "+++ %s %4d def [%-11s,%8s] reason:%8d E:%+.2e %3s #Dau:%3d #Par:%3d%-5s",
+	   tag, p->id, 
+	   p.particleName().c_str(),
+	   p.particleType().c_str(),
+	   p->reason,
+	   p.energy(),
+	   p->g4Parent>0 ? "Sim" : "Gen",
+	   int(p->daughters.size()),
+	   int(p->parents.size()),text);
+}
+
+/// Output type 2:+++ <tag>   20 G4:   7 def:0xde4eaa8 [gamma     ,   gamma] reason:      20 E:+3.304035e+01 in record:YES  #Par:  1/18   #Dau:  0
+void Geant4ParticleHandle::dump2(int level, const std::string& src, const char* tag, int g4id, bool inrec) const   {
+  char text[32];
+  Geant4ParticleHandle p(*this);
+  if ( p->parents.size() == 0 ) text[0]=0;
+  else if ( p->parents.size() == 1 ) ::snprintf(text,sizeof(text),"/%d",*(p->parents.begin()));
+  else if ( p->parents.size() >  1 ) ::snprintf(text,sizeof(text),"/%d..",*(p->parents.begin()));
+  printout((DD4hep::PrintLevel)level,src,
+	   "+++ %s %4d G4:%4d def [%-11s,%8s] reason:%8d "
+	   "E:%+.2e in record:%s  #Par:%3d%-5s #Dau:%3d",
+	   tag, p->id, g4id,
+	   p.particleName().c_str(),
+	   p.particleType().c_str(),
+	   p->reason,
+	   p.energy(),
+	   yes_no(inrec),
+	   int(p->parents.size()),text,
+	   int(p->daughters.size()));
+}
+
+/// 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 Geant4ParticleHandle::dump3(int level, const std::string& src, const char* tag) const  {
+  char text[256];
+  Geant4ParticleHandle p(*this);
+  text[0]=0;
+  if ( p->parents.size() == 1 ) 
+    ::snprintf(text,sizeof(text),"/%d",*(p->parents.begin()));
+  else if ( p->parents.size() >  1 )   {
+    text[0]='/';text[1]=0;
+    for(std::set<int>::const_iterator i=p->parents.begin(); i!=p->parents.end(); ++i)
+      ::snprintf(text+strlen(text),sizeof(text)-strlen(text),"%d ",*i);
+  }
+  printout((DD4hep::PrintLevel)level,src,
+	   "+++ %s ID:%3d %-12s status:%08X typ:%9d Vtx:(%+.2e,%+.2e,%+.2e)[mm] "
+	   "time: %+.2e [ns] #Dau:%3d #Par:%1d%-6s",
+	   tag,p->id,p.particleName().c_str(),p->status,p->pdgID,
+	   p->vsx/mm,p->vsy/mm,p->vsz/mm,p->time/ns,
+	   p->daughters.size(),
+	   p->parents.size(),
+	   text);
+}
+
+/// Default destructor
+Geant4ParticleMap::~Geant4ParticleMap()    {
+  clear();
+}
+
+/// Clear particle maps
+void Geant4ParticleMap::clear()    {
+  releaseObjects(particleMap)();
+  particleMap.clear();
+  equivalentTracks.clear();
+}
+
+/// Adopt particle maps
+void Geant4ParticleMap::adopt(ParticleMap& pm, TrackEquivalents& equiv)    {
+  clear();
+  particleMap = pm;
+  equivalentTracks = equiv;
+  pm.clear();
+  equiv.clear();
+}
+
+/// Access the equivalent track id (shortcut to the usage of TrackEquivalents)
+int Geant4ParticleMap::particleID(int g4_id, bool) const   {
+  int equiv_id  = g4_id;
+  if ( g4_id != 0 )  {
+    ParticleMap::const_iterator ipar;
+    while( (ipar=particleMap.find(equiv_id)) == particleMap.end() )  {
+      TrackEquivalents::const_iterator iequiv = equivalentTracks.find(equiv_id);
+      equiv_id = (iequiv == equivalentTracks.end()) ? -1 : (*iequiv).second;
+      if ( equiv_id < 0 ) {
+	printout(INFO,"Geant4ParticleMap",
+		 "+++ No Equivalent particle for track:%d last known is:%d",
+		 g4_id,equiv_id);
+	break;
+      }
+    }
+  }
+  return equiv_id;
+}
diff --git a/DDG4/src/Geant4ParticleGun.cpp b/DDG4/src/Geant4ParticleGun.cpp
index bfefea6fa..86af0110c 100644
--- a/DDG4/src/Geant4ParticleGun.cpp
+++ b/DDG4/src/Geant4ParticleGun.cpp
@@ -10,6 +10,8 @@
 // Framework include files
 #include "DD4hep/Printout.h"
 #include "DD4hep/InstanceCount.h"
+#include "DDG4/Geant4Context.h"
+#include "DDG4/Geant4Random.h"
 #include "DDG4/Geant4ParticleGun.h"
 #include "CLHEP/Units/SystemOfUnits.h"
 
@@ -17,8 +19,6 @@
 #include "G4ParticleTable.hh"
 #include "G4ParticleDefinition.hh"
 
-#include "TRandom1.h"
-
 // C/C++ include files
 #include <stdexcept>
 #include <limits>
@@ -30,7 +30,7 @@ using namespace DD4hep::Simulation;
 /// Standard constructor
 Geant4ParticleGun::Geant4ParticleGun(Geant4Context* context, const string& name)
   : Geant4GeneratorAction(context, name), m_position(0,0,0), m_direction(1,1,0.3),
-    m_particle(0), m_gun(0), m_rndm(0), m_shotNo(0)
+    m_particle(0), m_gun(0), m_shotNo(0)
 {
   InstanceCount::increment(this);
   m_needsControl = true;
@@ -46,8 +46,6 @@ Geant4ParticleGun::Geant4ParticleGun(Geant4Context* context, const string& name)
 Geant4ParticleGun::~Geant4ParticleGun() {
   if (m_gun)
     delete m_gun;
-  if ( m_rndm )
-    delete m_rndm;
   InstanceCount::decrement(this);
 }
 
@@ -60,13 +58,13 @@ void Geant4ParticleGun::operator()(G4Event* event) {
     G4ParticleTable* particleTable = G4ParticleTable::GetParticleTable();
     m_particle = particleTable->FindParticle(m_particleName);
     if (0 == m_particle) {
-      throw runtime_error("Bad particle type:"+m_particleName+"!");
+      throw runtime_error("Geant4ParticleGun: Bad particle type:"+m_particleName+"!");
     }
   }
   if ( m_isotrop )   {
-    if ( 0 == m_rndm ) m_rndm = new TRandom1();
-    double phi = 2*M_PI*m_rndm->Rndm();
-    double theta = M_PI*m_rndm->Rndm();
+    Geant4Random& rnd = context()->event().random();
+    double phi = 2*M_PI*rnd.rndm();
+    double theta = M_PI*rnd.rndm();
     double x1 = std::sin(theta)*std::cos(phi);
     double x2 = std::sin(theta)*std::sin(phi);
     double x3 = std::cos(theta);
@@ -78,7 +76,7 @@ void Geant4ParticleGun::operator()(G4Event* event) {
       m_direction.SetXYZ(m_direction.X()/r, m_direction.Y()/r, m_direction.Z()/r);
     }
   }
-  print("Geant4ParticleGun","Shoot [%d] %.3f GeV %s pos:(%.3f %.3f %.3f)[mm] dir:(%6.3f %6.3f %6.3f)",
+  print("Shoot [%d] %.3f GeV %s pos:(%.3f %.3f %.3f)[mm] dir:(%6.3f %6.3f %6.3f)",
 	m_shotNo, m_energy/GeV, m_particleName.c_str(), m_position.X(), m_position.Y(), m_position.Z(),
 	m_direction.X(),m_direction.Y(), m_direction.Z());
   m_gun->SetParticleDefinition(m_particle);
diff --git a/DDG4/src/Geant4ParticleHandler.cpp b/DDG4/src/Geant4ParticleHandler.cpp
index eb9e70c63..c844cfac6 100644
--- a/DDG4/src/Geant4ParticleHandler.cpp
+++ b/DDG4/src/Geant4ParticleHandler.cpp
@@ -7,7 +7,7 @@
 //
 //====================================================================
 // Framework include files
-#include "DD4hep/Printout.h"
+//#include "DD4hep/Printout.h"
 #include "DD4hep/Primitives.h"
 #include "DD4hep/InstanceCount.h"
 #include "DDG4/Geant4StepHandler.h"
@@ -30,6 +30,7 @@
 
 #include <set>
 #include <stdexcept>
+#include <algorithm>
 
 using namespace std;
 using namespace DD4hep;
@@ -53,8 +54,8 @@ namespace {
 }
 
 /// Standard constructor
-Geant4ParticleHandler::Geant4ParticleHandler(Geant4Context* context, const std::string& nam)
-  : Geant4GeneratorAction(context,nam), Geant4MonteCarloTruth(), m_userHandler(0)
+Geant4ParticleHandler::Geant4ParticleHandler(Geant4Context* context, const string& nam)
+  : Geant4GeneratorAction(context,nam), Geant4MonteCarloTruth(), m_userHandler(0), m_primaryMap(0)
 {
   //generatorAction().adopt(this);
   eventAction().callAtBegin(this,&Geant4ParticleHandler::beginEvent);
@@ -62,12 +63,12 @@ Geant4ParticleHandler::Geant4ParticleHandler(Geant4Context* context, const std::
   trackingAction().callAtFinal(this,&Geant4ParticleHandler::end,CallbackSequence::FRONT);
   trackingAction().callUpFront(this,&Geant4ParticleHandler::begin,CallbackSequence::FRONT);
   steppingAction().call(this,&Geant4ParticleHandler::step);
-
-  declareProperty("printEndTracking",    m_printEndTracking = false);
-  declareProperty("printStartTracking",  m_printStartTracking = false);
-  declareProperty("keepAllParticles",    m_keepAll = false);
-  declareProperty("saveProcesses",       m_processNames);
-  declareProperty("minimalKineticEnergy",m_kinEnergyCut = 100e0*MeV);
+  m_globalParticleID = 0;
+  declareProperty("PrintEndTracking",    m_printEndTracking = false);
+  declareProperty("PrintStartTracking",  m_printStartTracking = false);
+  declareProperty("KeepAllParticles",    m_keepAll = false);
+  declareProperty("SaveProcesses",       m_processNames);
+  declareProperty("MinimalKineticEnergy",m_kinEnergyCut = 100e0*MeV);
   InstanceCount::increment(this);
 }
 
@@ -98,8 +99,7 @@ bool Geant4ParticleHandler::adopt(Geant4UserParticleHandler* action)    {
 
 /// Clear particle maps
 void Geant4ParticleHandler::clear()  {
-  for(ParticleMap::iterator i=m_particleMap.begin(); i!=m_particleMap.end(); ++i)
-    delete (*i).second;
+  releaseObjects(m_particleMap)();
   m_particleMap.clear();
   m_equivalentTracks.clear();
 }
@@ -144,7 +144,6 @@ void Geant4ParticleHandler::mark(const G4Track* track)   {
     mask.set(G4PARTICLE_CREATED_CALORIMETER_HIT);
   }
   else if ( !mask.isSet(G4PARTICLE_CREATED_TRACKER_HIT) )  {
-    //printout(INFO,name(),"+++ Create TRACKER HIT: id=%d",m_currTrack.id);
     mask.set(G4PARTICLE_CREATED_TRACKER_HIT);
   }
 }
@@ -152,7 +151,7 @@ void Geant4ParticleHandler::mark(const G4Track* track)   {
 /// Event generation action callback
 void Geant4ParticleHandler::operator()(G4Event* event)  {
   typedef Geant4MonteCarloTruth _MC;
-  printout(INFO,name(),"+++ Add EVENT extension of type Geant4ParticleHandler.....");
+  info("+++ Event:%d Add EVENT extension of type Geant4ParticleHandler.....",event->GetEventID());
   context()->event().addExtension((_MC*)this, typeid(_MC), 0);
   clear();
   /// Call the user particle handler
@@ -163,14 +162,14 @@ void Geant4ParticleHandler::operator()(G4Event* event)  {
 
 /// User stepping callback
 void Geant4ParticleHandler::step(const G4Step* step, G4SteppingManager* mgr)   {
-  typedef std::vector<const G4Track*> _Sec;
+  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 ( m_currTrack.energy > m_kinEnergyCut )  {
+  if ( h.trkKineEnergy() > m_kinEnergyCut )  {
     //
     // Tracks below the energy threshold are NOT stored.
     // If these tracks produce hits or are selected due to another signature, 
@@ -193,18 +192,63 @@ void Geant4ParticleHandler::begin(const G4Track* track)   {
   double kine = h.kineticEnergy();
   G4ThreeVector m = track->GetMomentum();
   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() )  {
+      except("+++ Tracking preaction: Primary particle without generator particle!");
+    }
+    prim_part = (*iprim).second;
+    reason |= (G4PARTICLE_PRIMARY|G4PARTICLE_ABOVE_ENERGY_THRESHOLD);
+    m_particleMap[h.id()] = prim_part->addRef();
+  }
 
-  // Extract here all the information from the start of the tracking action
-  // which we will need later to create a proper MC particle.
-  m_currTrack.id          = h.id();
-  m_currTrack.reason      = (kine > m_kinEnergyCut) ? G4PARTICLE_ABOVE_ENERGY_THRESHOLD : 0;
+  if ( prim_part )   {
+    m_currTrack.id           = prim_part->id;
+    m_currTrack.reason       = prim_part->reason|reason;
+    m_currTrack.usermask     = prim_part->usermask;
+    m_currTrack.status       = prim_part->status;
+    m_currTrack.spin[0]      = prim_part->spin[0];
+    m_currTrack.spin[1]      = prim_part->spin[1];
+    m_currTrack.spin[2]      = prim_part->spin[2];
+    m_currTrack.colorFlow[0] = prim_part->colorFlow[0];
+    m_currTrack.colorFlow[1] = prim_part->colorFlow[1];
+    m_currTrack.parents      = prim_part->parents;
+    m_currTrack.daughters    = prim_part->daughters;
+    m_currTrack.definition   = prim_part->definition;
+    m_currTrack.pdgID        = prim_part->pdgID;
+    m_currTrack.mass         = prim_part->mass;
+  }
+  else  {
+    m_currTrack.id           = m_globalParticleID;
+    m_currTrack.reason       = reason;
+    m_currTrack.usermask     = 0;
+    m_currTrack.status      |= G4PARTICLE_SIM_CREATED;
+    m_currTrack.spin[0]      = 0;
+    m_currTrack.spin[1]      = 0;
+    m_currTrack.spin[2]      = 0;
+    m_currTrack.colorFlow[0] = 0;
+    m_currTrack.colorFlow[1] = 0;
+    m_currTrack.parents.clear();
+    m_currTrack.daughters.clear();    
+    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;
   m_currTrack.secondaries = 0;
-  m_currTrack.pdgID       = h.trackDef()->GetPDGEncoding();
-  m_currTrack.energy      = kine;
   m_currTrack.g4Parent    = h.parent();
-  m_currTrack.parent      = h.parent();
-  m_currTrack.definition  = h.trackDef();
   m_currTrack.process     = h.creatorProcess();
   m_currTrack.time        = h.globalTime();
   m_currTrack.vsx         = v.x();
@@ -219,7 +263,6 @@ void Geant4ParticleHandler::begin(const G4Track* track)   {
   m_currTrack.pex         = 0.0;
   m_currTrack.pey         = 0.0;
   m_currTrack.pez         = 0.0;
-  m_currTrack.daughters.clear();
   // If the creator process of the track is in the list of process products to be kept, set the proper flag
   if ( m_currTrack.process )  {
     Processes::iterator i=find(m_processNames.begin(),m_processNames.end(),m_currTrack.process->GetProcessName());
@@ -230,6 +273,7 @@ void Geant4ParticleHandler::begin(const G4Track* track)   {
   if ( m_keepAll )  {
     PropertyMask(m_currTrack.reason).set(G4PARTICLE_KEEP_ALWAYS);    
   }
+
   /// Initial update of the particle using the user handler
   if ( m_userHandler )  {
     m_userHandler->begin(track, m_currTrack);
@@ -239,18 +283,8 @@ void Geant4ParticleHandler::begin(const G4Track* track)   {
 /// Post-track action callback
 void Geant4ParticleHandler::end(const G4Track* track)   {
   Geant4TrackHandler h(track);
-  int id = h.id();
+  int g4_id = h.id();
   PropertyMask mask(m_currTrack.reason);
-  G4PrimaryParticle* prim = primary(id,context()->event().event());
-
-  if ( prim )   {
-    m_currTrack.reason |= (G4PARTICLE_PRIMARY|G4PARTICLE_ABOVE_ENERGY_THRESHOLD);
-    const G4ParticleDefinition* def = m_currTrack.definition;
-    printout(INFO,name(),"+++ Add Primary particle %d def:%p [%s, %s] reason:%d",
-	     id, def, 
-	     def ? def->GetParticleName().c_str() : "UNKNOWN",
-	     def ? def->GetParticleType().c_str() : "UNKNOWN", m_currTrack.reason);
-  }
 
   if ( !mask.isNull() )   {
     // These are candate tracks with a probability to be stored due to their properties:
@@ -261,85 +295,162 @@ void Geant4ParticleHandler::end(const G4Track* track)   {
     // - to be kept due to creator process 
     //
     // Update vertex end point and final momentum
+    Geant4ParticleHandle ph(&m_currTrack);
     G4ThreeVector m = track->GetMomentum();
-    m_currTrack.pex = m.x();
-    m_currTrack.pey = m.y();
-    m_currTrack.pez = m.z();
-
+    ph->pex = m.x();
+    ph->pey = m.y();
+    ph->pez = m.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->usermask |= p_par->usermask;
+      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);
     }
-
+    ParticleMap::iterator ip = m_particleMap.find(g4_id);
+    if ( mask.isSet(G4PARTICLE_PRIMARY) )   {
+      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 = m_particleMap[id] = new Particle();
+    Particle* p = ip==m_particleMap.end() ? (m_particleMap[g4_id] = new Particle()) : (*ip).second;
     p->get_data(m_currTrack);
-    // Add this track to it's parents list of daughters
-    ParticleMap::iterator ipar = m_particleMap.find(p->g4Parent);
-    if ( ipar != m_particleMap.end() )  {
-      Particle* p_par = (*ipar).second;
-      p_par->daughters.insert(id);
-    }
-    m_equivalentTracks[id] = id;
-#if 0
-    /// Some printout
-    const char* hit  = mask.isSet(G4PARTICLE_CREATED_HIT) ? "CREATED_HIT" : "";
-    const char* sec  = mask.isSet(G4PARTICLE_HAS_SECONDARIES) ? "SECONDARIES" : "";
-    const char* prim = mask.isSet(G4PARTICLE_PRIMARY) ? "PRIMARY" : "";
-    printout(INFO,name(),"+++ Tracking postaction: %d/%d par:%d [%s, %s] created by:%s E:%e state:%s %s %s %s",
-	     id,int(m_particleMap.size()),
-	     h.parent(),h.name().c_str(),h.type().c_str(),h.creatorName().c_str(),
-	     p->energy, h.statusName(), prim, hit, sec);
-#endif
   }
   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[id] = h.parent();
+    m_equivalentTracks[g4_id] = m_currTrack.g4Parent;
   }
 }
 
 /// Pre-event action callback
 void Geant4ParticleHandler::beginEvent(const G4Event* event)  {
+  Geant4PrimaryInteraction* interaction = context()->event().extension<Geant4PrimaryInteraction>();
+  info("+++ Event %d Begin event action. Access event related information.",event->GetEventID());
+  m_primaryMap = context()->event().extension<Geant4PrimaryMap>();
+  m_globalParticleID = interaction->nextPID();
+  m_particleMap.clear();
+  m_equivalentTracks.clear();
   /// Call the user particle handler
   if ( m_userHandler )  {
     m_userHandler->begin(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);
+}
+
 /// Post-event action callback
 void Geant4ParticleHandler::endEvent(const G4Event* event)  {
   int count = 0;
+  int level = outputLevel();
   do {
-    printout(INFO,name(),"+++ Iteration:%d Tracks:%d Equivalents:%d",++count,m_particleMap.size(),m_equivalentTracks.size());
+    if ( level <= VERBOSE ) dumpMap("Particle");
+    print("+++ Iteration:%d Tracks:%d Equivalents:%d",++count,m_particleMap.size(),m_equivalentTracks.size());
   } while( recombineParents() > 0 );
-  // Update the particle's parents and 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;
-    p->parent = equivalentTrack(p->g4Parent);
-    if ( p->parent > 0 )  {
-      ipar = m_particleMap.find(p->parent);
-      if ( ipar != iend )   {
-	set<int>& daughters = (*ipar).second->daughters;
-	if ( daughters.find(p->id) == daughters.end() ) daughters.insert(p->id);
-      }
-    }
-  }
-  /// No we have to updte the map of equivalent tracks and assign the 'equivalentTrack' entry
-  for(TrackEquivalents::iterator i=m_equivalentTracks.begin(); i!=m_equivalentTracks.end(); ++i)  {
-    int& track_id = (*i).second;
-    int  equiv_id = equivalentTrack(track_id);
-    track_id = equiv_id;
-  }
+
+  if ( level <= VERBOSE ) dumpMap("Recombined");
+  // Rebase the simulated tracks, so that they fit to the generator particles
+  rebaseSimulatedTracks(0);
+  if ( level <= DEBUG ) dumpMap("Rebased");
   // Consistency check....
   checkConsistency();
   /// Call the user particle handler
   if ( m_userHandler )  {
     m_userHandler->end(event);
   }
+  // Now export the data to the final record.
+  Geant4ParticleMap* part_map = context()->event().extension<Geant4ParticleMap>();
+  part_map->adopt(m_particleMap, m_equivalentTracks);
+  m_primaryMap = 0;
+  clear();
+}
+
+/// Rebase the simulated tracks, so that they fit to the generator particles
+void Geant4ParticleHandler::rebaseSimulatedTracks(int )   {
+  /// No we have to update the map of equivalent tracks and assign the 'equivalentTrack' entry
+  TrackEquivalents equivalents, orgParticles;
+  ParticleMap      finalParticles;
+  ParticleMap::const_iterator ipar, iend, i;
+  int count;
+
+  Geant4PrimaryInteraction* interaction = context()->event().extension<Geant4PrimaryInteraction>();
+  ParticleMap& pm = interaction->particles;
+
+  // (1.0) Copy the pre-defined particle mapping for the simulated tracks
+  //       It is assumed the mapping is ZERO based without holes.
+  for(count = 0, iend=pm.end(), i=pm.begin(); i!=iend; ++i)  {
+    Particle* p = (*i).second;
+    orgParticles[p->id] = p->id;
+    finalParticles[p->id] = p;
+    if ( p->id > count ) count = p->id;
+    if ( (p->reason&G4PARTICLE_PRIMARY) != G4PARTICLE_PRIMARY )  {
+      p->addRef();
+    }
+  }
+  // (1.1) Define the new particle mapping for the simulated tracks
+  for(++count, iend=m_particleMap.end(), i=m_particleMap.begin(); i!=iend; ++i)  {
+    Particle* p = (*i).second;
+    if ( (p->reason&G4PARTICLE_PRIMARY) != G4PARTICLE_PRIMARY )  {
+      //if ( orgParticles.find(p->id) == orgParticles.end() )  {
+      orgParticles[p->id] = count;
+      finalParticles[count] = p;
+      p->id = count;
+      ++count;
+    }
+  }
+  // (2) Re-evaluate the corresponding geant4 track equivalents using the new mapping
+  for(TrackEquivalents::iterator i=m_equivalentTracks.begin(),iend=m_equivalentTracks.end(); i!=iend; ++i)  {
+    int g4_equiv = (*i).first;
+    ParticleMap::const_iterator ipar;
+    while( (ipar=m_particleMap.find(g4_equiv)) == m_particleMap.end() )  {
+      TrackEquivalents::const_iterator iequiv = m_equivalentTracks.find(g4_equiv);
+      if ( iequiv == iend )
+	break;  // ERROR !! Will be handled by printout below because ipar==end()
+      g4_equiv = (*iequiv).second;
+    }
+    if ( ipar != m_particleMap.end() )
+      equivalents[(*i).first] = (*ipar).second->id;  // requires (1) !
+    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
+  //     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_HISTORY) )  {
+      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);
+	}
+      }
+    }
+  }
+  m_particleMap = finalParticles;
 }
 
 /// Clean the monte carlo record. Remove all unwanted stuff.
@@ -350,11 +461,12 @@ int Geant4ParticleHandler::recombineParents()  {
   /// Need to start from BACK, to clean first the latest produced stuff.
   /// Otherwise the daughter list of the earlier produced tracks would not be empty!
   for(ParticleMap::reverse_iterator i=m_particleMap.rbegin(); i!=m_particleMap.rend(); ++i)  {    
-    Particle* par = (*i).second;
-    set<int>& daughters = par->daughters;
+    int g4_id = (*i).first;
+    Particle* p = (*i).second;
+    set<int>& daughters = p->daughters;
     if ( daughters.size() == 0 )   {
-      PropertyMask mask(par->reason);
-      int  id             =  par->id;
+      PropertyMask mask(p->reason);
+      int  id             =  p->id;
       bool secondaries    =  mask.isSet(G4PARTICLE_HAS_SECONDARIES);
       bool tracker_track  =  mask.isSet(G4PARTICLE_CREATED_TRACKER_HIT);
       bool calo_track     =  mask.isSet(G4PARTICLE_CREATED_CALORIMETER_HIT);
@@ -362,7 +474,6 @@ int Geant4ParticleHandler::recombineParents()  {
       bool low_energy     = !mask.isSet(G4PARTICLE_ABOVE_ENERGY_THRESHOLD);
       bool keep_process   =  mask.isSet(G4PARTICLE_KEEP_PROCESS);
       bool keep_parent    =  mask.isSet(G4PARTICLE_KEEP_PARENT);
-      int  parent_id      = par->g4Parent;
       bool remove_me      = false;
 
       if ( id == break_trackID )   {  // Used for debugging to set break point
@@ -377,7 +488,7 @@ int Geant4ParticleHandler::recombineParents()  {
 	//continue;
       }
       else if ( keep_process )  {
-	ParticleMap::iterator ip = m_particleMap.find(parent_id);
+	ParticleMap::iterator ip = m_particleMap.find(p->g4Parent);
 	if ( ip != m_particleMap.end() )   {
 	  Particle* parent_part = (*ip).second;
 	  PropertyMask parent_mask(parent_part->reason);
@@ -408,19 +519,19 @@ int Geant4ParticleHandler::recombineParents()  {
 
       /// Remove this track from the list and also do the cleanup in the parent's children list
       if ( remove_me )  {
-	ParticleMap::iterator ip = m_particleMap.find(parent_id);
-	remove.insert(id);
-	m_equivalentTracks[id] = parent_id;
+	ParticleMap::iterator ip = m_particleMap.find(p->g4Parent);
+	remove.insert(g4_id);
+	m_equivalentTracks[g4_id] = p->g4Parent;
 	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 += par->steps;
-	  parent_part->secondaries += par->secondaries;
+	  parent_part->steps += p->steps;
+	  parent_part->secondaries += p->secondaries;
 	  /// Update of the particle using the user handler
 	  if ( m_userHandler )  {
-	    m_userHandler->combine(*par, *parent_part);
+	    m_userHandler->combine(*p, *parent_part);
 	  }
 	}
       }
@@ -429,7 +540,7 @@ int Geant4ParticleHandler::recombineParents()  {
   for(set<int>::const_iterator r=remove.begin(); r!=remove.end();++r)  {
     ParticleMap::iterator ir = m_particleMap.find(*r);
     if ( ir != m_particleMap.end() )  {
-      delete (*ir).second;
+      (*ir).second->release();
       m_particleMap.erase(ir);
     }
   }
@@ -444,42 +555,46 @@ void Geant4ParticleHandler::checkConsistency()  const   {
   for(ParticleMap::const_iterator j, i=m_particleMap.begin(); i!=m_particleMap.end(); ++i)  {
     Particle* p = (*i).second;
     PropertyMask mask(p->reason);
+    PropertyMask status(p->status);
     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;
-      j = m_particleMap.find(id_dau);
-      if ( j == m_particleMap.end() )   {
+      if ( (j=m_particleMap.find(id_dau)) == m_particleMap.end() )   {
 	++num_errors;
-	printout(INFO,name(),"+++ Particle:%d Daughter %d is not in particle map!",p->id,id_dau);
+	error("+++ Particle:%d Daughter %d is not in particle map!",p->id,id_dau);
       }
     }
-    // For all particles except the primaries, the parent must be contained in the record.
-    if ( !mask.isSet(G4PARTICLE_PRIMARY) )  {
-      int id_par = p->parent;
-      j = m_particleMap.find(id_par);
-      if ( j == m_particleMap.end() )   {
+    // We assume that particles from the generator have consistent parents
+    // For all other particles except the primaries, the parent must be contained in the record.
+    if ( !mask.isSet(G4PARTICLE_PRIMARY) && !status.isSet(G4PARTICLE_GEN_HISTORY) )  {
+      int parent_id = equivalentTrack(p->g4Parent);
+      bool in_map = (j=m_particleMap.find(parent_id)) != m_particleMap.end();
+      bool in_parent_list = p->parents.find(parent_id) != p->parents.end();
+      char parent_list[1024];
+      parent_list[0] = 0;
+      if ( !in_map || !in_parent_list )  {
 	++num_errors;
-	printout(INFO,name(),"+++ Particle:%d Parent %d is not in particle map!",p->id,id_par);
+	for(set<int>::const_iterator ip=p->parents.begin(); ip!=p->parents.end();++ip)
+	  ::snprintf(parent_list+strlen(parent_list),sizeof(parent_list)-strlen(parent_list),"%d ",*ip);
+	error("+++ Particle:%d Parent %d (G4id:%d)  In record:%s In parent list:%s [%s]",
+		 p->id,parent_id,p->g4Parent,yes_no(in_map),yes_no(in_parent_list),parent_list);
       }
     }
   }
 
   /// No we have to check the consistency of the map of equivalent tracks used to assign the
   /// proper MC particle to the created hits
-  for(TrackEquivalents::const_iterator i=m_equivalentTracks.begin(); i!=m_equivalentTracks.end(); ++i)  {
-    int track_id = (*i).second;
-    int equiv_id = equivalentTrack(track_id);
-    ParticleMap::const_iterator j = m_particleMap.find(equiv_id);
-    if ( j == m_particleMap.end() )   {
-      int g4_id = (*i).first;
+  for(TrackEquivalents::const_iterator i=m_equivalentTracks.begin(), iend=m_equivalentTracks.end(); i!=iend; ++i)  {
+    int g4_id    = (*i).first;
+    int equiv_id = equivalentTrack(g4_id);
+    if ( equiv_id < 0 )  {
       ++num_errors;
-      printout(INFO,name(),"+++ Geant4 Track:%d Track:%d Equivalent track %d is not in particle map!",g4_id,track_id,equiv_id);
     }
   }
 
   if ( num_errors > 0 )  {
-    printout(ERROR,name(),"+++ Consistency check failed. Found %d problems.",num_errors);
+    except("+++ Consistency check failed. Found %d problems.",num_errors);
   }
 }
 
@@ -487,17 +602,10 @@ void Geant4ParticleHandler::checkConsistency()  const   {
 int Geant4ParticleHandler::equivalentTrack(int g4_id)  const  {
   int equiv_id  = g4_id;
   if ( g4_id != 0 )  {
-    ParticleMap::const_iterator ipar;
-    while( (ipar=m_particleMap.find(equiv_id)) == m_particleMap.end() )  {
-      TrackEquivalents::const_iterator iequiv = m_equivalentTracks.find(equiv_id);
-      equiv_id = (iequiv == m_equivalentTracks.end()) ? -1 : (*iequiv).second;
-      if ( equiv_id < 0 ) {
-	printout(INFO,name(),"+++ No Equivalent particle for track:%d last known is:%d",g4_id,equiv_id);
-	break;
-      }
-    }
+    TrackEquivalents::const_iterator iequiv = m_equivalentTracks.find(equiv_id);
+    return (iequiv == m_equivalentTracks.end()) ? -1 : (*iequiv).second;
   }
-  return equiv_id;
+  return -1;
 }
 
 /// Access the equivalent track id (shortcut to the usage of TrackEquivalents)
diff --git a/DDG4/src/Geant4ParticlePrint.cpp b/DDG4/src/Geant4ParticlePrint.cpp
index 8a7768f07..ad6aa9395 100644
--- a/DDG4/src/Geant4ParticlePrint.cpp
+++ b/DDG4/src/Geant4ParticlePrint.cpp
@@ -13,10 +13,6 @@
 #include "DDG4/Geant4ParticlePrint.h"
 #include "DDG4/Geant4Data.h"
 
-#include "G4ParticleDefinition.hh"
-#include "G4VProcess.hh"
-#include "G4Event.hh"
-
 using namespace std;
 using namespace DD4hep;
 using namespace DD4hep::Simulation;
@@ -28,6 +24,9 @@ Geant4ParticlePrint::Geant4ParticlePrint(Geant4Context* context, const std::stri
   : Geant4EventAction(context,nam)
 {
   declareProperty("OutputType",m_outputType=3);
+  declareProperty("PrintBegin",m_printBegin=false);
+  declareProperty("PrintEnd",  m_printEnd=true);
+  declareProperty("PrintGen",  m_printGeneration=true);
   InstanceCount::increment(this);
 }
 
@@ -36,53 +35,63 @@ Geant4ParticlePrint::~Geant4ParticlePrint()  {
   InstanceCount::decrement(this);
 }
 
+/// Print particle table
+void Geant4ParticlePrint::makePrintout() const  {
+  Geant4ParticleMap* parts = context()->event().extension<Geant4ParticleMap>();
+  if ( parts )   {
+    const ParticleMap& particles = parts->particles();
+    if ( (m_outputType&2) != 0 ) printParticleTree(particles);  // Tree printout....
+    if ( (m_outputType&1) != 0 ) printParticles(particles);     // Table printout....
+    return;
+  }
+  except("No Geant4MonteCarloTruth object present in the event structure to access the particle information!", c_name());
+}
+
+/// Generation action callback
+void Geant4ParticlePrint::operator()(G4Event* )  {
+  if ( m_printGeneration ) makePrintout();
+}
+
 /// Pre-event action callback
 void Geant4ParticlePrint::begin(const G4Event* )  {
+  if ( m_printBegin ) makePrintout();
 }
 
 /// Post-event action callback
 void Geant4ParticlePrint::end(const G4Event* )  {
-  Geant4MonteCarloTruth* truth = context()->event().extension<Geant4MonteCarloTruth>();
-  if ( truth )   {
-    const ParticleMap& particles = truth->particles();
-    if ( (m_outputType&1) != 0 ) printParticles(particles);     // Table printout....
-    if ( (m_outputType&2) != 0 ) printParticleTree(particles);  // Tree printout....
-    return;
-  }
-  except("No Geant4MonteCarloTruth object present in the event structure to access the particle information!", c_name());
+  if ( m_printEnd ) makePrintout();
 }
 
-void Geant4ParticlePrint::printParticle(const std::string& prefix, const Particle* p) const   {
+void Geant4ParticlePrint::printParticle(const std::string& prefix, Geant4ParticleHandle p) const   {
   char equiv[32];
   PropertyMask mask(p->reason);
-  const char* proc_name = "???";
-  const char* proc_type = p->process ? G4VProcess::GetProcessTypeName(p->process->GetProcessType()).c_str() : "";
-
-  if ( p->process ) proc_name = p->process->GetProcessName().c_str();
-  else if ( mask.isSet(G4PARTICLE_PRIMARY) ) proc_name = "Primary";
+  string proc_name = p.processName();
+  string proc_type = p.processTypeName();
+  int parent_id = p->parents.empty() ? -1 : *(p->parents.begin());
 
   equiv[0] = 0;
-  if ( p->g4Parent != p->parent )  {
+  if ( p->parents.end() == p->parents.find(p->g4Parent) )  {
     ::snprintf(equiv,sizeof(equiv),"/%d",p->g4Parent);
   }
-  printout(INFO,name(),"+++ %sID: %6d %12s %6d%-7s %7s %3s %5d %6s %8.3g %-4s %-7s %-7s %-3s [%s%s%s]",
-	   prefix.c_str(),
-	   p->id,
-	   p->definition->GetParticleName().c_str(),
-	   p->parent,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" : "",
-	   proc_name,
-	   p->process ? "/" : "",
-	   proc_type
-	   );
+  print("+++ %s ID:%7d %12s %6d%-7s %7s %3s %5d %3s %+.3e  %-4s %-7s %-3s %-3s %2d  [%s%s%s]",
+	prefix.c_str(),
+	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()
+	);
 }
 
 /// Print record of kept particles
@@ -95,11 +104,11 @@ void Geant4ParticlePrint::printParticles(const ParticleMap& particles) const  {
   int num_calo_hits = 0;
   int num_tracker_hits = 0;
 
-  printout(INFO,name(),"+++ MC Particles #Tracks:%6d %-12s Parent%-7s "
-	   "Primary Secondary Energy %-8s Calo Tracker Process/Par Details",
-	   int(particles.size()),"ParticleType","","in [MeV]");
+  print("+++ MC Particles #Tracks:%7d ParticleType Parent/Geant4 "
+	"Primary Secondary Energy in [MeV] Calo Tracker Process/Par Details",
+	int(particles.size()));
   for(ParticleMap::const_iterator i=particles.begin(); i!=particles.end(); ++i)  {
-    const Particle* p = (*i).second;
+    Geant4ParticleHandle p = (*i).second;
     PropertyMask mask(p->reason);
     printParticle("MC Particle Track",p);
     num_secondaries += int(p->daughters.size());
@@ -110,17 +119,15 @@ void Geant4ParticlePrint::printParticles(const ParticleMap& particles) const  {
     if ( mask.isSet(G4PARTICLE_KEEP_PARENT) ) ++num_parent;
     else if ( mask.isSet(G4PARTICLE_KEEP_PROCESS) ) ++num_process;
   }
-  printout(INFO,name(),"+++ MC Particles #Tracks:%6d %-12s Parent%-7s "
-	   "Primary Secondary Energy %-8s Calo Tracker Process/Parent",
-	   int(particles.size()),"","","");
-  printout(INFO,name(),"+++ MC Particle Summary: %6s %-12s %6s%-7s "
-	   "%7d %9d %6d %-8s %4d %7d %7d %6d",
-	   "","","","",
-	   num_primary, num_secondaries, num_energy,"",
-	   num_calo_hits,num_tracker_hits,num_process,num_parent);
+  print("+++ MC Particles #Tracks:%7d ParticleType Parent/Geant4 "
+	"Primary Secondary Energy          Calo Tracker Process/Par",
+	int(particles.size()));
+  print("+++ MC Particle Summary:                       %7d %10d %7d  %7d      %9d %5d %6d",
+	num_primary, num_secondaries, num_energy,
+	num_calo_hits,num_tracker_hits,num_process,num_parent);
 }
 
-void Geant4ParticlePrint::printParticleTree(const ParticleMap& particles, int level, const Particle* p)  const  {
+void Geant4ParticlePrint::printParticleTree(const ParticleMap& particles, int level, Geant4ParticleHandle p)  const  {
   char txt[32];
   size_t len = sizeof(txt)-1;
   // Ensure we do not overwrite the array
@@ -128,7 +135,7 @@ void Geant4ParticlePrint::printParticleTree(const ParticleMap& particles, int le
   
   ::snprintf(txt,sizeof(txt),"%5d ",level);
   ::memset(txt+6,' ',len-6);
-  txt[len] = 0;
+  txt[len-1] = 0;
   txt[len-2] = '>';
   txt[level+6]='+';
   ::memset(txt+level+6+1,'-',len-level-3-6);
@@ -138,19 +145,19 @@ void Geant4ParticlePrint::printParticleTree(const ParticleMap& particles, int le
   // 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;
-    const Particle* dau = (*particles.find(id_dau)).second;
+    Geant4ParticleHandle dau = (*particles.find(id_dau)).second;
     printParticleTree(particles,level+1,dau);
   }
 }
 
 /// Print tree of kept particles
 void Geant4ParticlePrint::printParticleTree(const ParticleMap& particles)  const  {
-  printout(INFO,name(),"+++ MC Particle Parent daughter relationships. [%d particles]",int(particles.size()));
-  printout(INFO,name(),"+++ MC Particles %12s #Tracks:%7d %-12s Parent%-7s "
-	   "Primary Secondary Energy %-8s Calo Tracker Process/Par Details",
-	   "",int(particles.size()),"ParticleType","","in [MeV]");
+  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",
+	"",int(particles.size()),"ParticleType","","in [MeV]");
   for(ParticleMap::const_iterator i=particles.begin(); i!=particles.end(); ++i)  {
-    const Particle* p = (*i).second;
+    Geant4ParticleHandle p = (*i).second;
     PropertyMask mask(p->reason);
     if ( mask.isSet(G4PARTICLE_PRIMARY) ) printParticleTree(particles,0,p);
   }
diff --git a/DDG4/src/Geant4Primary.cpp b/DDG4/src/Geant4Primary.cpp
new file mode 100644
index 000000000..bfd24d1b1
--- /dev/null
+++ b/DDG4/src/Geant4Primary.cpp
@@ -0,0 +1,119 @@
+// $Id: Geant4Hits.cpp 513 2013-04-05 14:31:53Z gaede $
+//====================================================================
+//  AIDA Detector description implementation for LCD
+//--------------------------------------------------------------------
+//
+//  Author     : M.Frank
+//
+//====================================================================
+
+// Framework include files
+#include "DD4hep/Primitives.h"
+#include "DD4hep/InstanceCount.h"
+#include "DDG4/Geant4Primary.h"
+
+// C/C++ include files
+#include <stdexcept>
+#include <cstdio>
+
+using namespace DD4hep;
+using namespace DD4hep::Simulation;
+
+/// Default destructor
+PrimaryExtension::~PrimaryExtension() {
+}
+
+/// Default destructor
+Geant4PrimaryMap::~Geant4PrimaryMap()   {
+  releaseObjects(primaryMap)();  
+}
+
+/// Default constructor
+Geant4PrimaryInteraction::Geant4PrimaryInteraction()
+  : mask(0), next_particle_identifier(-1)
+{
+}
+
+/// Copy constructor
+Geant4PrimaryInteraction::Geant4PrimaryInteraction(const Geant4PrimaryInteraction&)
+  : mask(0), next_particle_identifier(-1)
+{
+}
+
+/// Assignment operator
+Geant4PrimaryInteraction& Geant4PrimaryInteraction::operator=(const Geant4PrimaryInteraction& c)  {
+  if ( &c == this ) {}
+  return *this;
+}
+
+/// Default destructor
+Geant4PrimaryInteraction::~Geant4PrimaryInteraction()   {
+  releaseObjects(vertices)();
+  releaseObjects(particles)();
+}
+
+/// Access a new particle identifier within the interaction
+int Geant4PrimaryInteraction::nextPID()   {
+  return ++next_particle_identifier;
+}
+
+/// Access a new particle identifier within the interaction
+void Geant4PrimaryInteraction::setNextPID(int new_value)   {
+  next_particle_identifier = new_value-1;
+}
+
+/// Default constructor
+Geant4PrimaryEvent::Geant4PrimaryEvent() 
+{
+}
+
+/// Copy constructor
+Geant4PrimaryEvent::Geant4PrimaryEvent(const Geant4PrimaryEvent&)
+{
+}
+
+/// Assignment operator
+Geant4PrimaryEvent& Geant4PrimaryEvent::operator=(const Geant4PrimaryEvent& c)  {
+  if ( &c == this ) {}
+  return *this;
+}
+
+/// Default destructor
+Geant4PrimaryEvent::~Geant4PrimaryEvent()   {
+  destroyObjects(m_interactions)();
+}
+
+/// Add a new interaction object to the event
+void Geant4PrimaryEvent::add(int id, Geant4PrimaryInteraction* interaction)   {
+  if ( interaction )  {
+    Interactions::iterator i = m_interactions.find(id);
+    if ( i == m_interactions.end() )  {
+      interaction->mask = id;
+      m_interactions.insert(std::make_pair(id,interaction));
+      return;
+    }
+    char text[132];
+    ::snprintf(text,sizeof(text),"Geant4PrimaryEvent: Interaction with ID '%d' "
+	       "exists and cannot be added twice!",id);
+    throw std::runtime_error(text);
+  }
+  throw std::runtime_error("Geant4PrimaryEvent: CANNOT add invalid Interaction!");
+}
+
+/// Retrieve an interaction by it's ID
+Geant4PrimaryEvent::Interaction* Geant4PrimaryEvent::get(int mask) const   {
+  Interactions::const_iterator i = m_interactions.find(mask);
+  if ( i != m_interactions.end() )  {
+    return (*i).second;
+  }
+  return 0;
+}
+
+/// Retrieve all intractions
+std::vector<Geant4PrimaryEvent::Interaction*> Geant4PrimaryEvent::interactions() const   {
+  std::vector<Interaction*> v;
+  for(Interactions::const_iterator i=m_interactions.begin(); i!=m_interactions.end(); ++i)
+    v.push_back((*i).second);
+  return v;
+}
+
diff --git a/DDG4/src/Geant4PrimaryHandler.cpp b/DDG4/src/Geant4PrimaryHandler.cpp
new file mode 100644
index 000000000..f45ca9ed7
--- /dev/null
+++ b/DDG4/src/Geant4PrimaryHandler.cpp
@@ -0,0 +1,71 @@
+// $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 "DD4hep/Printout.h"
+#include "DD4hep/InstanceCount.h"
+#include "DDG4/Geant4Primary.h"
+#include "DDG4/Geant4PrimaryHandler.h"
+
+#include "G4Event.hh"
+#include "G4PrimaryVertex.hh"
+#include "G4PrimaryParticle.hh"
+
+#include <stdexcept>
+
+using namespace DD4hep;
+using namespace DD4hep::Simulation;
+
+/// Standard constructor
+Geant4PrimaryHandler::Geant4PrimaryHandler(Geant4Context* context, const std::string& nam)
+  : Geant4GeneratorAction(context,nam)
+{
+  InstanceCount::increment(this);
+}
+
+/// Default destructor
+Geant4PrimaryHandler::~Geant4PrimaryHandler()  {
+  InstanceCount::decrement(this);
+}
+
+/// Event generation action callback
+void Geant4PrimaryHandler::operator()(G4Event* event)  {
+  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;
+  Interaction::VertexMap::const_iterator iv, ivend;
+  int num_vtx = 0, num_part = 0;
+
+  for(iv=vm.begin(), ivend=vm.end(); iv != ivend; ++iv, ++num_vtx, num_part=0)  {
+    Geant4Vertex* v = (*iv).second;
+    G4PrimaryVertex* g4 = new G4PrimaryVertex(v->x,v->y,v->z,v->time);
+    print("+++++ G4PrimaryVertex %3d  at (%+.2e,%+.2e,%+.2e) [mm] %+.2e [ns]  %d particles",
+	  num_vtx,v->x/mm,v->y/mm,v->z/mm,v->time/ns,int(v->out.size()));
+    // Generate Geant4 primaries coming from this vertex
+    for(Geant4Vertex::Particles::const_iterator j=v->out.begin(); j!=v->out.end(); ++j, ++num_part)  {
+      // Same particle cannot come from 2 vertices! Hence it must ALWAYS be recreated
+      Interaction::ParticleMap::const_iterator ip = pm.find(*j);
+      if ( ip == pm.end() )  { // ERROR. may not happen. Something went wrong in the gathering.
+	const char* text = "+++ Fatal inconsistency in the Geant4PrimaryInteraction record.";
+	printout(ERROR,name(),text);
+	throw std::runtime_error(name()+std::string("  ")+text);
+      }
+      Geant4Particle* p = (*ip).second;
+      G4PrimaryParticle* g4part = new G4PrimaryParticle(p->pdgID,p->psx,p->psy,p->psz);
+      g4part->SetMass(p->mass);
+      g4->SetPrimary(g4part);
+      printM1("+++ +-> G4Primary[%3d] ID:%3d type:%9d Momentum:(%+.2e,%+.2e,%+.2e) [GeV] time:%+.2e [ns] #Par:%3d #Dau:%3d",
+	       num_part,p->id,p->pdgID,p->psx/GeV,p->psy/GeV,p->psz/GeV,p->time/ns,
+	       int(p->parents.size()),int(p->daughters.size()));
+      primaries->primaryMap[g4part] = p->addRef();
+    }
+    event->AddPrimaryVertex(g4);
+  }
+}
diff --git a/DDG4/src/Geant4ROOTDump.cpp b/DDG4/src/Geant4ROOTDump.cpp
index 3d48b9358..457b0c7db 100644
--- a/DDG4/src/Geant4ROOTDump.cpp
+++ b/DDG4/src/Geant4ROOTDump.cpp
@@ -12,6 +12,7 @@
 #include "DD4hep/Factories.h"
 #include "DD4hep/Primitives.h"
 #include "DDG4/Geant4DataDump.h"
+#include "DDG4/Geant4Particle.h"
 
 #include "TInterpreter.h"
 #include "TSystem.h"
@@ -127,7 +128,7 @@ static long dump_root(DD4hep::Geometry::LCDD&, int argc, char** argv) {
 	if ( data.first == cl_particles )  {
 	  Particles* parts = (Particles*)data.second;
 	  dump.print(INFO, (*i).first, parts);
-	  for_each(parts->begin(), parts->end(), DestroyObject<Particle*>());
+	  for_each(parts->begin(), parts->end(), DestroyObject<Geant4Particle*>());
 	}
       }
       for(ENTRIES::const_iterator i=event.begin(); i!=event.end(); ++i)  {
@@ -137,12 +138,12 @@ static long dump_root(DD4hep::Geometry::LCDD&, int argc, char** argv) {
 	else if ( data.first == cl_tracker )   {
 	  TrackerHits* hits = (TrackerHits*)data.second;
 	  dump.print(INFO, (*i).first, hits);
-	  for_each(hits->begin(), hits->end(), DestroyObject<SimpleTracker::Hit*>());
+	  for_each(hits->begin(), hits->end(), DestroyObject<Geant4Tracker::Hit*>());
 	}
 	else if ( data.first == cl_calo )   {
 	  CalorimeterHits* hits = (CalorimeterHits*)data.second;
 	  dump.print(INFO, (*i).first, hits);
-	  for_each(hits->begin(), hits->end(), DestroyObject<SimpleCalorimeter::Hit*>());
+	  for_each(hits->begin(), hits->end(), DestroyObject<Geant4Calorimeter::Hit*>());
 	}
 	if ( data.first ) data.first->Destructor(data.second);
       }
diff --git a/DDG4/src/Geant4Random.cpp b/DDG4/src/Geant4Random.cpp
new file mode 100644
index 000000000..2e729ff7c
--- /dev/null
+++ b/DDG4/src/Geant4Random.cpp
@@ -0,0 +1,82 @@
+// $Id: Geant4Converter.cpp 603 2013-06-13 21:15:14Z markus.frank $
+//====================================================================
+//  AIDA Detector description implementation for LCD
+//--------------------------------------------------------------------
+//
+//  Author     : M.Frank
+//
+//====================================================================
+
+// Framework include files
+#include "DD4hep/Printout.h"
+#include "DD4hep/InstanceCount.h"
+#include "DDG4/Geant4Random.h"
+
+#include "TRandom1.h"
+
+// C/C++ include files
+#include <cmath>
+
+using namespace std;
+using namespace DD4hep::Simulation;
+
+/// Default constructor
+Geant4Random::Geant4Random()   {
+  if ( 0 == gRandom ) gRandom = new TRandom1();
+  InstanceCount::increment(this);
+}
+
+/// Default destructor
+Geant4Random::~Geant4Random()  {
+  InstanceCount::decrement(this);
+}
+
+void   Geant4Random::circle(double &x, double &y, double r)  {
+  gRandom->Circle(x,y,r);
+}
+
+//
+double Geant4Random::exp(double tau)  {
+  return gRandom->Exp(tau);
+}
+
+//
+double Geant4Random::gauss(double mean, double sigma)  {
+  return gRandom->Gaus(mean,sigma);
+}
+
+//
+double Geant4Random::landau(double mean, double sigma)  {
+  return gRandom->Landau(mean,sigma);
+}
+
+//
+double Geant4Random::rndm(int i)  {
+  return gRandom->Rndm(i);
+}
+
+//
+void   Geant4Random::rndmArray(int n, float *array)  {
+  gRandom->RndmArray(n,array);
+}
+
+//
+void   Geant4Random::rndmArray(int n, double *array)  {
+  gRandom->RndmArray(n,array);
+}
+
+//
+void   Geant4Random::sphere(double &x, double &y, double &z, double r)  {
+  gRandom->Sphere(x,y,z,r);
+}
+
+//
+double Geant4Random::uniform(double x1)  {
+  return gRandom->Uniform(x1);
+}
+
+//
+double Geant4Random::uniform(double x1, double x2)  {
+  return gRandom->Uniform(x1,x2);
+}
+
diff --git a/DDG4/src/Geant4SensDetAction.cpp b/DDG4/src/Geant4SensDetAction.cpp
index 7f190989d..287d7978a 100644
--- a/DDG4/src/Geant4SensDetAction.cpp
+++ b/DDG4/src/Geant4SensDetAction.cpp
@@ -217,8 +217,8 @@ Geant4SensDetActionSequence::Geant4SensDetActionSequence(Geant4Context* context,
   m_needsControl = true;
   context->sensitiveActions().insert(name(), this);
   /// Update the sensitive detector type, so that the proper instance is created
-  Geometry::SensitiveDetector sd = context->lcdd().sensitiveDetector(nam);
-  sd.setType("Geant4SensDet");
+  m_sensitive = context->lcdd().sensitiveDetector(nam);
+  m_sensitive.setType("Geant4SensDet");
   InstanceCount::increment(this);
 }
 
@@ -334,7 +334,7 @@ void Geant4SensDetActionSequence::begin(G4HCofThisEvent* hce) {
   m_actors(ContextUpdate(context()));
   for (size_t count = 0; count < m_collections.size(); ++count) {
     const std::pair<string, create_t>& cr = m_collections[count];
-    G4VHitsCollection* c = (*cr.second)(name(), cr.first);
+    Geant4HitCollection* c = (*cr.second)(name(), cr.first, m_sensitive);
     int id = m_detector->GetCollectionID(count);
     m_hce->AddHitsCollection(id, c);
   }
diff --git a/DDG4/src/Geant4TestActions.cpp b/DDG4/src/Geant4TestActions.cpp
index dae7a52e5..ef0eaf0b0 100644
--- a/DDG4/src/Geant4TestActions.cpp
+++ b/DDG4/src/Geant4TestActions.cpp
@@ -61,7 +61,7 @@ Geant4TestGeneratorAction::~Geant4TestGeneratorAction() {
 
 /// Callback to generate primary particles
 void Geant4TestGeneratorAction::operator()(G4Event* evt)  {
-  PRINT(name(), "%s> calling Geant4TestGeneratorAction(event_id=%d Context: run=%p evt=%p)", 
+  PRINT("%s> calling Geant4TestGeneratorAction(event_id=%d Context: run=%p evt=%p)", 
 	m_type.c_str(), evt->GetEventID(), &context()->run(), &context()->event());
 }
 
@@ -78,25 +78,25 @@ Geant4TestRunAction::~Geant4TestRunAction() {
 
 /// begin-of-run callback
 void Geant4TestRunAction::begin(const G4Run* run) {
-  PRINT(name(), "%s> calling begin(run_id=%d,num_event=%d Context:%p)", m_type.c_str(), run->GetRunID(),
+  PRINT("%s> calling begin(run_id=%d,num_event=%d Context:%p)", m_type.c_str(), run->GetRunID(),
 	run->GetNumberOfEventToBeProcessed(), &context()->run());
 }
 
 /// End-of-run callback
 void Geant4TestRunAction::end(const G4Run* run) {
-  PRINT(name(), "%s> calling end(run_id=%d, num_event=%d Context:%p)", 
+  PRINT("%s> calling end(run_id=%d, num_event=%d Context:%p)", 
 	m_type.c_str(), run->GetRunID(), run->GetNumberOfEvent(), &context()->run());
 }
 
 /// begin-of-event callback
 void Geant4TestRunAction::beginEvent(const G4Event* evt) {
-  PRINT(name(), "%s> calling beginEvent(event_id=%d Context: run=%p evt=%p)", 
+  PRINT("%s> calling beginEvent(event_id=%d Context: run=%p evt=%p)", 
 	m_type.c_str(), evt->GetEventID(), &context()->run(), &context()->event());
 }
 
 /// End-of-event callback
 void Geant4TestRunAction::endEvent(const G4Event* evt) {
-  PRINT(name(), "%s> calling endEvent(event_id=%d Context: run=%p evt=%p)", 
+  PRINT("%s> calling endEvent(event_id=%d Context: run=%p evt=%p)", 
 	m_type.c_str(), evt->GetEventID(), &context()->run(), &context()->event());
 }
 
@@ -112,7 +112,7 @@ Geant4TestEventAction::~Geant4TestEventAction() {
 }
 /// begin-of-event callback
 void Geant4TestEventAction::begin(const G4Event* evt) {
-  PRINT(name(), "%s> calling begin(event_id=%d Context:  run=%p (%d) evt=%p (%d))", 
+  PRINT("%s> calling begin(event_id=%d Context:  run=%p (%d) evt=%p (%d))", 
 	m_type.c_str(), evt->GetEventID(), 
 	&context()->run(), context()->run().run().GetRunID(),
 	&context()->event(), context()->event().event().GetEventID());
@@ -120,7 +120,7 @@ void Geant4TestEventAction::begin(const G4Event* evt) {
 
 /// End-of-event callback
 void Geant4TestEventAction::end(const G4Event* evt) {
-  PRINT(name(), "%s> calling end(event_id=%d Context:  run=%p (%d) evt=%p (%d))", 
+  PRINT("%s> calling end(event_id=%d Context:  run=%p (%d) evt=%p (%d))", 
 	m_type.c_str(), evt->GetEventID(), &context()->run(), &context()->event(),
 	&context()->run(), context()->run().run().GetRunID(),
 	&context()->event(), context()->event().event().GetEventID());
@@ -128,14 +128,14 @@ void Geant4TestEventAction::end(const G4Event* evt) {
 
 /// begin-of-run callback
 void Geant4TestEventAction::beginRun(const G4Run* run) {
-  PRINT(name(), "%s> calling beginRun(run_id=%d,num_event=%d Context:%p)",
+  PRINT("%s> calling beginRun(run_id=%d,num_event=%d Context:%p)",
 	   m_type.c_str(), run->GetRunID(),
 	   run->GetNumberOfEventToBeProcessed(), &context()->run());
 }
 
 /// End-of-run callback
 void Geant4TestEventAction::endRun(const G4Run* run) {
-  PRINT(name(), "%s> calling endRun(run_id=%d, num_event=%d Context:%p)", 
+  PRINT("%s> calling endRun(run_id=%d, num_event=%d Context:%p)", 
 	   m_type.c_str(), run->GetRunID(),
 	   run->GetNumberOfEvent(), &context()->run());
 }
@@ -152,7 +152,7 @@ Geant4TestTrackAction::~Geant4TestTrackAction() {
 }
 /// Begin-of-tracking callback
 void Geant4TestTrackAction::begin(const G4Track* trk) {
-  PRINT(name(), "%s> calling begin(track=%d, parent=%d, position=(%f,%f,%f) Context: run=%p evt=%p)", 
+  PRINT("%s> calling begin(track=%d, parent=%d, position=(%f,%f,%f) Context: run=%p evt=%p)", 
 	m_type.c_str(), trk->GetTrackID(),
 	trk->GetParentID(), trk->GetPosition().x(), trk->GetPosition().y(), trk->GetPosition().z(), 
 	&context()->run(), &context()->event());
@@ -160,7 +160,7 @@ void Geant4TestTrackAction::begin(const G4Track* trk) {
 
 /// End-of-tracking callback
 void Geant4TestTrackAction::end(const G4Track* trk) {
-  PRINT(name(), "%s> calling end(track=%d, parent=%d, position=(%f,%f,%f) Context: run=%p evt=%p)", 
+  PRINT("%s> calling end(track=%d, parent=%d, position=(%f,%f,%f) Context: run=%p evt=%p)", 
 	m_type.c_str(), trk->GetTrackID(),
 	trk->GetParentID(), trk->GetPosition().x(), trk->GetPosition().y(), trk->GetPosition().z(), 
 	&context()->run(), &context()->event());
@@ -178,7 +178,7 @@ Geant4TestStepAction::~Geant4TestStepAction() {
 }
 /// User stepping callback
 void Geant4TestStepAction::operator()(const G4Step*, G4SteppingManager*) {
-  PRINT(name(), "%s> calling operator()", m_type.c_str());
+  PRINT("%s> calling operator()", m_type.c_str());
 }
 
 /// Standard constructor with initializing arguments
@@ -186,7 +186,7 @@ Geant4TestSensitive::Geant4TestSensitive(Geant4Context* c, const std::string& n,
     : Geant4Sensitive(c, n, det, lcdd), Geant4TestBase(this, "Geant4TestSensitive") {
   InstanceCount::increment(this);
   m_collectionID = defineCollection < TestHit > (n);
-  PRINT(name(), "%s> Collection ID is %d", m_type.c_str(), int(m_collectionID));
+  PRINT("%s> Collection ID is %d", m_type.c_str(), int(m_collectionID));
 }
 
 /// Default destructor
@@ -197,7 +197,7 @@ Geant4TestSensitive::~Geant4TestSensitive() {
 /// Begin-of-tracking callback
 void Geant4TestSensitive::begin(G4HCofThisEvent* hce) {
   Geant4HitCollection* c = collectionByID(m_collectionID);
-  PRINT(name(), "%s> calling begin(num_coll=%d, coll=%s Context: run=%p evt=%p)", 
+  PRINT("%s> calling begin(num_coll=%d, coll=%s Context: run=%p evt=%p)", 
 	   m_type.c_str(), hce->GetNumberOfCollections(),
 	c ? c->GetName().c_str() : "None", &context()->run(), &context()->event());
 }
@@ -205,7 +205,7 @@ void Geant4TestSensitive::begin(G4HCofThisEvent* hce) {
 /// End-of-tracking callback
 void Geant4TestSensitive::end(G4HCofThisEvent* hce) {
   Geant4HitCollection* c = collection(m_collectionID);
-  PRINT(name(), "%s> calling end(num_coll=%d, coll=%s Context: run=%p evt=%p)", 
+  PRINT("%s> calling end(num_coll=%d, coll=%s Context: run=%p evt=%p)", 
 	m_type.c_str(), hce->GetNumberOfCollections(),
 	c ? c->GetName().c_str() : "None", &context()->run(), &context()->event());
 }
@@ -213,7 +213,7 @@ void Geant4TestSensitive::end(G4HCofThisEvent* hce) {
 /// Method for generating hit(s) using the information of G4Step object.
 bool Geant4TestSensitive::process(G4Step* step, G4TouchableHistory*) {
   Geant4HitCollection* c = collection(m_collectionID);
-  PRINT(name(), "%s> calling process(track=%d, dE=%f, dT=%f len=%f, First,last in Vol=(%c,%c), coll=%s Context: run=%p evt=%p)",
+  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(), 
 	   step->GetTotalEnergyDeposit(), step->GetDeltaTime(),
 	   step->GetStepLength(), step->IsFirstStepInVolume() ? 'Y' : 'N', 
diff --git a/DDG4/src/Geant4Vertex.cpp b/DDG4/src/Geant4Vertex.cpp
new file mode 100644
index 000000000..ee5658ccb
--- /dev/null
+++ b/DDG4/src/Geant4Vertex.cpp
@@ -0,0 +1,61 @@
+// $Id: Geant4Hits.cpp 513 2013-04-05 14:31:53Z gaede $
+//====================================================================
+//  AIDA Detector description implementation for LCD
+//--------------------------------------------------------------------
+//
+//  Author     : M.Frank
+//
+//====================================================================
+
+// Framework include files
+#include "DD4hep/Printout.h"
+#include "DD4hep/InstanceCount.h"
+#include "DDG4/Geant4Vertex.h"
+
+using namespace DD4hep;
+using namespace DD4hep::Simulation;
+
+/// Default destructor
+VertexExtension::~VertexExtension() {
+}
+
+/// Copy constructor
+Geant4Vertex::Geant4Vertex(const Geant4Vertex& c)
+  : ref(1), x(c.x), y(c.y), z(c.z), time(c.time), out(c.out), in(c.in)
+{
+  InstanceCount::increment(this);
+}
+
+/// Default constructor
+Geant4Vertex::Geant4Vertex()
+  : ref(1), x(0), y(0), z(0), time(0)
+{
+  InstanceCount::increment(this);
+}
+
+/// Default destructor
+Geant4Vertex::~Geant4Vertex()  {
+  InstanceCount::decrement(this);
+}
+
+/// Assignment operator
+Geant4Vertex& Geant4Vertex::operator=(const Geant4Vertex& c)   {
+  if ( this != &c )  {
+    x = c.x;
+    y = c.y;
+    z = c.z;
+    time = c.time;
+    in = c.in;
+    out = c.out;
+  }
+  return *this;
+}
+
+Geant4Vertex* Geant4Vertex::addRef()   {
+  ++ref;
+  return this;
+}
+
+void Geant4Vertex::release()  {
+  if ( --ref <= 0 ) delete this;
+}
diff --git a/UtilityApps/src/run_plugin.h b/UtilityApps/src/run_plugin.h
index 48a40eeec..4dc37b4f3 100644
--- a/UtilityApps/src/run_plugin.h
+++ b/UtilityApps/src/run_plugin.h
@@ -28,7 +28,7 @@ using namespace DD4hep::Geometry;
 //______________________________________________________________________________
 namespace {
 
-  LCDD& dd4hep_instance(const char* name="") {
+  LCDD& dd4hep_instance(const char* /* name */ ="") {
 #if 0
 #include "Reflex/PluginService.h"
     try {
diff --git a/doc/release.notes b/doc/release.notes
index 05774538e..bfa80c226 100644
--- a/doc/release.notes
+++ b/doc/release.notes
@@ -4,6 +4,19 @@ DD4hep  ----  Release Notes
 =================================
 
 
+2014/08/15 Markus Frank
+-----------------------
+  - DDG4: Impreoved LCIO handling for DDG4
+  - DDG4: Input handling:
+    - LCIO input file reading with multiple *independent* inputs
+      to support overlay, multiple interactions, etc.
+    - Primary verex smearing independent for each input
+    - Primary vertex boosts independent for each input
+  - DDG4: Output handling
+    - MC Particle handling
+    - Improved MC truth handling for produced Hits.
+      Still needs revisiting.
+
  --------
 | v00-10 |  
  --------   
-- 
GitLab