diff --git a/DDCore/include/DD4hep/Primitives.h b/DDCore/include/DD4hep/Primitives.h
index df05dd66d2bae20782cdc645fad14616210ce9da..c91bf84fae8e1e6f210eaca9af511651dff9288d 100644
--- a/DDCore/include/DD4hep/Primitives.h
+++ b/DDCore/include/DD4hep/Primitives.h
@@ -241,9 +241,15 @@ namespace DD4hep {
     void set(const T& m)   {
       mask |= m;
     }
+    void clear(const T& m)   {
+      mask &= ~m;
+    }
     bool isSet(const T& m)  const {
       return (mask&m) == m;
     }
+    bool anySet(const T& m)  const {
+      return (mask&m) != 0;
+    }
     bool testBit(int bit) const  {
       T m = T(1)<<bit;
       return isSet(m);
diff --git a/DDG4/examples/CLICSidSimu.py b/DDG4/examples/CLICSidSimu.py
index 267958c7f4deb0117497b3e5be9ba044c81b2621..2be162aebb71568408a9b57f9436e1ea7d451981 100644
--- a/DDG4/examples/CLICSidSimu.py
+++ b/DDG4/examples/CLICSidSimu.py
@@ -52,56 +52,63 @@ def run():
   gen = DDG4.GeneratorAction(kernel,"Geant4GeneratorActionInit/GenerationInit")
   kernel.generatorAction().adopt(gen)
 
+  #VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
   """
   Generation of isotrope tracks using the DDG4 partcle gun:
-  """
+
   # Setup particle gun
   gun = simple.setupGun('Gun','pi-',energy=10*GeV,isotrop=True,multiplicity=3)
   gun.OutputLevel = 5 # generator_output_level
+  gun.Mask = 1
+  #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  """
 
-  gen = DDG4.GeneratorAction(kernel,"Geant4PrimaryConverter/GunConverter");
-  gen.OutputLevel = 5 # generator_output_level
-  kernel.generatorAction().adopt(gen)
-
+  #VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
   """
   Generation of isotrope tracks of a given multiplicity with overlay:
 
   # First particle generator: pi+
   gen = DDG4.GeneratorAction(kernel,"Geant4IsotropeGenerator/IsotropPi+");
-  gen.particle = 'pi+'
-  gen.energy = 100 * GeV
-  gen.multiplicity = 2
-  gen.mask = 1
+  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)
+  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
+  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)
+  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)
+  #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   """
 
+  #VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
   """
   Generation of primary particles from LCIO input files
+  """
 
   # First particle file reader
   gen = DDG4.GeneratorAction(kernel,"LCIOInputAction/LCIO1");
   gen.Input = "LCIOStdHepReader|/home/frankm/SW/data/e2e2nn_gen_1343_1.stdhep"
-  gen.OutputLevel = generator_output_level
+  #gen.Input = "LCIOStdHepReader|/home/frankm/SW/data/qq_gen_128_999.stdhep"
+  gen.Input = "LCIOStdHepReader|/home/frankm/SW/data/smuonLR_PointK_3TeV_BS_noBkg_run0001.stdhep"
+  gen.Input = "LCIOStdHepReader|/home/frankm/SW/data/bbbb_3TeV.stdhep"
+  gen.OutputLevel = 4 # generator_output_level
   gen.Mask = 1
   gen.MomentumScale = 0.1
   kernel.generatorAction().adopt(gen)
@@ -116,7 +123,8 @@ def run():
   # 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.Input = "LCIOStdHepReader|/home/frankm/SW/data/bbnn_3TeV_01.stdhep"
+  gen.OutputLevel = 4 # generator_output_level
   gen.Mask = 2
   gen.MomentumScale = 0.1
   kernel.generatorAction().adopt(gen)
@@ -127,24 +135,24 @@ def run():
   gen.Offset = (20*mm, 10*mm, 10*mm, 0*ns)
   gen.Sigma = (2*mm, 1*mm, 1*mm, 0*ns)
   kernel.generatorAction().adopt(gen)
+  #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
   # Merge all existing interaction records
   gen = DDG4.GeneratorAction(kernel,"Geant4InteractionMerger/InteractionMerger")
-  gen.OutputLevel = generator_output_level
+  gen.OutputLevel = 4 #generator_output_level
   kernel.generatorAction().adopt(gen)
 
   # Finally generate Geant4 primaries
   gen = DDG4.GeneratorAction(kernel,"Geant4PrimaryHandler/PrimaryHandler")
-  gen.OutputLevel = generator_output_level
+  gen.OutputLevel = 4 #generator_output_level
   kernel.generatorAction().adopt(gen)
-  """
 
   # 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.OutputLevel = 4 # generator_output_level
   part.enableUI()
   user = DDG4.Action(kernel,"Geant4UserParticleHandler/UserParticleHandler")
   part.adopt(user)
diff --git a/DDG4/include/DDG4/Geant4InteractionMerger.h b/DDG4/include/DDG4/Geant4InteractionMerger.h
index 90e2a16909976f23276ea6738f9dae674b19309f..a71fa1a743016d300ddfbc77df349599fdde691a 100644
--- a/DDG4/include/DDG4/Geant4InteractionMerger.h
+++ b/DDG4/include/DDG4/Geant4InteractionMerger.h
@@ -22,12 +22,17 @@ namespace DD4hep {
    */
   namespace Simulation {
 
+    // Forward declarations
+    class Geant4PrimaryInteraction;
+
     /** Geant4Action to convert the particle information to Geant4
      *
      *  @author  M.Frank
      *  @version 1.0
      */
     class Geant4InteractionMerger : public Geant4GeneratorAction    {
+      /// Append input interaction to global output
+      void appendInteraction(Geant4PrimaryInteraction* output, Geant4PrimaryInteraction* input);
     public:
       /// Standard constructor
       Geant4InteractionMerger(Geant4Context* context, const std::string& nam);
diff --git a/DDG4/include/DDG4/Geant4Particle.h b/DDG4/include/DDG4/Geant4Particle.h
index 0b023766c58f475729b6c7096430a3a4a09a8e02..5382f8ceff1a4bd470fd9a8df40d01270d2cea02 100644
--- a/DDG4/include/DDG4/Geant4Particle.h
+++ b/DDG4/include/DDG4/Geant4Particle.h
@@ -62,8 +62,9 @@ namespace DD4hep {
       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_GENERATOR       =        // Particle comes from generator
+      (  G4PARTICLE_GEN_EMPTY+G4PARTICLE_GEN_STABLE+
+	 G4PARTICLE_GEN_DECAYED+G4PARTICLE_GEN_DOCUMENTATION  ),
       G4PARTICLE_GEN_STATUS          = 0x3FF, // Mask for generator status (bit 0...9)
 
       // Simulation status of a given particle
@@ -94,7 +95,7 @@ namespace DD4hep {
       typedef std::set<int> Particles;
       /// Reference counter
       int ref;           //! not persistent
-      int id, g4Parent, reason, usermask;
+      int id, g4Parent, reason, mask;
       int steps, secondaries, pdgID;
       int status, colorFlow[2];
       char charge, _spare[3];
diff --git a/DDG4/include/DDG4/Geant4ParticleGun.h b/DDG4/include/DDG4/Geant4ParticleGun.h
index 52fb2ec7509cd7066a9c973e89b6d10ad133db8e..253ccca46c1db45fd160b0ff20e4c254a71995fb 100644
--- a/DDG4/include/DDG4/Geant4ParticleGun.h
+++ b/DDG4/include/DDG4/Geant4ParticleGun.h
@@ -14,7 +14,6 @@
 
 // Forward declarations
 class G4ParticleDefinition;
-class G4ParticleGun;
 
 /*
  *   DD4hep namespace declaration
@@ -34,22 +33,23 @@ namespace DD4hep {
      */
     class Geant4ParticleGun: public Geant4GeneratorAction {
     protected:
-      /// Position and shooting direction of the gun
+      /// Property: Position and shooting direction of the gun
       ROOT::Math::XYZVector m_position, m_direction;
-      /// Pointer to geant4 particle definition
-      G4ParticleDefinition* m_particle;
-      /// Pointer to the particle gun itself
-      G4ParticleGun* m_gun;
-      /// Particle energy
+      /// Property: Particle energy
       double m_energy;
-      /// Particle name
+      /// Property: Particle name
       std::string m_particleName;
-      /// Desired multiplicity of the particles to be shot
+      /// Property: Desired multiplicity of the particles to be shot
       int m_multiplicity;
+      /// Property: Interaction mask indentifier
+      int m_mask;
+      /// Property: Isotrope particles?
+      bool m_isotrop;
+
+      /// Pointer to geant4 particle definition
+      G4ParticleDefinition* m_particle;
       /// Shot number in sequence
       int m_shotNo;
-      /// Isotrope particles?
-      bool m_isotrop;
     public:
       /// Standard constructor
       Geant4ParticleGun(Geant4Context* context, const std::string& name);
diff --git a/DDG4/include/DDG4/Geant4Primary.h b/DDG4/include/DDG4/Geant4Primary.h
index 3bbf70131b28a0c5a16c228d4a011e4b37bd28e6..98628ebb4606357da7f3e84b94385771b73e844d 100644
--- a/DDG4/include/DDG4/Geant4Primary.h
+++ b/DDG4/include/DDG4/Geant4Primary.h
@@ -103,6 +103,8 @@ namespace DD4hep {
       int nextPID();
       /// Set the next PID value
       void setNextPID(int value);
+      /// Apply mask to all contained vertices (max. 1) and particles
+      bool applyMask();
     };
 
     /// Class modelling a complete primary event with multiple interactions
diff --git a/DDG4/include/DDG4/Geant4PrimaryConverter.h b/DDG4/include/DDG4/Geant4PrimaryConverter.h
deleted file mode 100644
index 9fea3351202b49a27523ce39749ed8816aaaeb69..0000000000000000000000000000000000000000
--- a/DDG4/include/DDG4/Geant4PrimaryConverter.h
+++ /dev/null
@@ -1,47 +0,0 @@
-//====================================================================
-//  AIDA Detector description implementation
-//--------------------------------------------------------------------
-//
-//  Author     : M.Frank
-//
-//====================================================================
-#ifndef DD4HEP_DDG4_GEANT4PRIMARYCONVERTER_H
-#define DD4HEP_DDG4_GEANT4PRIMARYCONVERTER_H
-
-// Framework include files
-#include "DDG4/Geant4GeneratorAction.h"
-#include "Math/Vector3D.h"
-
-/*
- *   DD4hep namespace declaration
- */
-namespace DD4hep {
-
-  /*
-   *   Simulation namespace declaration
-   */
-  namespace Simulation {
-
-    /** @class Geant4Primaryconverter Geant4Primaryconverter.h DDG4/Geant4Primaryconverter.h
-     *
-     * Convert G4PrimaryVertix and G4PrimaryParticle constructs into 
-     * Geant4Primary records. Required for native G4 particle guns.
-     *
-     * @author  M.Frank
-     * @version 1.0
-     */
-    class Geant4PrimaryConverter: public Geant4GeneratorAction {
-    protected:
-      /// Interaction mask
-      int m_mask;
-    public:
-      /// Standard constructor
-      Geant4PrimaryConverter(Geant4Context* context, const std::string& name);
-      /// Default destructor
-      virtual ~Geant4PrimaryConverter();
-      /// Callback to generate primary particles
-      virtual void operator()(G4Event* event);
-    };
-  }    // End namespace Simulation
-}      // End namespace DD4hep
-#endif /* DD4HEP_DDG4_GEANT4PRIMARYCONVERTER_H  */
diff --git a/DDG4/include/DDG4/Geant4Vertex.h b/DDG4/include/DDG4/Geant4Vertex.h
index 3ad19da25b892c4cb5b67001fef6711580e7feaa..222ea5752fea441eb1d76d36af110f071ec868af 100644
--- a/DDG4/include/DDG4/Geant4Vertex.h
+++ b/DDG4/include/DDG4/Geant4Vertex.h
@@ -44,6 +44,8 @@ namespace DD4hep {
       typedef std::set<int> Particles;
       /// Reference counter
       int ref;            //! not persistent
+      /// Vertex mask to associate particles from collision
+      int mask;
       /// Vertex data
       double x,y,z,time;
       /// The list of outgoing particles
diff --git a/DDG4/lcio/LCIOInputAction.cpp b/DDG4/lcio/LCIOInputAction.cpp
index 45fb86588709bd071ac56229731d760e518646b0..b952b17b155f54ab058c7a5f4b9c998283635dae 100644
--- a/DDG4/lcio/LCIOInputAction.cpp
+++ b/DDG4/lcio/LCIOInputAction.cpp
@@ -15,16 +15,25 @@
 #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"
+
+#include "G4Event.hh"
 
 using namespace std;
 using namespace DD4hep::Simulation;
-
 typedef DD4hep::ReferenceBitMask<int> PropertyMask;
 
+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;
+  }
+}
+
 /// Standard constructor
 LCIOInputAction::LCIOInputAction(Geant4Context* context, const string& name)
   : Geant4GeneratorAction(context,name), m_reader(0)
@@ -81,36 +90,14 @@ EVENT::LCCollection* LCIOInputAction::readParticles(int which)  {
   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());
+  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;
+  vector<EVENT::MCParticle*>  mcpcoll;
 
   prim->add(m_mask, inter);
   // check if there is at least one particle
@@ -120,21 +107,25 @@ void LCIOInputAction::operator()(G4Event* event)   {
   // 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);
+  Geant4Vertex* vtx = new Geant4Vertex();
+  vtx->x = 0;
+  vtx->y = 0;
+  vtx->z = 0;
+  vtx->time = 0;
+  inter->vertices.insert(make_pair(m_mask,vtx));
   // build collection of MCParticles
   G4ParticleTable*      tab = G4ParticleTable::GetParticleTable();
   for(int i=0; i<NHEP; ++i )   {
     EVENT::MCParticle* mcp = mcpcoll[i];
-    Geant4ParticleHandle p(col[i]);
+    Geant4ParticleHandle p(new Particle(i));
     const double mom_scale = m_momScale;
     const double *mom   = mcp->getMomentum();
     const double *vsx   = mcp->getVertex();
@@ -143,9 +134,6 @@ void LCIOInputAction::operator()(G4Event* event)   {
     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->charge       = int(mcp->getCharge()*3.0);
     p->psx          = mom_scale*mom[0]*GeV;
@@ -174,7 +162,6 @@ void LCIOInputAction::operator()(G4Event* event)   {
       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);
@@ -187,158 +174,15 @@ void LCIOInputAction::operator()(G4Event* event)   {
     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);
+    if ( par.size() == 0 )  {
+      if ( status.isSet(G4PARTICLE_GEN_EMPTY) || status.isSet(G4PARTICLE_GEN_DOCUMENTATION) )
+	vtx->in.insert(p->id);  // Beam particles and primary quarks etc.
+      else
+	vtx->out.insert(p->id); // Stuff, to be given to Geant4 together with daughters
+    }
     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"
diff --git a/DDG4/lcio/LCIOInputAction.h b/DDG4/lcio/LCIOInputAction.h
index 9014f266cf605774bdc196913113e77250a1cc61..36e9c3d246e552b41bc95733b2a58ea4fcfe7088 100644
--- a/DDG4/lcio/LCIOInputAction.h
+++ b/DDG4/lcio/LCIOInputAction.h
@@ -78,8 +78,6 @@ namespace DD4hep  {
       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 */
diff --git a/DDG4/plugins/Geant4Factories.cpp b/DDG4/plugins/Geant4Factories.cpp
index 899f3b1c37d57635641f200759f3ab213c03da91..e4cfc7fa9cb232f6537dbdd3ddc7012d914b2f44 100644
--- a/DDG4/plugins/Geant4Factories.cpp
+++ b/DDG4/plugins/Geant4Factories.cpp
@@ -91,10 +91,6 @@ DECLARE_GEANT4ACTION(Geant4InteractionMerger)
 #include "DDG4/Geant4PrimaryHandler.h"
 DECLARE_GEANT4ACTION(Geant4PrimaryHandler)
 
-//=============================
-#include "DDG4/Geant4PrimaryConverter.h"
-DECLARE_GEANT4ACTION(Geant4PrimaryConverter)
-
 //=============================
 #include "DDG4/Geant4TestActions.h"
 namespace DD4hep {  namespace Simulation   {
diff --git a/DDG4/src/Geant4InteractionMerger.cpp b/DDG4/src/Geant4InteractionMerger.cpp
index e8b4489ae11ea0efef49115cabadf5c9c476981b..840c7efcc157c1486317cdb9dd562fd39e2a8831 100644
--- a/DDG4/src/Geant4InteractionMerger.cpp
+++ b/DDG4/src/Geant4InteractionMerger.cpp
@@ -58,15 +58,22 @@ void rebaseVertices(Geant4PrimaryInteraction::VertexMap& vertices, int part_offs
   }
 }
 
-void appendInteraction(Geant4PrimaryInteraction* output, Geant4PrimaryInteraction* input)   {
+/// Append input interaction to global output
+void Geant4InteractionMerger::appendInteraction(Geant4PrimaryInteraction* output, Geant4PrimaryInteraction* input)   {
   Geant4PrimaryInteraction::ParticleMap::iterator ip, ipend;
   for( ip=input->particles.begin(), ipend=input->particles.end(); ip != ipend; ++ip )  {
     Geant4Particle* p = (*ip).second;
     output->particles.insert(make_pair(p->id,p->addRef()));
   }
-  Geant4PrimaryInteraction::VertexMap::iterator 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()));
+  Geant4PrimaryInteraction::VertexMap::iterator ivfnd, iv, ivend;
+  for( iv=input->vertices.begin(), ivend=input->vertices.end(); iv != ivend; ++iv )   {
+    ivfnd = output->vertices.find((*iv).second->mask);
+    if ( ivfnd != output->vertices.end() )   {
+      abortRun("Duplicate primary interaction identifier!",
+	       "Cannot handle 2 interactions with identical identifiers!");
+    }
+    output->vertices.insert(make_pair((*iv).second->mask,(*iv).second->addRef()));
+  }
 }
 
 /// Event generation action callback
@@ -76,11 +83,15 @@ void Geant4InteractionMerger::operator()(G4Event* /* event */)  {
   Geant4PrimaryEvent* evt = context()->event().extension<Geant4PrimaryEvent>();
   Interaction* output = context()->event().extension<Interaction>();
   Interactions inter  = evt->interactions();
-  int particle_offset = 0, vertex_offset = 0;
+  int particle_offset = 0;
 
   for(Interactions::const_iterator i=inter.begin(); i != inter.end(); ++i)  {
     Interaction* interaction = *i;
-    vertex_offset = particle_offset;
+    int vertex_offset = particle_offset;
+    if ( !interaction->applyMask() )   {
+      abortRun("Found single interaction with multiple primary vertices!",
+	       "Cannot merge individual interactions with more than one primary!");
+    }
     rebaseParticles(interaction->particles,particle_offset);
     rebaseVertices(interaction->vertices,vertex_offset);
     appendInteraction(output,interaction);
diff --git a/DDG4/src/Geant4InteractionVertexSmear.cpp b/DDG4/src/Geant4InteractionVertexSmear.cpp
index 6a2c562f0572200a13cac1652d4397cb667a0ce7..68a0f824fd121fd21c8cd3f5aa1a7b3d245a22b6 100644
--- a/DDG4/src/Geant4InteractionVertexSmear.cpp
+++ b/DDG4/src/Geant4InteractionVertexSmear.cpp
@@ -56,7 +56,9 @@ void Geant4InteractionVertexSmear::operator()(G4Event*) {
     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);
+    print("+++ Smearing primary vertex for interaction type %d (%d Vertices, %d particles) "
+	  "by (%+.2e mm, %+.2e mm, %+.2e mm, %+.2e ns)",
+	  m_mask,int(inter->vertices.size()),int(inter->particles.size()),dx,dy,dz,dt);
 
     // Now move begin and end-vertex of all primary vertices accordingly
     for(iv=inter->vertices.begin(); iv != inter->vertices.end(); ++iv)  {
diff --git a/DDG4/src/Geant4IsotropeGenerator.cpp b/DDG4/src/Geant4IsotropeGenerator.cpp
index bd6d4ef6412ee3a3eec0ff5242ce8cf81612fa10..dc4ef90f711d3ae82ad666a5dc8f8ee3f22e239a 100644
--- a/DDG4/src/Geant4IsotropeGenerator.cpp
+++ b/DDG4/src/Geant4IsotropeGenerator.cpp
@@ -32,10 +32,10 @@ Geant4IsotropeGenerator::Geant4IsotropeGenerator(Geant4Context* context, const s
 {
   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);
+  declareProperty("Particle",      m_particleName = "e-");
+  declareProperty("Energy",        m_energy = 50 * MeV);
+  declareProperty("Multiplicity",  m_multiplicity = 1);
+  declareProperty("Mask",          m_mask = 0);
 }
 
 /// Default destructor
@@ -61,6 +61,7 @@ void Geant4IsotropeGenerator::operator()(G4Event*) {
   prim->add(m_mask, inter);
 
   Geant4Vertex* vtx = new Geant4Vertex();
+  vtx->mask = m_mask;
   inter->vertices.insert(make_pair(inter->vertices.size(),vtx));
   for(int i=0; i<m_multiplicity; ++i)   {
     double phi = 2*M_PI*rnd.rndm();
@@ -72,11 +73,8 @@ void Geant4IsotropeGenerator::operator()(G4Event*) {
 
     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->mask       = m_mask;
     p->pdgID      = m_particle->GetPDGEncoding();
     p->definition = m_particle;
     p->psx        = x1*momentum;
diff --git a/DDG4/src/Geant4Particle.cpp b/DDG4/src/Geant4Particle.cpp
index bd2953641906fa007ad96e61b0c0857136e46f8f..cb70c4434cad0a5a2fda90cf5036da0b3daffebf 100644
--- a/DDG4/src/Geant4Particle.cpp
+++ b/DDG4/src/Geant4Particle.cpp
@@ -27,7 +27,7 @@ ParticleExtension::~ParticleExtension() {
 
 /// Copy constructor
 Geant4Particle::Geant4Particle(const Geant4Particle& c)
-  : ref(1), id(c.id), g4Parent(c.g4Parent), reason(c.reason), usermask(c.usermask),
+  : ref(1), id(c.id), g4Parent(c.g4Parent), reason(c.reason), mask(c.mask),
     steps(c.steps), secondaries(c.secondaries), pdgID(c.pdgID),
     status(c.status), charge(0),
     vsx(c.vsx), vsy(c.vsy), vsz(c.vsz), 
@@ -48,7 +48,7 @@ Geant4Particle::Geant4Particle(const Geant4Particle& c)
 
 /// Default constructor
 Geant4Particle::Geant4Particle()
-  : ref(1), id(0), g4Parent(0), reason(0), usermask(0), 
+  : ref(1), id(0), g4Parent(0), reason(0), mask(0), 
     steps(0), secondaries(0), pdgID(0),
     status(0), charge(0),
     vsx(0.0), vsy(0.0), vsz(0.0), 
@@ -65,7 +65,7 @@ Geant4Particle::Geant4Particle()
 
 /// Constructor with ID initialization
 Geant4Particle::Geant4Particle(int part_id)
-  : ref(1), id(part_id), g4Parent(0), reason(0), usermask(0), 
+  : ref(1), id(part_id), g4Parent(0), reason(0), mask(0), 
     steps(0), secondaries(0), pdgID(0),
     status(0), charge(0),
     vsx(0.0), vsy(0.0), vsz(0.0), 
@@ -99,7 +99,7 @@ Geant4Particle& Geant4Particle::get_data(Geant4Particle& c)   {
     id = c.id; 
     g4Parent    = c.g4Parent;
     reason      = c.reason; 
-    usermask    = c.usermask;
+    mask        = c.mask;
     status      = c.status;
     charge      = c.charge;
     steps       = c.steps; 
@@ -178,8 +178,10 @@ std::string Geant4ParticleHandle::particleType() const   {
 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";
+  else if ( particle->status&G4PARTICLE_GEN_EMPTY ) return "Gen.Empty";
+  else if ( particle->status&G4PARTICLE_GEN_STABLE ) return "Gen.Stable";
+  else if ( particle->status&G4PARTICLE_GEN_DECAYED ) return "Gen.Decay";
+  else if ( particle->status&G4PARTICLE_GEN_DOCUMENTATION ) return "Gen.DOC";
   return "???";
 }
 
@@ -240,7 +242,7 @@ void Geant4ParticleHandle::dump2(int level, const std::string& src, const char*
   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 "
+	   "+++ %s %4d G4:%4d [%-12s,%8s] reason:%8d "
 	   "E:%+.2e in record:%s  #Par:%3d%-5s #Dau:%3d",
 	   tag, p->id, g4id,
 	   p.particleName().c_str(),
diff --git a/DDG4/src/Geant4ParticleGun.cpp b/DDG4/src/Geant4ParticleGun.cpp
index 86af0110c390ed9039554d97d12a9b5e7d85f2cf..290545cf7f6a2842a0161f82976e578f10fde7c3 100644
--- a/DDG4/src/Geant4ParticleGun.cpp
+++ b/DDG4/src/Geant4ParticleGun.cpp
@@ -12,10 +12,10 @@
 #include "DD4hep/InstanceCount.h"
 #include "DDG4/Geant4Context.h"
 #include "DDG4/Geant4Random.h"
+#include "DDG4/Geant4Primary.h"
 #include "DDG4/Geant4ParticleGun.h"
 #include "CLHEP/Units/SystemOfUnits.h"
 
-#include "G4ParticleGun.hh"
 #include "G4ParticleTable.hh"
 #include "G4ParticleDefinition.hh"
 
@@ -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_shotNo(0)
+    m_particle(0), m_shotNo(0)
 {
   InstanceCount::increment(this);
   m_needsControl = true;
@@ -40,20 +40,19 @@ Geant4ParticleGun::Geant4ParticleGun(Geant4Context* context, const string& name)
   declareProperty("position", m_position);
   declareProperty("direction", m_direction);
   declareProperty("isotrop", m_isotrop = false);
+  declareProperty("Mask", m_mask = 1);
 }
 
 /// Default destructor
 Geant4ParticleGun::~Geant4ParticleGun() {
-  if (m_gun)
-    delete m_gun;
   InstanceCount::decrement(this);
 }
 
 /// Callback to generate primary particles
-void Geant4ParticleGun::operator()(G4Event* event) {
-  if (0 == m_gun) {
-    m_gun = new G4ParticleGun(m_multiplicity);
-  }
+void Geant4ParticleGun::operator()(G4Event* )   {
+  typedef DD4hep::ReferenceBitMask<int> PropertyMask;
+  Geant4Event& evt = context()->event();
+  Geant4PrimaryEvent* prim = evt.extension<Geant4PrimaryEvent>();
   if (0 == m_particle || m_particle->GetParticleName() != m_particleName.c_str()) {
     G4ParticleTable* particleTable = G4ParticleTable::GetParticleTable();
     m_particle = particleTable->FindParticle(m_particleName);
@@ -77,12 +76,44 @@ void Geant4ParticleGun::operator()(G4Event* event) {
     }
   }
   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_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);
-  m_gun->SetParticleEnergy(m_energy);
-  m_gun->SetParticleMomentumDirection(G4ThreeVector(m_direction.X(), m_direction.Y(), m_direction.Z()));
-  m_gun->SetParticlePosition(G4ThreeVector(m_position.X(), m_position.Y(), m_position.Z()));
-  m_gun->GeneratePrimaryVertex(event);
+
+  Geant4PrimaryInteraction* inter = new Geant4PrimaryInteraction();
+  Geant4Vertex* vtx = new Geant4Vertex();
+  inter->vertices.insert(make_pair(m_mask,vtx));
+  prim->add(m_mask, inter);
+
+  for(int i=0; i<m_multiplicity; ++i)    {
+    Geant4ParticleHandle p = new Geant4Particle(i);
+    p->reason       = 0;
+    p->pdgID        = m_particle->GetPDGEncoding();
+    p->psx          = m_direction.X()*m_energy;
+    p->psy          = m_direction.Y()*m_energy;
+    p->psz          = m_direction.Z()*m_energy;
+    p->time         = 0;
+    p->properTime   = 0;
+    p->vsx          = m_position.X();
+    p->vsy          = m_position.Y();
+    p->vsz          = m_position.Z();
+    p->vex          = m_position.X();
+    p->vey          = m_position.Y();
+    p->vez          = m_position.Z();
+    p->definition   = m_particle;
+    p->process      = 0;
+    p->spin[0]      = 0;
+    p->spin[1]      = 0;
+    p->spin[2]      = 0;
+    p->colorFlow[0] = 0;
+    p->colorFlow[0] = 0;
+    p->mass         = m_particle->GetPDGMass();
+    p->charge       = m_particle->GetPDGCharge();
+    PropertyMask status(p->status);
+    status.set(G4PARTICLE_GEN_STABLE);
+    vtx->out.insert(p->id);
+    inter->particles.insert(make_pair(p->id,p));
+    p.dump3(outputLevel()-1,name(),"+->");
+  }
   ++m_shotNo;
 }
diff --git a/DDG4/src/Geant4ParticleHandler.cpp b/DDG4/src/Geant4ParticleHandler.cpp
index c647d2ba3d85c05de67b4b561cde229c49d22c5f..2b559ff0984355c7fabaa474f8173a868097a586 100644
--- a/DDG4/src/Geant4ParticleHandler.cpp
+++ b/DDG4/src/Geant4ParticleHandler.cpp
@@ -219,7 +219,7 @@ void Geant4ParticleHandler::begin(const G4Track* track)   {
   if ( prim_part )   {
     m_currTrack.id           = prim_part->id;
     m_currTrack.reason       = prim_part->reason|reason;
-    m_currTrack.usermask     = prim_part->usermask;
+    m_currTrack.mask         = prim_part->mask;
     m_currTrack.status       = prim_part->status;
     m_currTrack.spin[0]      = prim_part->spin[0];
     m_currTrack.spin[1]      = prim_part->spin[1];
@@ -235,7 +235,7 @@ void Geant4ParticleHandler::begin(const G4Track* track)   {
   else  {
     m_currTrack.id           = m_globalParticleID;
     m_currTrack.reason       = reason;
-    m_currTrack.usermask     = 0;
+    m_currTrack.mask         = 0;
     m_currTrack.status      |= G4PARTICLE_SIM_CREATED;
     m_currTrack.spin[0]      = 0;
     m_currTrack.spin[1]      = 0;
@@ -315,7 +315,7 @@ void Geant4ParticleHandler::end(const G4Track* track)   {
     if ( ipar != m_particleMap.end() )  {
       Particle* p_par = (*ipar).second;
       p_par->daughters.insert(ph->id);
-      ph->usermask |= p_par->usermask;
+      ph->mask |= p_par->mask;
       G4ThreeVector dist(ph->vsx-p_par->vex,ph->vsy-p_par->vey,ph->vsz-p_par->vez);
       if ( dist.r() > 1e-15 )   {
 	// Set flag that the end vertex of the parent is not the start vertex of this track....
@@ -447,7 +447,8 @@ void Geant4ParticleHandler::rebaseSimulatedTracks(int )   {
     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 ( 0 == (p->status&G4PARTICLE_GEN_GENERATOR) )
+      {
       if ( p->g4Parent > 0 )  {
 	p->parents.clear();
 	p->parents.insert(equivalentTrack(p->g4Parent));  // Requires (2)
@@ -576,7 +577,7 @@ void Geant4ParticleHandler::checkConsistency()  const   {
     }
     // 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) )  {
+    if ( !mask.isSet(G4PARTICLE_PRIMARY) && !status.anySet(G4PARTICLE_GEN_GENERATOR) )  {
       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();
diff --git a/DDG4/src/Geant4ParticlePrint.cpp b/DDG4/src/Geant4ParticlePrint.cpp
index ad6aa93956cc12edfb5695bd1eac80f0ac19a991..c81c0dcbddde3af3f8057f032e15836f2d3f186b 100644
--- a/DDG4/src/Geant4ParticlePrint.cpp
+++ b/DDG4/src/Geant4ParticlePrint.cpp
@@ -65,6 +65,7 @@ void Geant4ParticlePrint::end(const G4Event* )  {
 void Geant4ParticlePrint::printParticle(const std::string& prefix, Geant4ParticleHandle p) const   {
   char equiv[32];
   PropertyMask mask(p->reason);
+  PropertyMask status(p->status);
   string proc_name = p.processName();
   string proc_type = p.processTypeName();
   int parent_id = p->parents.empty() ? -1 : *(p->parents.begin());
@@ -73,7 +74,7 @@ void Geant4ParticlePrint::printParticle(const std::string& prefix, Geant4Particl
   if ( p->parents.end() == p->parents.find(p->g4Parent) )  {
     ::snprintf(equiv,sizeof(equiv),"/%d",p->g4Parent);
   }
-  print("+++ %s ID:%7d %12s %6d%-7s %7s %3s %5d %3s %+.3e  %-4s %-7s %-3s %-3s %2d  [%s%s%s]",
+  print("+++ %s ID:%7d %12s %6d%-7s %7s %3s %5d %3s %+.3e  %-4s %-7s %-3s %-3s %2d  [%s%s%s] %c%c%c%c",
 	prefix.c_str(),
 	p->id,
 	p.particleName().c_str(),
@@ -90,7 +91,11 @@ void Geant4ParticlePrint::printParticle(const std::string& prefix, Geant4Particl
 	p.numParent(),
 	proc_name.c_str(),
 	p->process ? "/" : "",
-	proc_type.c_str()
+	proc_type.c_str(),
+	status.isSet(G4PARTICLE_GEN_EMPTY) ? 'E' : '.',
+	status.isSet(G4PARTICLE_GEN_STABLE) ? 'S' : '.',
+	status.isSet(G4PARTICLE_GEN_DECAYED) ? 'D' : '.',
+	status.isSet(G4PARTICLE_GEN_DOCUMENTATION) ? 'd' : '.'
 	);
 }
 
diff --git a/DDG4/src/Geant4Primary.cpp b/DDG4/src/Geant4Primary.cpp
index bfd24d1b1604779470204c426b9a3f7be64ae229..38e8dbf0fca38fe23f30a3cd70302083ae416d19 100644
--- a/DDG4/src/Geant4Primary.cpp
+++ b/DDG4/src/Geant4Primary.cpp
@@ -62,6 +62,21 @@ void Geant4PrimaryInteraction::setNextPID(int new_value)   {
   next_particle_identifier = new_value-1;
 }
 
+/// Apply mask to all contained vertices and particles
+bool Geant4PrimaryInteraction::applyMask()   {
+  if ( vertices.size() <= 1 )  {
+    Geant4PrimaryInteraction::ParticleMap::iterator ip, ipend;
+    for( ip=particles.begin(), ipend=particles.end(); ip != ipend; ++ip )
+      (*ip).second->mask = mask;
+    
+    Geant4PrimaryInteraction::VertexMap::iterator iv, ivend;
+    for( iv=vertices.begin(), ivend=vertices.end(); iv != ivend; ++iv )
+      (*iv).second->mask = mask;
+    return true;
+  }
+  return false;
+}
+
 /// Default constructor
 Geant4PrimaryEvent::Geant4PrimaryEvent() 
 {
diff --git a/DDG4/src/Geant4PrimaryConverter.cpp b/DDG4/src/Geant4PrimaryConverter.cpp
deleted file mode 100644
index 4554a8fdf8e86db95b21ec53fdce51a9db35649a..0000000000000000000000000000000000000000
--- a/DDG4/src/Geant4PrimaryConverter.cpp
+++ /dev/null
@@ -1,101 +0,0 @@
-// $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/Geant4Primary.h"
-#include "DDG4/Geant4Context.h"
-#include "DDG4/Geant4PrimaryConverter.h"
-
-#include "G4Event.hh"
-#include "G4PrimaryVertex.hh"
-#include "G4PrimaryParticle.hh"
-
-// C/C++ include files
-#include <limits>
-
-using namespace std;
-using namespace DD4hep::Simulation;
-
-/// Standard constructor
-Geant4PrimaryConverter::Geant4PrimaryConverter(Geant4Context* context, const string& name)
-  : Geant4GeneratorAction(context, name)
-{
-  InstanceCount::increment(this);
-  declareProperty("Mask", m_mask = 1);
-  m_needsControl = true;
-}
-
-/// Default destructor
-Geant4PrimaryConverter::~Geant4PrimaryConverter() {
-  InstanceCount::decrement(this);
-}
-
-/// Callback to generate primary particles
-void Geant4PrimaryConverter::operator()(G4Event* event) {
-  typedef DD4hep::ReferenceBitMask<int> PropertyMask;
-  Geant4Event& evt = context()->event();
-  Geant4PrimaryMap* primaries = evt.extension<Geant4PrimaryMap>();
-  Geant4PrimaryEvent* prim = evt.extension<Geant4PrimaryEvent>();
-  Geant4PrimaryInteraction* inter = new Geant4PrimaryInteraction();
-  Geant4PrimaryInteraction* output = evt.extension<Geant4PrimaryInteraction>();
-  const G4Event& e = *event;
-
-  prim->add(m_mask, inter);
-  print("+++ Particle interaction converted from Geant4 primaries:");
-
-  for(int cnt=0, i=0, ni=e.GetNumberOfPrimaryVertex(); i<ni; ++i)  {
-    G4PrimaryVertex* v4 = e.GetPrimaryVertex(i);
-    Geant4Vertex* vtx = new Geant4Vertex();
-    vtx->x = v4->GetX0()*mm;
-    vtx->y = v4->GetY0()*mm;
-    vtx->z = v4->GetZ0()*mm;
-    vtx->time = v4->GetT0()*ns;
-    inter->vertices.insert(make_pair(inter->vertices.size(),vtx));
-    output->vertices.insert(make_pair(output->vertices.size(),vtx->addRef()));
-    for(int j=0, nj=v4->GetNumberOfParticle(); j<nj; ++j)  {
-      const G4PrimaryParticle* p4 = v4->GetPrimary(j);
-      Geant4ParticleHandle p = new Geant4Particle(cnt);
-      p->reason       = 0;
-      p->usermask     = 0;
-      p->pdgID        = p4->GetPDGcode();
-      p->psx          = p4->GetPx()*GeV;
-      p->psy          = p4->GetPy()*GeV;
-      p->psz          = p4->GetPz()*GeV;
-      p->time         = v4->GetT0()*ns;
-      p->properTime   = v4->GetT0()*ns;
-      p->vsx          = v4->GetX0()*mm;
-      p->vsy          = v4->GetY0()*mm;
-      p->vsz          = v4->GetZ0()*mm;
-      p->vex          = v4->GetX0()*mm;
-      p->vey          = v4->GetY0()*mm;
-      p->vez          = v4->GetZ0()*mm;
-      p->definition   = p4->GetParticleDefinition();
-      p->process      = 0;
-      p->spin[0]      = 0;
-      p->spin[1]      = 0;
-      p->spin[2]      = 0;
-      p->colorFlow[0] = 0;
-      p->colorFlow[0] = 0;
-      p->mass         = p4->GetMass();
-      p->charge       = p4->GetCharge();
-      PropertyMask status(p->status);
-      status.set(G4PARTICLE_GEN_CREATED);
-      status.set(G4PARTICLE_GEN_STABLE);
-      p.dump3(outputLevel()-1,name(),"+->");
-
-      vtx->out.insert(p->id);
-      inter->particles.insert(make_pair(p->id,p));
-      output->particles.insert(make_pair(p->id,p->addRef()));
-      primaries->primaryMap.insert(make_pair(p4,p->addRef()));
-      cnt++;
-    }
-  }
-}
diff --git a/DDG4/src/Geant4PrimaryHandler.cpp b/DDG4/src/Geant4PrimaryHandler.cpp
index f45ca9ed79b96929a075c65112b7b342fdfceb6f..4e677b3bef6403b7c207b28793659479d069cb0c 100644
--- a/DDG4/src/Geant4PrimaryHandler.cpp
+++ b/DDG4/src/Geant4PrimaryHandler.cpp
@@ -18,9 +18,13 @@
 
 #include <stdexcept>
 
+using namespace std;
 using namespace DD4hep;
 using namespace DD4hep::Simulation;
 
+typedef Geant4PrimaryInteraction Interaction;
+typedef ReferenceBitMask<int> PropertyMask;
+
 /// Standard constructor
 Geant4PrimaryHandler::Geant4PrimaryHandler(Geant4Context* context, const std::string& nam)
   : Geant4GeneratorAction(context,nam)
@@ -33,39 +37,108 @@ Geant4PrimaryHandler::~Geant4PrimaryHandler()  {
   InstanceCount::decrement(this);
 }
 
+static G4PrimaryParticle* createG4Primary(const Geant4ParticleHandle p)  {
+  G4PrimaryParticle* g4 = new G4PrimaryParticle(p->pdgID, p->psx, p->psy, p->psz);
+  g4->SetMass(p->mass);
+  return g4;
+}
+
+typedef map<Geant4Particle*,G4PrimaryParticle*> Primaries;
+Primaries getRelevant(set<int>& visited,
+						    map<int,G4PrimaryParticle*>& prim,
+						    Interaction::ParticleMap& pm, 
+						    const Geant4ParticleHandle p)  
+{
+  Primaries res;
+  visited.insert(p->id);
+  PropertyMask status(p->status);
+  if ( status.isSet(G4PARTICLE_GEN_STABLE) )  {
+    if ( prim.find(p->id) == prim.end() )  {
+      G4PrimaryParticle* p4 = createG4Primary(p);
+      prim[p->id] = p4;
+      res.insert(make_pair(p,p4));
+    }
+  }
+  else if ( p->daughters.size() > 0 )  {
+    const Geant4Particle::Particles& dau = p->daughters;
+    int first_daughter = *(dau.begin());
+    Geant4ParticleHandle dp = pm[first_daughter];
+    double me = p->mass / p.energy();
+    //  fix by S.Morozov for real != 0
+    double proper_time = fabs(dp->time-p->time) * me;
+    double proper_time_Precision =  pow(10,-DBL_DIG)*me*fmax(fabs(p->time),fabs(dp->time));
+    bool isProperTimeZero = ( proper_time <= proper_time_Precision ) ;
+    // -- remove original --- if (proper_time != 0) {
+    if ( !isProperTimeZero ) {
+      map<int,G4PrimaryParticle*>::iterator ip4 = prim.find(p->id);
+      G4PrimaryParticle* p4 = (ip4 == prim.end()) ? 0 : (*ip4).second;
+      if ( !p4 )  {
+	p4 = createG4Primary(p);
+	p4->SetProperTime(proper_time);
+	prim[p->id] = p4;
+	Primaries daughters;
+	for(Geant4Particle::Particles::const_iterator i=dau.begin(); i!=dau.end(); ++i)  {
+	  if ( visited.find(*i) == visited.end() )  {
+	    Primaries tmp = getRelevant(visited,prim,pm,pm[*i]);
+	    daughters.insert(tmp.begin(),tmp.end());
+	  }
+	}
+	for(Primaries::iterator i=daughters.begin(); i!=daughters.end(); ++i)
+	  p4->SetDaughter((*i).second);
+      }
+      res.insert(make_pair(p,p4));
+    }
+    else  {
+      for(Geant4Particle::Particles::const_iterator i=dau.begin(); i!=dau.end(); ++i)  {
+	if ( visited.find(*i) == visited.end() )  {
+	  Primaries tmp = getRelevant(visited,prim,pm,pm[*i]);
+	  res.insert(tmp.begin(),tmp.end());
+	}
+      }
+    }
+  }
+  return res;
+}
+
 /// Event generation action callback
 void Geant4PrimaryHandler::operator()(G4Event* event)  {
-  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;
+  map<int,G4PrimaryParticle*> prim;
+  set<int> visited;
 
-  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);
+  Geant4PrimaryInteraction::VertexMap::iterator ivfnd, iv, ivend;
+  for(Interaction::VertexMap::const_iterator iend=vm.end(),i=vm.begin(); i!=iend; ++i)  {
+    int num_part = 0;
+    Geant4Vertex* v = (*i).second;
+    G4PrimaryVertex* v4 = new G4PrimaryVertex(v->x,v->y,v->z,v->time);
+    event->AddPrimaryVertex(v4);
+    print("+++++ G4PrimaryVertex at (%+.2e,%+.2e,%+.2e) [mm] %+.2e [ns]",
+	  v->x/mm,v->y/mm,v->z/mm,v->time/ns);    
+    for(Geant4Vertex::Particles::const_iterator ip=v->out.begin(); ip!=v->out.end(); ++ip)  {
+      Geant4ParticleHandle p = pm[*ip];
+      if ( p->parents.size() == 0 )  {
+	Primaries relevant = getRelevant(visited,prim,pm,p);
+	for(Primaries::const_iterator j=relevant.begin(); j!= relevant.end(); ++j)  {
+	  Geant4ParticleHandle r = (*j).first;
+	  G4PrimaryParticle* p4 = (*j).second;
+	  PropertyMask reason(r->reason);
+	  reason.set(G4PARTICLE_PRIMARY);
+	  v4->SetPrimary(p4);
+	  printM1("+++ +-> G4Primary[%3d] ID:%3d type:%9d/%-12s "
+		  "Momentum:(%+.2e,%+.2e,%+.2e) [GeV] time:%+.2e [ns] #Par:%3d #Dau:%3d",
+		  num_part,r->id,r->pdgID,r.particleName().c_str(),
+		  r->psx/GeV,r->psy/GeV,r->psz/GeV,r->time/ns,
+		  int(r->parents.size()),int(r->daughters.size()));
+	  ++num_part;
+	}
       }
-      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);
+  }
+  for(map<int,G4PrimaryParticle*>::iterator i=prim.begin(); i!=prim.end(); ++i)  {
+    Geant4ParticleHandle p = pm[(*i).first];
+    primaries->primaryMap[(*i).second] = p->addRef();
   }
 }
diff --git a/DDG4/src/Geant4UIManager.cpp b/DDG4/src/Geant4UIManager.cpp
index 97ebd1d9b0900587de40a854cac3cef4754f87a4..459626226c8322aae76b43588a25e0eb120edc11 100644
--- a/DDG4/src/Geant4UIManager.cpp
+++ b/DDG4/src/Geant4UIManager.cpp
@@ -108,6 +108,6 @@ void Geant4UIManager::start() {
 
 /// Stop and release resources
 void Geant4UIManager::stop() {
-  deletePtr(m_vis);
-  deletePtr(m_ui);
+  // deletePtr(m_vis);
+  //deletePtr(m_ui);
 }
diff --git a/DDG4/src/Geant4Vertex.cpp b/DDG4/src/Geant4Vertex.cpp
index ee5658ccb3c55610b1ad55bb8ff047e07c1d53d9..d1dc57ef90358760fc813929a8fefb13e6bd06c8 100644
--- a/DDG4/src/Geant4Vertex.cpp
+++ b/DDG4/src/Geant4Vertex.cpp
@@ -21,14 +21,14 @@ 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)
+  : ref(1), mask(c.mask), 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)
+  : ref(1), mask(0), x(0), y(0), z(0), time(0)
 {
   InstanceCount::increment(this);
 }
@@ -41,6 +41,7 @@ Geant4Vertex::~Geant4Vertex()  {
 /// Assignment operator
 Geant4Vertex& Geant4Vertex::operator=(const Geant4Vertex& c)   {
   if ( this != &c )  {
+    mask = c.mask;
     x = c.x;
     y = c.y;
     z = c.z;