diff --git a/DDDigi/CMakeLists.txt b/DDDigi/CMakeLists.txt
index 35e7513a95c2d4fd92920f6ac636998ea60ebeef..8026b13af80b8e269c593e587c4ae9456793bedd 100644
--- a/DDDigi/CMakeLists.txt
+++ b/DDDigi/CMakeLists.txt
@@ -10,23 +10,16 @@
 #==========================================================================
 SET_PROPERTY(DIRECTORY . PROPERTY PACKAGE_NAME DDDigi)
 file(GLOB DDDigi_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp
+                         ${CMAKE_CURRENT_SOURCE_DIR}/src/noise/*.cpp
                          ${CMAKE_CURRENT_SOURCE_DIR}/src/segmentations/*.cpp)
 add_library(DDDigi ${DDDigi_SOURCES})
 add_library(DD4hep::DDDigi ALIAS DDDigi)
 
-## FIND_PACKAGE(GSL REQUIRED  QUIET)
-if(GSL_FOUND)
-  dd4hep_print( "|++> GSL_INCLUDE_DIR -->  ${GSL_INCLUDE_DIR}")
-  dd4hep_print( "|++> GSL_LIBRARY     -->  ${GSL_LIBRARY}")
-  dd4hep_print( "|++> GSL found. DDDigi will run multi threaded.")
-endif()
-
 target_link_libraries(DDDigi PUBLIC
-  DD4hep::DDCore Boost::boost ROOT::Core ROOT::Geom ROOT::GenVector ROOT::RIO ${GSL_LIBRARY})
+  DD4hep::DDCore Boost::boost ROOT::Core ROOT::Geom ROOT::GenVector ROOT::RIO)
 
 target_include_directories(DDDigi
   PUBLIC
-  ${GSL_INCLUDE_DIR}
   $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
   $<INSTALL_INTERFACE:include>
   )
diff --git a/DDDigi/include/DDDigi/DigiData.h b/DDDigi/include/DDDigi/DigiData.h
index 1340308930ae59a74a0595816d92fac25b0e2c2e..02c6b4804078a2ac899de672ff84dd400c4e7675 100644
--- a/DDDigi/include/DDDigi/DigiData.h
+++ b/DDDigi/include/DDDigi/DigiData.h
@@ -218,7 +218,7 @@ namespace dd4hep {
       /// Merge new deposit map onto existing map (not thread safe!)
       std::size_t merge(ParticleMapping&& updates);
       /// Add new entry to the particle mapping (not thread safe!)
-      void push(Key::key_type key, Particle&& particle);
+      void push(Key key, Particle&& particle);
     };
 
     /// Initializing constructor
@@ -275,7 +275,7 @@ namespace dd4hep {
     class DepositMapping : public std::map<CellID, EnergyDeposit>   {
     public: 
       std::string    name { };
-      Key::mask_type mask { 0x0 };
+      Key            key  { 0x0 };
 
     public: 
       /// Initializing constructor
@@ -298,8 +298,8 @@ namespace dd4hep {
     };
 
     /// Initializing constructor
-    inline DepositMapping::DepositMapping(const std::string& n, Key::mask_type m)
-      : name(n), mask(m)
+    inline DepositMapping::DepositMapping(const std::string& n, Key::mask_type mask)
+      : name(n), key(mask, n)
     {
     }
 
@@ -312,21 +312,20 @@ namespace dd4hep {
      */
     class DataSegment   {
     public:
-      using key_type = Key::key_type;
-      using container_map_t = std::map<key_type, std::any>;
+      using container_map_t = std::map<Key::key_type, std::any>;
       using iterator = container_map_t::iterator;
       using const_iterator = container_map_t::const_iterator;
 
     private:
       /// Call on failed any-casts
-      std::string invalid_cast(key_type key, const std::type_info& type)  const;
+      std::string invalid_cast(Key key, const std::type_info& type)  const;
       /// Call on failed data requests during data requests
-      std::string invalid_request(key_type key)  const;
+      std::string invalid_request(Key key)  const;
 
       /// Access data item by key
-      std::any* get_item(key_type key, bool exc);
+      std::any* get_item(Key key, bool exc);
       /// Access data item by key  (CONST)
-      const std::any* get_item(key_type key, bool exc)  const;
+      const std::any* get_item(Key key, bool exc)  const;
 
     public:
       container_map_t data;
@@ -350,62 +349,64 @@ namespace dd4hep {
 
       /** Locked operations */
       /// Emplace data item (locked)
-      bool emplace(key_type key, std::any&& data);
+      bool emplace(Key key, std::any&& data);
       /// Remove data item from segment (locked)
-      bool erase(key_type key);
+      bool erase(Key key);
       /// Remove data items from segment (locked)
-      std::size_t erase(const std::vector<key_type>& keys);
+      std::size_t erase(const std::vector<Key>& keys);
+      /// Print segment keys
+      void print_keys()   const;
       
       /** Unlocked operations */
       /// Access data as reference by key. If not existing, an exception is thrown
-      template<typename T> T& get(key_type key);
+      template<typename T> T& get(Key key);
       /// Access data as reference by key. If not existing, an exception is thrown
-      template<typename T> const T& get(key_type key)  const;
+      template<typename T> const T& get(Key key)  const;
 
       /// Access data as pointers by key. If not existing, nullptr is returned
-      template<typename T> T* pointer(key_type key);
+      template<typename T> T* pointer(Key key);
       /// Access data as pointers by key. If not existing, nullptr is returned
-      template<typename T> const T* pointer(key_type key)  const;
+      template<typename T> const T* pointer(Key key)  const;
 
       /// Access container size
-      std::size_t size()  const               { return this->data.size();    }
+      std::size_t size()  const           { return this->data.size();        }
       /// Check container if empty
-      bool        empty() const               { return this->data.empty();   }
+      bool        empty() const           { return this->data.empty();       }
       /// Begin iteration
-      iterator begin()                        { return this->data.begin();   }
+      iterator begin()                    { return this->data.begin();       }
       /// End iteration
-      iterator end()                          { return this->data.end();     }
+      iterator end()                      { return this->data.end();         }
       /// Find entry by key
-      iterator find(key_type key)             { return this->data.find(key); }
+      iterator find(Key key)              { return this->data.find(key.key); }
       /// Begin iteration (CONST)
-      const_iterator begin() const            { return this->data.begin();   }
+      const_iterator begin() const        { return this->data.begin();       }
       /// End iteration (CONST)
-      const_iterator end()   const            { return this->data.end();     }
+      const_iterator end()   const        { return this->data.end();         }
       /// Find entry by key
-      const_iterator find(key_type key) const { return this->data.find(key); }
+      const_iterator find(Key key) const  { return this->data.find(key.key); }
     };
 
     /// Access data as reference by key. If not existing, an exception is thrown
-    template<typename T> inline T& DataSegment::get(key_type key)     {
+    template<typename T> inline T& DataSegment::get(Key key)     {
       if ( T* ptr = std::any_cast<T>(this->get_item(key, true)) )
 	return *ptr;
       throw std::runtime_error(this->invalid_cast(key, typeid(T)));
     }
     /// Access data as reference by key. If not existing, an exception is thrown
-    template<typename T> inline const T& DataSegment::get(key_type key)  const   {
+    template<typename T> inline const T& DataSegment::get(Key key)  const   {
       if ( const T* ptr = std::any_cast<T>(this->get_item(key, true)) )
 	return *ptr;
       throw std::runtime_error(this->invalid_cast(key, typeid(T)));
     }
 
     /// Access data as pointers by key. If not existing, nullptr is returned
-    template<typename T> inline T* DataSegment::pointer(key_type key)     {
+    template<typename T> inline T* DataSegment::pointer(Key key)     {
       if ( T* ptr = std::any_cast<T>(this->get_item(key, false)) )
 	return ptr;
       return nullptr;
     }
     /// Access data as pointers by key. If not existing, nullptr is returned
-    template<typename T> inline const T* DataSegment::pointer(key_type key)  const   {
+    template<typename T> inline const T* DataSegment::pointer(Key key)  const   {
       if ( const T* ptr = std::any_cast<T>(this->get_item(key, false)) )
 	return ptr;
       return nullptr;
diff --git a/DDDigi/include/DDDigi/DigiSegmentationSplitter.h b/DDDigi/include/DDDigi/DigiSegmentationSplitter.h
index 163380384c68adc8ee1b4de55006846c47be0114..3c9e72a24d99e145f3bc0e5a530bd6748669eb53 100644
--- a/DDDigi/include/DDDigi/DigiSegmentationSplitter.h
+++ b/DDDigi/include/DDDigi/DigiSegmentationSplitter.h
@@ -14,52 +14,22 @@
 #define DDDIGI_DIGISEGMENTATIONSPLITTER_H
 
 // Framework include files
-#include <DDDigi/DigiActionSequence.h>
 #include <DDDigi/DigiData.h>
+#include <DDDigi/DigiEventAction.h>
+#include <DDDigi/DigiActionSequence.h>
+#include <DDDigi/DigiSegmentationTool.h>
 
 /// Namespace for the AIDA detector description toolkit
 namespace dd4hep {
 
-  /// DDSegmentation namespace declaration
-  namespace DDSegmentation {
-    class BitFieldElement;
-  }
-
   /// Namespace for the Digitization part of the AIDA detector description toolkit
   namespace digi {
 
-    class DigiSegmentContext;
+    /// Forward declarations
     class DigiSegmentAction;
+    class DigiSegmentContext;
     class DigiSegmentationSplitter;
 
-    class DigiSegmentContext  {
-    public:
-      DetElement             detector   { };
-      IDDescriptor           idspec     { };
-      const BitFieldElement* field      { nullptr };
-      uint64_t               cell_mask  { ~0x0UL };
-      uint64_t               det_mask   { 0UL };
-      uint64_t               split_mask { 0UL };
-      int32_t                offset     { 0 };
-      int32_t                width      { 0 };
-      int32_t                max_split  { 0 };
-      uint32_t               id         { 0 };
-
-    public:
-      uint32_t split_id(uint64_t cell_id)  const  {  
-	return int( (cell_id & this->split_mask) >> this->offset );
-      }
-      uint64_t cell_id(uint64_t cell_id)  const  {  
-	return (cell_id & this->cell_mask) >> this->offset;
-      }
-      const std::string& name()  const  {
-	return this->field->name();
-      }
-      const char* cname()  const  {
-	return this->field->name().c_str();
-      }
-    };
-
     /// Default base class for all Digitizer actions and derivates thereof.
     /**
      *  This is a utility class supporting properties, output and access to
@@ -78,21 +48,19 @@ namespace dd4hep {
       /// Reference to the implementation
       std::unique_ptr<internals_t> internals;
 
-      /// Main functional callback
-      virtual void execute(DigiContext& context)  const  final;
-
       /// Define standard assignments and constructors
       DDDIGI_DEFINE_ACTION_CONSTRUCTORS(DigiSegmentAction);
 
     public:
       /// Standard constructor
       DigiSegmentAction(const DigiKernel& kernel, const std::string& name);
-
       /// Default destructor
       virtual ~DigiSegmentAction();
 
       /// Main functional callback
-      std::map<Key::key_type, std::any> 
+      virtual void execute(DigiContext& context)  const  final;
+      /// Main functional callback
+      std::vector<std::pair<Key::key_type, std::any> >
 	handleSegment(DigiContext&              context,
 		      const DigiSegmentContext& segment,
 		      const DepositMapping&     deposits)  const;
@@ -108,25 +76,44 @@ namespace dd4hep {
      *  \ingroup DD4HEP_SIMULATION
      */
     class DigiSegmentationSplitter : public DigiActionSequence   {
+
     protected:
       /// Implementation declaration
       class internals_t;
       /// Reference to the implementation
       std::unique_ptr<internals_t> internals;
 
-    public:
+      /// Property: Identifier of the input repository
+      std::string m_input_id;
+      /// Property: Split element of the ID descriptor
+      std::string m_processor_type;
+      /// Name of the subdetector to be handed
+      std::string m_detector_name;
+      /// Splitter field in the segmentation description
+      std::string m_split_by;
+      /// Property: Flag if processors should be shared
+      bool        m_share_processor   { true };
+      /// Property: Input mask in the repository
+      int         m_input_mask;
+
+      /// Segmentation too instance
+      DigiSegmentationTool  m_split_tool;
+      /// Segmentation split context
+      DigiSegmentContext    m_split_context;
+
+      /// Split elements used to parallelize the processing
+      std::map<VolumeID, std::pair<DetElement, VolumeID> > m_splits;
+      /// Input data keys: depend on dd4hep::Readout and the input mask(s)
+      std::vector<Key> m_data_keys;
 
     protected:
       /// Define standard assignments and constructors
       DDDIGI_DEFINE_ACTION_CONSTRUCTORS(DigiSegmentationSplitter);
-
       /// Default destructor
       virtual ~DigiSegmentationSplitter();
 
-      /// Split actions according to the segmentation
-      //void split_segments(DigiEvent& event, DataSegment& data)  const;
-
-      void init_processors();
+      /// Initialization function
+      void initialize();
 
     public:
       /// Standard constructor
diff --git a/DDDigi/include/DDDigi/DigiSegmentationTool.h b/DDDigi/include/DDDigi/DigiSegmentationTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..8d1b1ffa74c0c5f1f8dfc7c4f2e4112fa95fea0e
--- /dev/null
+++ b/DDDigi/include/DDDigi/DigiSegmentationTool.h
@@ -0,0 +1,114 @@
+//==========================================================================
+//  AIDA Detector description implementation 
+//--------------------------------------------------------------------------
+// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
+// All rights reserved.
+//
+// For the licensing terms see $DD4hepINSTALL/LICENSE.
+// For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
+//
+// Author     : M.Frank
+//
+//==========================================================================
+#ifndef DDDIGI_DIGISEGMENTATIONTOOL_H
+#define DDDIGI_DIGISEGMENTATIONTOOL_H
+
+// Framework include files
+#include <DD4hep/Detector.h>
+#include <DD4hep/DetElement.h>
+
+/// Namespace for the AIDA detector description toolkit
+namespace dd4hep {
+
+  /// Namespace for the Digitization part of the AIDA detector description toolkit
+  namespace digi {
+
+    /// Forward declarations
+    class DigiSegmentContext;
+    class DigiSegmentationTool;
+
+    /// Segmentation split context
+    /**
+     *  
+     *  
+     *
+     *  \author  M.Frank
+     *  \version 1.0
+     *  \ingroup DD4HEP_SIMULATION
+     */
+    class DigiSegmentContext  {
+    public:
+      DetElement             detector   { };
+      IDDescriptor           idspec     { };
+      const BitFieldElement* field      { nullptr };
+      uint64_t               cell_mask  { ~0x0UL };
+      uint64_t               det_mask   { 0UL };
+      uint64_t               split_mask { 0UL };
+      int32_t                offset     { 0 };
+      int32_t                width      { 0 };
+      int32_t                max_split  { 0 };
+      uint32_t               id         { 0 };
+
+    public:
+      /// Split field name
+      const std::string& name()  const;
+      /// Split field name
+      const char* cname()  const;
+      /// Get the identifier of the cell to be split
+      uint32_t split_id(uint64_t cell_id)  const  {  
+	return int( (cell_id & this->split_mask) >> this->offset );
+      }
+      /// The CELL ID part of the identifier
+      uint64_t cell_id(uint64_t cell_id)  const  {  
+	return ( (cell_id & this->cell_mask) >> (this->offset + width) );
+      }
+      /// The identifier of the parent detector
+      uint64_t detector_id(uint64_t cell_id)  const  {  
+	return (cell_id & this->det_mask);
+      }
+    };
+
+    /// Tool to handle segmentation manipulations
+    /**
+     *  
+     *  
+     *
+     *  \author  M.Frank
+     *  \version 1.0
+     *  \ingroup DD4HEP_SIMULATION
+     */
+    class DigiSegmentationTool  {
+    public:
+      Detector&         description;
+      DetElement        detector;
+      SensitiveDetector sensitive;
+      IDDescriptor      iddescriptor;
+
+    public:
+      /// Initializing constructor
+      DigiSegmentationTool(Detector& desc);
+      /// Default destructor
+      virtual ~DigiSegmentationTool() = default;
+
+      /// Setup tool to handle a given detector of the geometry
+      void set_detector(const std::string& det_name);
+
+      /// Access the readout collection keys (mask is empty!)
+      std::vector<Key> collection_keys()   const;
+      /// Access the readout collection keys with predefined mask
+      std::vector<Key> collection_keys(Key::mask_type mask)   const;
+      /// Access the collection keys from readout structures of multiple subdetectors
+      std::vector<Key> collection_keys(const std::vector<std::string>& detectors)   const;
+      /// Access the collection keys from readout structures of multiple subdetectors
+      std::vector<Key> collection_keys(const std::vector<std::string>& detectors, Key::mask_type mask)   const;
+
+      /// Create a split context depending on the segmentation field
+      DigiSegmentContext split_context(const std::string& split_by)  const;
+
+      /// Create full set of detector segments which can be split according to the context
+      std::map<VolumeID, std::pair<DetElement, VolumeID> > 
+	split_segmentation(const std::string& split_by)  const;
+    };
+  }    // End namespace digi
+}      // End namespace dd4hep
+#endif // DDDIGI_DIGISEGMENTATIONTOOL_H
diff --git a/DDDigi/python/dddigi.py b/DDDigi/python/dddigi.py
index 53b97320a26a3f2a196b3f6ad74ea962e845a3fe..94bb896d4f2803b8e28a0f6bc77094b066b0e218 100644
--- a/DDDigi/python/dddigi.py
+++ b/DDDigi/python/dddigi.py
@@ -210,7 +210,7 @@ def Synchronize(kernel, nam, parallel=False):
 
 def _setup(obj):
   def _adopt(self, action):
-    self.__adopt(action.get())
+    getattr(self,'__adopt')(action.get())
   _import_class('digi', obj)
   cls = getattr(current, obj)
   setattr(cls, '__adopt', getattr(cls, 'adopt'))
diff --git a/DDDigi/src/DigiContainerCombine.cpp b/DDDigi/src/DigiContainerCombine.cpp
index 5871265c12f383075589aa8dcc6cd505126bb930..e36d49f3b0bb7dddaad9c8753b887738cff92cb6 100644
--- a/DDDigi/src/DigiContainerCombine.cpp
+++ b/DDDigi/src/DigiContainerCombine.cpp
@@ -44,6 +44,7 @@ public:
   std::set<Key::key_type>        keys  { };
   /// Container keys of all containers to be manipulated
   std::set<Key::key_type>        cont_keys  { };
+
   /// Predicate function to select containers for merging
   std::function<bool(Key::key_type)>  container_selector;
   /// Flag to check the initialization
@@ -55,17 +56,6 @@ public:
       if ( !this->inited )   {
 	this->inited = true;
 
-	this->container_selector = [this](Key::key_type k)  {
-	  const auto& m = this->masks;
-	  bool use = m.empty() || this->keys.empty();
-	  if ( !use )  {
-	    use = std::find(m.begin(), m.end(), Key::mask(k)) != m.end();
-	    if ( !use )   {
-	      return this->cont_keys.find(Key::item(k)) != this->cont_keys.end();
-	    }
-	  }
-	  return true;
-	};
 	for ( const auto& c : this->containers )   {
 	  Key key(0x0, c);
 	  this->cont_keys.emplace(key.key);
@@ -78,6 +68,17 @@ public:
 	    this->keys.emplace(key.key);
 	  }
 	}
+
+	this->container_selector = [this](Key::key_type k)  {
+	  const auto& m = this->masks;
+	  bool use = m.empty() || this->keys.empty();
+	  if ( !use )  {
+	    if ( !this->cont_keys.empty() )
+	      return this->cont_keys.find(Key::item(k)) != this->cont_keys.end();
+	    return std::find(m.begin(), m.end(), Key::mask(k)) != m.end();
+	  }
+	  return true;
+	};
       }
     }
   }
@@ -105,7 +106,7 @@ dd4hep::digi::DigiContainerCombine::~DigiContainerCombine() {
 
 /// Combine selected containers to one single deposit container
 template <typename PREDICATE> std::size_t 
-dd4hep::digi::DigiContainerCombine::combine_containers(DigiEvent& event,
+dd4hep::digi::DigiContainerCombine::combine_containers(DigiEvent&   event,
 						       DataSegment& inputs,
 						       DataSegment& outputs,
 						       const PREDICATE& predicate)  const
@@ -113,68 +114,82 @@ dd4hep::digi::DigiContainerCombine::combine_containers(DigiEvent& event,
   std::size_t cnt_depos = 0;
   std::size_t cnt_parts = 0;
   std::size_t cnt_conts = 0;
-  std::vector<Key::key_type> to_erase;
+  std::vector<Key> keys;
+  std::vector<std::any*> work;
+  std::set<Key::itemkey_type> items;
 
+  keys.reserve(inputs.size());
+  work.reserve(inputs.size());
   for( auto& i : inputs )   {
     if ( predicate(i.first) )   {
-      Key depo_key(i.first);
-      Key input_key(i.first);
-      DepositMapping* din = std::any_cast<DepositMapping>(&i.second);
-      if ( din )   {
-	depo_key.values.mask = internals->deposit_mask;
-	cnt_depos += din->size();
+      keys.emplace_back(i.first);
+      work.emplace_back(&i.second);
+      items.insert(Key(i.first).values.item);
+    }
+  }
+  Key depo_key;
+  depo_key.values.mask = internals->deposit_mask;
+  for(auto itm : items)   {
+    for( std::size_t i=0; i < keys.size(); ++i )   {
+      if ( keys[i].values.item != itm )
+	continue;
+      auto* output = work[i];
+      depo_key.values.item = itm;
+
+      /// Merge deposit mapping
+      if ( DepositMapping* depos = std::any_cast<DepositMapping>(output) )   {
+	if ( !internals->output_name_flag.empty() )
+	  depos->name = depos->name+"/"+internals->output_name_flag;
+	cnt_depos += depos->size();
 	cnt_conts++;
-	auto iter = outputs.find(depo_key.key);
-	if ( iter == outputs.end() )   {
-	  this->info("%s+++ %-32s Mask: %06X Input: %06X Merged %6ld deposits",
-		     event.id(), din->name.c_str(), depo_key.values.mask, 
-		     input_key.values.mask, din->size()); 
-	  if ( !internals->output_name_flag.empty() )   {
-	    din->name = din->name+"/"+internals->output_name_flag;
+	this->info("%s+++ %-32s Mask: $%04X Input: $%04X Merged %6ld deposits",
+		   event.id(), depos->name.c_str(), depo_key.values.mask, 
+		   keys[i].values.mask, depos->size()); 
+	for( std::size_t j=i+1; j < keys.size(); ++j )   {
+	  if ( keys[j].values.item == itm )   {
+	    DepositMapping* next = std::any_cast<DepositMapping>(work[j]);
+	    cnt_depos += next->size();
+	    cnt_conts++;
+	    std::size_t cnt = depos->merge(std::move(*next));
+	    this->info("%s+++ %-32s Mask: $%04X Input: $%04X Merged %6ld deposits",
+		       event.id(), depos->name.c_str(), depo_key.values.mask, 
+		       keys[j].values.mask, cnt); 
+	    cnt_depos += cnt;
+	    cnt_conts++;
+	    work[j]->reset();
 	  }
-	  outputs.emplace(depo_key.key, std::move(i.second));
-	  to_erase.emplace_back(i.first);
-	  continue;
 	}
-	DepositMapping* out = std::any_cast<DepositMapping>(&iter->second);
-	std::size_t cnt = out->merge(std::move(*din));
-	this->info("%s+++ %-32s Mask: %06X Input: %06X Merged %6ld deposits",
-		   event.id(), out->name.c_str(), depo_key.values.mask, 
-		   input_key.values.mask, cnt); 
-	i.second.reset();
-	to_erase.emplace_back(i.first);
-	continue;
+	outputs.emplace(depo_key, std::move(*output));
+	break;
       }
-      ParticleMapping* pin = std::any_cast<ParticleMapping>(&i.second);
-      if ( pin )   {
-	depo_key.values.mask = internals->deposit_mask;
-	cnt_parts += pin->size();
+      else if ( ParticleMapping* parts = std::any_cast<ParticleMapping>(output) )   {
+	if ( !internals->output_name_flag.empty() )
+	  parts->name = parts->name+"/"+internals->output_name_flag;
+	cnt_parts += parts->size();
 	cnt_conts++;
-	auto iter = outputs.find(depo_key.key);
-	if ( iter == outputs.end() )   {
-	  this->info("%s+++ %-32s Mask: %06X Input: %06X Merged %6ld particles",
-		     event.id(), pin->name.c_str(), depo_key.values.mask, 
-		     input_key.values.mask, pin->size()); 
-	  if ( !internals->output_name_flag.empty() )   {
-	    pin->name = pin->name+"/"+internals->output_name_flag;
+
+	this->info("%s+++ %-32s Mask: $%04X Input: $%04X Merged %6ld particles",
+		   event.id(), parts->name.c_str(), depo_key.values.mask, 
+		   keys[i].values.mask, parts->size()); 
+	for( std::size_t j=i+1; j < keys.size(); ++j )   {
+	  if ( keys[j].values.item == itm )   {
+	    ParticleMapping* next = std::any_cast<ParticleMapping>(work[j]);
+	    std::size_t cnt = parts->merge(std::move(*next));
+	    this->info("%s+++ %-32s Mask: $%04X Input: $%04X Merged %6ld particles",
+		       event.id(), parts->name.c_str(), depo_key.values.mask, 
+		       keys[j].values.mask, cnt); 
+	    cnt_parts += cnt;
+	    cnt_conts++;
+	    work[j]->reset();
 	  }
-	  outputs.emplace(depo_key.key, std::move(i.second));
-	  to_erase.emplace_back(i.first);
-	  continue;
 	}
-	ParticleMapping* out = std::any_cast<ParticleMapping>(&iter->second);
-	std::size_t cnt = out->merge(std::move(*pin));
-	this->info("%s+++ %-32s Mask: %06X Input: %06X Merged %6ld particles",
-		   event.id(), out->name.c_str(), depo_key.values.mask, 
-		   input_key.values.mask, cnt); 
-	i.second.reset();
-	to_erase.emplace_back(i.first);
-	continue;
-      }      
+	outputs.emplace(depo_key, std::move(*output));
+	break;
+      }
     }
   }
   if ( this->internals->erase_combined )   {
-    inputs.erase(to_erase);
+    inputs.erase(keys);
   }
   this->info("%s+++ Merged %ld particles and %ld deposits from %ld containers",
 	     event.id(), cnt_parts, cnt_depos, cnt_conts);
diff --git a/DDDigi/src/DigiData.cpp b/DDDigi/src/DigiData.cpp
index e9ad1a36713291c3090c2564dd8385b704a4a02e..371e219d6009d21f527caf1bff481341a997480a 100644
--- a/DDDigi/src/DigiData.cpp
+++ b/DDDigi/src/DigiData.cpp
@@ -40,6 +40,7 @@ void Key::set(const std::string& name, int mask)    {
     std::lock_guard<std::mutex> lock(_k.lock);
     except("DDDigi::Key", "+++ No key name was specified  --  this is illegal!");
   }
+  this->key = 0;
   this->values.mask = (unsigned char)(0xFF&mask);
   this->values.item = detail::hash32(name);
   std::lock_guard<std::mutex> lock(_k.lock);
@@ -89,16 +90,15 @@ std::size_t ParticleMapping::merge(ParticleMapping&& updates)    {
   return update_size;
 }
 
-void ParticleMapping::push(Key::key_type k, Particle&& part)  {
+void ParticleMapping::push(Key key, Particle&& part)  {
 #if defined(__GNUC__) && (__GNUC__ < 10)
   /// Lower compiler version have a bad implementation of std::any
   bool ret = false;
   if ( part.history.has_value() ) {}
 #else
-  bool ret = this->emplace(k, std::move(part)).second;
+  bool ret = this->emplace(key.key, std::move(part)).second;
 #endif
   if ( !ret )   {
-    Key key(k);
     except("ParticleMapping","Error in particle map. Duplicate ID: mask:%04X Number:%d",
 	   key.values.mask, key.values.item);
   }
@@ -110,14 +110,14 @@ DataSegment::DataSegment(std::mutex& l) : lock(l)
 }
 
 /// Remove data item from segment
-bool DataSegment::emplace(key_type key, std::any&& item)    {
+bool DataSegment::emplace(Key key, std::any&& item)    {
   std::lock_guard<std::mutex> l(lock);
 #if defined(__GNUC__) && (__GNUC__ < 10)
   /// Lower compiler version have a bad implementation of std::any
   bool ret = false;
   if ( item.has_value() ) {}
 #else
-  bool ret = data.emplace(key, std::move(item)).second;
+  bool ret = data.emplace(key.key, std::move(item)).second;
 #endif
   if ( !ret )   {
     Key k(key);
@@ -128,9 +128,9 @@ bool DataSegment::emplace(key_type key, std::any&& item)    {
 }
 
 /// Remove data item from segment
-bool DataSegment::erase(key_type key)    {
+bool DataSegment::erase(Key key)    {
   std::lock_guard<std::mutex> l(lock);
-  auto iter = data.find(key);
+  auto iter = data.find(key.key);
   if ( iter != data.end() )   {
     data.erase(iter);
     return true;
@@ -139,11 +139,11 @@ bool DataSegment::erase(key_type key)    {
 }
 
 /// Remove data items from segment (locked)
-std::size_t DataSegment::erase(const std::vector<key_type>& keys)   {
+std::size_t DataSegment::erase(const std::vector<Key>& keys)   {
   std::size_t count = 0;
   std::lock_guard<std::mutex> l(lock);
   for(auto key : keys)   {
-    auto iter = data.find(key);
+    auto iter = data.find(key.key);
     if ( iter != data.end() )   {
       data.erase(iter);
       ++count;
@@ -152,28 +152,40 @@ std::size_t DataSegment::erase(const std::vector<key_type>& keys)   {
   return count;
 }
 
+/// Print segment keys
+void DataSegment::print_keys()   const   {
+  size_t count = 0;
+  for( const auto& e : this->data )   {
+    Key k(e.first);
+    printout(INFO, "DataSegment", "Key No.%4: %16lX <> %16lX -> %04X %10ld",
+	     count, e.first, k.key, k.values.mask, k.values.item, 
+	     typeName(e.second.type()).c_str());
+    ++count;
+  }
+}
+
 /// Call on failed any-casts during data requests
-std::string DataSegment::invalid_cast(key_type key, const std::type_info& type)  const   {
+std::string DataSegment::invalid_cast(Key key, const std::type_info& type)  const   {
   return dd4hep::format(0, "Invalid segment data cast. Key:%ld type:%s",
 			key, typeName(type).c_str());
 }
 
 /// Call on failed data requests during data requests
-std::string DataSegment::invalid_request(key_type key)  const   {
+std::string DataSegment::invalid_request(Key key)  const   {
   return dd4hep::format(0, "Invalid segment data requested. Key:%ld",key);
 }
 
 /// Access data item by key
-std::any* DataSegment::get_item(key_type key, bool exc)   {
-  auto it = this->data.find(key);
+std::any* DataSegment::get_item(Key key, bool exc)   {
+  auto it = this->data.find(key.key);
   if (it != this->data.end()) return &it->second;
   if ( exc ) throw std::runtime_error(invalid_request(key));
   return nullptr;
 }
 
 /// Access data item by key  (CONST)
-const std::any* DataSegment::get_item(key_type key, bool exc)  const   {
-  auto it = this->data.find(key);
+const std::any* DataSegment::get_item(Key key, bool exc)  const   {
+  auto it = this->data.find(key.key);
   if (it != this->data.end()) return &it->second;
   if ( exc ) throw std::runtime_error(invalid_request(key));
   return nullptr;
diff --git a/DDDigi/src/DigiHitAttenuatorExp.cpp b/DDDigi/src/DigiHitAttenuatorExp.cpp
index fb883f524d9eaf7a6d42952d5d845c464668e874..16ae3b2be864ae804e16711f7e05359bd6169697 100644
--- a/DDDigi/src/DigiHitAttenuatorExp.cpp
+++ b/DDDigi/src/DigiHitAttenuatorExp.cpp
@@ -86,8 +86,9 @@ void dd4hep::digi::DigiHitAttenuatorExp::execute(DigiContext& context)  const
       }
       count += m->size();
       std::string nam = Key::key_name(k.first)+":";
-      debug("%s+++ %-32s Mask: %06X Attenuated exponentially %6ld hits by %8.5f",
-	    event.id(), nam.c_str(), m->mask, m->size(), factor); 
+      debug("%s+++ %-32s mask:%04X item: %08X Attenuated exponentially %6ld hits by %8.5f",
+	    event.id(), nam.c_str(), m->key.values.mask, m->key.values.item, 
+	    m->size(), factor); 
       continue;
     }
   }
diff --git a/DDDigi/src/DigiSegmentationSplitter.cpp b/DDDigi/src/DigiSegmentationSplitter.cpp
index 560d18f650b77559f0c14d89884f0d67fc7af0d4..f4d1bfb0adbcede22e77e832b574b8e20fe876ee 100644
--- a/DDDigi/src/DigiSegmentationSplitter.cpp
+++ b/DDDigi/src/DigiSegmentationSplitter.cpp
@@ -13,160 +13,36 @@
 
 // Framework include files
 #include <DD4hep/Plugins.h>
-#include <DD4hep/Detector.h>
 #include <DD4hep/InstanceCount.h>
 
-#include <DDDigi/DigiData.h>
 #include <DDDigi/DigiKernel.h>
 #include <DDDigi/DigiContext.h>
 #include <DDDigi/DigiSegmentationSplitter.h>
 
-#include <sstream>
-
 using namespace dd4hep::digi;
 
 class DigiSegmentAction::internals_t  {
 public:
-  const DigiSegmentContext* split { nullptr };
-  const DepositMapping*     input { nullptr };
+  DigiSegmentContext split { };
+  std::vector<std::pair<Key::key_type, std::any> > output;
+  const DepositMapping*    input { nullptr };
 };
 
 class DigiSegmentationSplitter::internals_t   {
 public:
-  /// Property: Identifier of the input repository
-  std::string input_id;
-  /// Property: Subdetector to handle
-  std::string detector_name;
-  /// Property: Factory name of the processor type
-  std::string split_by;
-  /// Property: Split element of the ID descriptor
-  std::string processor_type;
-  /// Property: Flag if processors should be shared
-  bool        share_processor   { true };
-  /// Property: Input mask in the repository
-  int         input_mask;
-
-  std::vector<Key::key_type> data_keys;
-
-  DigiSegmentContext splitter;
-
-  const DigiKernel& kernel;
-  Detector&         description;
-  DetElement        detector;
-  SensitiveDetector sensitive;
-  IDDescriptor      iddescriptor;
+  /// Reference to master
   DigiSegmentationSplitter* split { nullptr };
-
-  std::map<uint64_t, DigiSegmentContext> split_processors;
-
   /// Flag to check the initialization
   bool inited  { false };
-
-  internals_t(const DigiKernel& krnl, DigiSegmentationSplitter* s) 
-    : kernel(krnl), description(kernel.detectorDescription()), split(s)
-  {
-  }
-
-  void scan_detector(DetElement de, VolumeID vid, VolumeID mask)   {
-    const auto& new_ids = de.placement().volIDs();
-    VolumeID    new_vid = vid;
-    VolumeID    new_msk = mask;
-    if ( !new_ids.empty() )   {
-      new_vid |= this->iddescriptor.encode(new_ids);
-      new_msk |= this->iddescriptor.get_mask(new_ids);
-      for (const auto& id : new_ids)   {
-	if ( id.first == this->split_by )   {
-	  DigiSegmentContext context = this->splitter;
-	  context.detector = de;
-	  context.id = id.second;
-	  this->split_processors.emplace(new_vid, std::move(context));
-	  return;
-	}
-      }
-    }
-    for ( const auto& c : de.children() )
-      scan_detector(c.second, new_vid, new_msk);
-  }
-
-  void init_basics()   {
-    const char* det = this->detector_name.c_str();
-    this->detector = this->description.detector(det);
-    if ( !this->detector.isValid() )   {
-      split->except("FAILED: Cannot access subdetector %s from the detector description.", det);
-    }
-    this->sensitive = this->description.sensitiveDetector(det);
-    if ( !sensitive.isValid() )   {
-      split->except("FAILED: Cannot access sensitive detector for %s.", det);
-    }
-    this->iddescriptor = this->sensitive.idSpec();
-    if ( !this->iddescriptor.isValid() )   {
-      split->except("FAILED: Cannot access ID descriptor for detector %s.", det);
-    }
-    Readout rd = this->sensitive.readout();
-    auto colls = rd.collectionNames();
-    if ( colls.empty() ) colls.emplace_back(rd.name());
-    for( const auto& c : colls )   {
-      this->data_keys.emplace_back(Key(this->input_mask, c).key);
-    }
-  }
-
-  void init_splitting()   {
-    const char* det = this->detector_name.c_str();
-    /// Setup the splitter
-    this->splitter.cell_mask = ~0x0UL;
-    this->splitter.detector  = this->detector;
-    this->splitter.idspec    = this->iddescriptor;
-    for(const auto& f : this->iddescriptor.fields())   {
-      const BitFieldElement* e = f.second;
-      if ( e->name() == this->split_by )   {
-	this->splitter.field      = e;
-	this->splitter.split_mask = e->mask();
-	this->splitter.width      = e->width();
-	this->splitter.offset     = e->offset();
-	this->splitter.max_split  = 1 << e->width();
-      }
-      else   {
-	this->splitter.det_mask |= e->mask();
-      }
-      this->splitter.cell_mask = (splitter.cell_mask << e->width());
-      split->info("%-24s %-8s [%3d,%7d] width:%2d offset:%2d mask:%016lX Split:%016lX Det:%016lX Cells:%016lX",
-		  iddescriptor.name(), e->name().c_str(),
-		  e->minValue(), e->maxValue(), e->width(), e->offset(),
-		  e->mask(), this->splitter.split_mask, this->splitter.det_mask, this->splitter.cell_mask);
-      if ( this->splitter.field ) break;
-    }
-    if ( !this->splitter.field )   {
-      split->except("FAILED: The ID descriptor for detector %s has no field %s.",
-		    det, split_by.c_str());
-    }
-    this->split_processors.clear();
-    const auto& ids = this->detector.placement().volIDs();
-    VolumeID    vid = this->iddescriptor.encode(ids);
-    VolumeID    msk = this->iddescriptor.get_mask(ids);
-    this->scan_detector(this->detector, vid, msk);
-    split->info("%-24s has %ld parallel entries in when splitting by \"%s\"",
-		det, this->split_processors.size(), this->split_by.c_str());
-    std::stringstream str;
-    for( auto id : this->split_processors )
-      str << std::setw(16) << std::hex << std::setfill('0') << id.first << " ";
-    split->info("%-24s --> Parallel Vid: %s", det, str.str().c_str());
-    str.str("");
-    for( auto id : this->split_processors )
-      str << std::setw(16) << std::dec << std::setfill(' ') << this->splitter.split_id(id.first) << " ";
-    split->info("%-24s --> Parallel ID:  %s", det, str.str().c_str());
-  }
-
+  /// Default constructor
+  internals_t(DigiSegmentationSplitter* s) : split(s)  {}
   /// Initializing function: compute values which depend on properties
   void initialize(DigiContext& context)   {
     if ( !this->inited )   {
       std::lock_guard<std::mutex> lock(context.initializer_lock());
       if ( !this->inited )   {
-	const std::string det = this->detector_name;
+	this->split->initialize();
 	this->inited = true;
-	this->init_basics();
-	this->init_splitting();
-	this->split->init_processors();
-	split->info("+++ Detector splitter is now fully initialized!");
       }
     }
   }
@@ -174,15 +50,15 @@ public:
 
 /// Standard constructor
 DigiSegmentationSplitter::DigiSegmentationSplitter(const DigiKernel& krnl, const std::string& nam)
-  : DigiActionSequence(krnl, nam)
+  : DigiActionSequence(krnl, nam), m_split_tool(krnl.detectorDescription())
 {
-  this->internals = std::make_unique<internals_t>(m_kernel, this);
-  declareProperty("input",           this->internals->input_id = "deposits");
-  declareProperty("detector",        this->internals->detector_name);
-  declareProperty("mask",            this->internals->input_mask);
-  declareProperty("split_by",        this->internals->split_by);
-  declareProperty("processor_type",  this->internals->processor_type);
-  declareProperty("share_processor", this->internals->share_processor = true);
+  this->internals = std::make_unique<internals_t>(this);
+  declareProperty("detector",        this->m_detector_name);
+  declareProperty("split_by",        this->m_split_by);
+  declareProperty("input",           this->m_input_id = "deposits");
+  declareProperty("mask",            this->m_input_mask);
+  declareProperty("processor_type",  this->m_processor_type);
+  declareProperty("share_processor", this->m_share_processor = false);
   InstanceCount::increment(this);
 }
 
@@ -191,33 +67,38 @@ DigiSegmentationSplitter::~DigiSegmentationSplitter() {
   InstanceCount::decrement(this);
 }
 
-void DigiSegmentationSplitter::init_processors()   {
+
+/// Initialization function
+void DigiSegmentationSplitter::initialize()   {
   char text[256];
   std::size_t count = 0;
-  auto& imp   = *this->internals;
-  std::string typ = imp.processor_type;
-  DigiSegmentAction* proc = nullptr;
+  DigiSegmentAction* proc;
+
+  this->m_split_tool.set_detector(this->m_detector_name);
+  this->m_split_context = this->m_split_tool.split_context(this->m_split_by);
+  this->m_data_keys = this->m_split_tool.collection_keys(this->m_input_mask);
+  this->m_splits = this->m_split_tool.split_segmentation(this->m_split_by);
+
   /// Create the processors:
-  for( const auto& p : imp.split_processors )   {
-    auto& split = p.second;
-    ::snprintf(text, sizeof(text), "_%05X", split.split_id(p.first));
+  for( auto& p : this->m_splits )   {
+    ::snprintf(text, sizeof(text), "_%05X", m_split_context.split_id(p.first));
     std::string nam = this->name() + text;
-    proc = PluginService::Create<DigiSegmentAction*>(typ, &m_kernel, nam);
+    proc = PluginService::Create<DigiSegmentAction*>(m_processor_type, &m_kernel, nam);
     proc->internals = std::make_unique<DigiSegmentAction::internals_t>();
-    proc->internals->split = &split;
+    proc->internals->split          = this->m_split_context;
+    proc->internals->split.detector = p.second.first;
+    proc->internals->split.id       = p.second.second;
     this->DigiActionSequence::adopt(proc);
     ++count;
   }
+  info("+++ Detector splitter is now fully initialized!");
 }
 
 /// Main functional callback
 void DigiSegmentationSplitter::execute(DigiContext& context)  const    {
-  auto& imp   = *this->internals;
-  auto& event = *context.event;
-  auto& input = event.get_segment(imp.input_id);
-
+  auto& input = context.event->get_segment(this->m_input_id);
   this->internals->initialize(context);
-  for( auto k : imp.data_keys )   {
+  for( auto k : this->m_data_keys )   {
     auto* hits = input.pointer<DepositMapping>(k);
     if ( hits )    {
       /// prepare processors for execution
@@ -245,16 +126,13 @@ DigiSegmentAction::~DigiSegmentAction() {
 }
 
 void DigiSegmentAction::execute(DigiContext& context)  const  {
-  auto& input = *this->internals->input;
-  auto& split = *this->internals->split;
-  auto ret = this->handleSegment(context, split, input);
-  if ( !ret.empty() )    {
-    //auto& segment = context.event->get_segment();
-  }
+  auto& imp = *this->internals;
+  auto ret = this->handleSegment(context, imp.split, *imp.input);
+  imp.output = std::move(ret);
 }
 
 /// Main functional callback
-std::map<Key::key_type, std::any> 
+std::vector<std::pair<Key::key_type, std::any> >
 DigiSegmentAction::handleSegment(DigiContext&              context,
 				 const DigiSegmentContext& segment,
 				 const DepositMapping&     deposits)  const   {
diff --git a/DDDigi/src/DigiSegmentationTool.cpp b/DDDigi/src/DigiSegmentationTool.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e2aea1bab5089a2b8f3c0507c99530e8af18e908
--- /dev/null
+++ b/DDDigi/src/DigiSegmentationTool.cpp
@@ -0,0 +1,185 @@
+//==========================================================================
+//  AIDA Detector description implementation 
+//--------------------------------------------------------------------------
+// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
+// All rights reserved.
+//
+// For the licensing terms see $DD4hepINSTALL/LICENSE.
+// For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
+//
+// Author     : M.Frank
+//
+//==========================================================================
+
+// Framework include files
+#include <DD4hep/Printout.h>
+#include <DDDigi/DigiData.h>
+#include <DDDigi/DigiSegmentationTool.h>
+
+#include <sstream>
+
+using namespace std;
+using namespace dd4hep::digi;
+
+namespace  {
+  void scan_detector(const DigiSegmentationTool& tool,
+		     const string& split_by,
+		     map<dd4hep::VolumeID, pair<dd4hep::DetElement, dd4hep::VolumeID> >& splits,
+		     dd4hep::DetElement de, dd4hep::VolumeID vid, dd4hep::VolumeID mask)   {
+    const auto& new_ids = de.placement().volIDs();
+    dd4hep::VolumeID    new_vid = vid;
+    dd4hep::VolumeID    new_msk = mask;
+    if ( !new_ids.empty() )   {
+      new_vid |= tool.iddescriptor.encode(new_ids);
+      new_msk |= tool.iddescriptor.get_mask(new_ids);
+      for (const auto& id : new_ids)   {
+	if ( id.first == split_by )   {
+	  splits.emplace(new_vid, make_pair(de, id.second));
+	  return;
+	}
+      }
+    }
+    for ( const auto& c : de.children() )
+      scan_detector(tool, split_by, splits, c.second, new_vid, new_msk);
+  }
+}
+
+/// Split field name
+const string& DigiSegmentContext::name()  const  {
+  return this->field->name();
+}
+/// Split field name
+const char* DigiSegmentContext::cname()  const  {
+  return this->field->name().c_str();
+}
+
+/// Initializing constructor
+DigiSegmentationTool::DigiSegmentationTool(Detector& desc)
+  : description(desc)
+{
+}
+
+/// Setup tool to handle a given detector of the geometry
+void DigiSegmentationTool::set_detector(const string& det_name)    {
+  const char* det = det_name.c_str();
+  this->detector = this->description.detector(det_name);
+  if ( !this->detector.isValid() )   {
+    except("DigiSegmentationTool",
+	   "FAILED: Cannot access subdetector %s from the detector description.", det);
+  }
+  this->sensitive = this->description.sensitiveDetector(det_name);
+  if ( !sensitive.isValid() )   {
+    except("DigiSegmentationTool",
+	   "FAILED: Cannot access sensitive detector for %s.", det);
+  }
+  this->iddescriptor = this->sensitive.idSpec();
+  if ( !this->iddescriptor.isValid() )   {
+    except("DigiSegmentationTool",
+	   "FAILED: Cannot access ID descriptor for detector %s.", det);
+  }
+}
+
+/// Access the readout collection keys
+vector<Key> DigiSegmentationTool::collection_keys()   const   {
+  return collection_keys(0x0);
+}
+
+/// Access the readout collection keys
+vector<Key> DigiSegmentationTool::collection_keys(Key::mask_type mask)   const   {
+  vector<Key> keys;
+  if ( this->sensitive.isValid() )    {
+    Readout rd = this->sensitive.readout();
+    auto colls = rd.collectionNames();
+    if ( colls.empty() ) colls.emplace_back(rd.name());
+    for( const auto& c : colls )
+      keys.emplace_back(Key(mask, c));
+    return keys;
+  }
+  except("DigiSegmentationTool",
+	 "+++ collection_keys: Readout not valid. Is the proper detector set ?");
+  return keys;
+}
+
+/// Access the readout collection keys
+vector<Key> 
+DigiSegmentationTool::collection_keys(const vector<string>& detectors) const  {
+  vector<Key> keys;
+  for( const auto& det : detectors )   {
+    DigiSegmentationTool tool(this->description);
+    tool.set_detector(det);
+    auto det_keys = tool.collection_keys(0x0);
+    keys.insert(keys.end(), det_keys.begin(), det_keys.end());
+  }
+  return keys;
+}
+
+/// Access the readout collection keys
+vector<Key> 
+DigiSegmentationTool::collection_keys(const vector<string>& detectors,
+				      Key::mask_type mask)   const
+{
+  vector<Key> keys;
+  for( const auto& det : detectors )   {
+    DigiSegmentationTool tool(this->description);
+    tool.set_detector(det);
+    auto det_keys = tool.collection_keys(mask);
+    keys.insert(keys.end(), det_keys.begin(), det_keys.end());
+  }
+  return keys;
+}
+
+/// Create a split context depending on the segmentation field
+DigiSegmentContext 
+DigiSegmentationTool::split_context(const string& split_by)  const {
+  DigiSegmentContext splitter;
+  splitter.cell_mask = ~0x0UL;
+  splitter.detector  = this->detector;
+  splitter.idspec    = this->iddescriptor;
+  for(const auto& f : this->iddescriptor.fields())   {
+    const BitFieldElement* e = f.second;
+    if ( e->name() == split_by )   {
+      splitter.field      = e;
+      splitter.split_mask = e->mask();
+      splitter.width      = e->width();
+      splitter.offset     = e->offset();
+      splitter.max_split  = 1 << e->width();
+    }
+    else   {
+      splitter.det_mask |= e->mask();
+    }
+    splitter.cell_mask = (splitter.cell_mask << e->width());
+    printout(INFO,"DigiSegmentationTool",
+	     "%-24s %-8s [%3d,%7d] width:%2d offset:%2d mask:%016lX Split:%016lX Det:%016lX Cells:%016lX",
+	     this->iddescriptor.name(), e->name().c_str(),
+	     e->minValue(), e->maxValue(), e->width(), e->offset(),
+	     e->mask(), splitter.split_mask, splitter.det_mask, splitter.cell_mask);
+    if ( splitter.field ) break;
+  }
+  if ( !splitter.field )   {
+    except("DigiSegmentationTool",
+	   "FAILED: The ID descriptor for detector %s has no field %s.",
+	   this->detector.name(), split_by.c_str());
+  }
+  return splitter;
+}
+
+/// Create full set of detector segments which can be split according to the context
+map<dd4hep::VolumeID, pair<dd4hep::DetElement, dd4hep::VolumeID> >
+DigiSegmentationTool::split_segmentation(const string& split_by)  const
+{
+  map<VolumeID, pair<DetElement, VolumeID> > segmentation_splits;
+  const auto& ids = this->detector.placement().volIDs();
+  VolumeID    vid = this->iddescriptor.encode(ids);
+  VolumeID    msk = this->iddescriptor.get_mask(ids);
+  const char* det = this->detector.name();
+
+  ::scan_detector(*this, split_by, segmentation_splits, this->detector, vid, msk);
+  printout(INFO,"DigiSegmentationTool",
+	   "%-24s has %ld parallel entries in when splitting by \"%s\"",
+	   det, segmentation_splits.size(), split_by.c_str());
+  stringstream str;
+  for( auto id : segmentation_splits )
+    str << setw(16) << hex << setfill('0') << id.first << " ";
+  printout(INFO,"DigiSegmentationTool","%-24s --> Parallel Entries: %s", det, str.str().c_str());
+  return segmentation_splits;
+}
diff --git a/DDDigi/src/noise/DigiSubdetectorSequence.cpp b/DDDigi/src/noise/DigiSubdetectorSequence.cpp
index a56e098d06b5bc61137bfa845c0b6e142f3a8f7a..a46bd2a73096fbbc7165042fa19cc6086817b419 100644
--- a/DDDigi/src/noise/DigiSubdetectorSequence.cpp
+++ b/DDDigi/src/noise/DigiSubdetectorSequence.cpp
@@ -15,6 +15,9 @@
 #include <DDDigi/DigiSubdetectorSequence.h>
 #include <DDDigi/DigiSegmentation.h>
 #include <DDDigi/DigiKernel.h>
+#include <DDDigi/DigiContext.h>
+#include <DDDigi/DigiData.h>
+
 #include <DD4hep/InstanceCount.h>
 #include <DD4hep/Detector.h>
 #include <DD4hep/IDDescriptor.h>
diff --git a/examples/DDDigi/CMakeLists.txt b/examples/DDDigi/CMakeLists.txt
index 3e0f6324323daad06cd5dd1ab3193e08af579ab9..91a576cff82b23c1ba0804a107a7c904f532aa02 100644
--- a/examples/DDDigi/CMakeLists.txt
+++ b/examples/DDDigi/CMakeLists.txt
@@ -52,4 +52,3 @@ dd4hep_add_test_reg(DDDigi_colored_noise
   REGEX_FAIL "Error;ERROR;Exception"
   )
 #
-