diff --git a/DDDigi/include/DDDigi/DigiAttenuator.h b/DDDigi/include/DDDigi/DigiAttenuator.h
index 8ab5834986062324c7d2cfe725f6482fcb8a3dfd..4082a7084e8e8a560107313ec1916b44475b47d2 100644
--- a/DDDigi/include/DDDigi/DigiAttenuator.h
+++ b/DDDigi/include/DDDigi/DigiAttenuator.h
@@ -13,12 +13,8 @@
 #ifndef DDDIGI_DIGIATTENUATOR_H
 #define DDDIGI_DIGIATTENUATOR_H
 
-/// Framework include files
-#include <DDDigi/DigiAction.h>
-#include <DDDigi/DigiSignalProcessor.h>
-
-/// C/C++ include files
-#include <functional>
+// Framework include files
+#include <DDDigi/DigiContainerProcessor.h>
 
 /// Namespace for the AIDA detector description toolkit
 namespace dd4hep {
@@ -26,30 +22,85 @@ namespace dd4hep {
   /// Namespace for the Digitization part of the AIDA detector description toolkit
   namespace digi {
 
-    /// Base class for attenuator actions to the digitization
+    /// Tool to compute decay time of the signal for spillover
+    /**
+     *  The following signal decays are supported:
+     *  -- Exponential decay depending on time offset(t0) and mean signal decay time
+     *  -- more to be added
+     *
+     *  \author  M.Frank
+     *  \version 1.0
+     *  \ingroup DD4HEP_DIGITIZATION
+     */
+    class DigiAttenuationTool   {
+    public:
+      /// Exponential decay depending on time offset(t0) and mean signal decay time
+      double exponential(double t0, double decay_time)  const;
+    };
+
+    /// Default base class for all Digitizer actions and derivates thereof.
     /**
+     *  This is a utility class supporting properties, output and access to
+     *  event and run objects through the context.
      *
      *  \author  M.Frank
      *  \version 1.0
      *  \ingroup DD4HEP_DIGITIZATION
      */
-    class DigiAttenuator : public DigiSignalProcessor {
+    class DigiAttenuator : public DigiContainerProcessor   {
+    protected:
+      /// Signal reduction factor
+      double  m_factor { 1.0 };
+
     protected:
       /// Define standard assignments and constructors
       DDDIGI_DEFINE_ACTION_CONSTRUCTORS(DigiAttenuator);
-      /// Function object to be executed
-      std::function<double(const DigiCellData&)> processor;
+      /// Default destructor
+      virtual ~DigiAttenuator();
+      /// Attenuator callback for single container
+      template <typename T> std::size_t attenuate(T& cont) const;
+
     public:
       /// Standard constructor
       DigiAttenuator(const DigiKernel& kernel, const std::string& nam);
-      /// Default destructor
-      virtual ~DigiAttenuator();
-      /// Callback to read event attenuator
-      virtual double operator()(const DigiCellData& data) const {
-        return processor(data);
-      }
+      /// Main functional callback adapter
+      virtual void execute(DigiContext& context, work_t& work)  const override;
     };
 
+    /// Default base class for all Digitizer actions and derivates thereof.
+    /**
+     *  This is a utility class supporting properties, output and access to
+     *  event and run objects through the context.
+     *
+     *  \author  M.Frank
+     *  \version 1.0
+     *  \ingroup DD4HEP_DIGITIZATION
+     */
+    class DigiAttenuatorSequence : public  DigiContainerSequenceAction  {
+    protected:
+      /// Property: Data processor type
+      std::string                    m_processor_type { };
+      /// Property: Signal decay algorithm
+      std::string                    m_signal_decay   { };
+      /// Property: Container names to be loaded
+      std::map<std::string, double>  m_container_attenuation  { };
+      /// Property: T0 with respect to central crossing
+      double                         m_t0     { 0e0 };
+
+    protected:
+      /// Define standard assignments and constructors
+      DDDIGI_DEFINE_ACTION_CONSTRUCTORS(DigiAttenuatorSequence);
+      /// Default destructor
+      virtual ~DigiAttenuatorSequence();
+
+    public:
+      /// Standard constructor
+      DigiAttenuatorSequence(const DigiKernel& kernel, const std::string& nam);
+      /// Initialization callback
+      virtual void initialize();
+      /// Main functional callback
+      virtual void execute(DigiContext& context)  const;
+    };
   }    // End namespace digi
 }      // End namespace dd4hep
 #endif // DDDIGI_DIGIATTENUATOR_H
diff --git a/DDDigi/include/DDDigi/DigiAttenuatorSequenceAction.h b/DDDigi/include/DDDigi/DigiAttenuatorSequenceAction.h
deleted file mode 100644
index 3e27c14bb596027546355a444e38606f83a0ea45..0000000000000000000000000000000000000000
--- a/DDDigi/include/DDDigi/DigiAttenuatorSequenceAction.h
+++ /dev/null
@@ -1,66 +0,0 @@
-//==========================================================================
-//  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_DIGIATTENUATORSEQUENCEACTION_H
-#define DDDIGI_DIGIATTENUATORSEQUENCEACTION_H
-
-// Framework include files
-#include <DDDigi/DigiEventAction.h>
-
-/// Namespace for the AIDA detector description toolkit
-namespace dd4hep {
-
-  /// Namespace for the Digitization part of the AIDA detector description toolkit
-  namespace digi {
-
-    /// Default base class for all Digitizer actions and derivates thereof.
-    /**
-     *  This is a utility class supporting properties, output and access to
-     *  event and run objects through the context.
-     *
-     *  \author  M.Frank
-     *  \version 1.0
-     *  \ingroup DD4HEP_DIGITIZATION
-     */
-    class DigiAttenuatorSequenceAction : public DigiEventAction   {
-    protected:
-      /// Property: Input data segment name
-      std::string                    m_processor_name { };
-      /// Property: Input data segment name
-      std::string                    m_input_segment  { };
-      /// Property: Container names to be loaded
-      std::map<std::string, double>  m_container_attenuation  { };
-      /// Property: event mask to be handled
-      int                            m_mask   { 0 };
-      /// Property: T0 with respect to central crossing
-      double                         m_t0     { 0e0 };
-
-      /// Keys of all containers to be manipulated
-      std::map<Key, double> m_attenuation  { };
-
-    protected:
-      /// Define standard assignments and constructors
-      DDDIGI_DEFINE_ACTION_CONSTRUCTORS(DigiAttenuatorSequenceAction);
-      /// Default destructor
-      virtual ~DigiAttenuatorSequenceAction();
-
-    public:
-      /// Standard constructor
-      DigiAttenuatorSequenceAction(const DigiKernel& kernel, const std::string& nam);
-      /// Initialization callback
-      virtual void initialize();
-      /// Main functional callback
-      virtual void execute(DigiContext& context)  const;
-    };
-  }    // End namespace digi
-}      // End namespace dd4hep
-#endif // DDDIGI_DIGIATTENUATORSEQUENCEACTION_H
diff --git a/DDDigi/include/DDDigi/DigiContainerProcessor.h b/DDDigi/include/DDDigi/DigiContainerProcessor.h
index d90741c311f833da7c4ca7a56bc5f3bb580ff9a3..075848e245755e91def3e1e96a90c851de2f7d5b 100644
--- a/DDDigi/include/DDDigi/DigiContainerProcessor.h
+++ b/DDDigi/include/DDDigi/DigiContainerProcessor.h
@@ -42,22 +42,57 @@ namespace dd4hep {
      */
     class DigiContainerProcessor : public DigiAction   {
     public:
-      struct work_t  {
-	/// Event processing context
-	DigiContext&    context;
+      using segment_t = DataSegment;
+      struct input_t  {
 	/// Input data key
 	Key             key;
 	/// Input deposits
-	std::any&       input;
+	std::any&       data;
+      };
+      struct output_t  {
 	/// Lock for secure output merging
-	std::mutex&     output_lock;
+	//std::mutex&     lock;
 	/// Handle to output 
-	std::any&       output;
+	//std::any&       data;
+	int             mask;
+	segment_t&      data;
+      };
+
+      struct work_t  {
+	/// Event processing context
+	DigiContext&    context;
+	/// Input data
+	input_t         input;
+	/// Output data
+	output_t&       output;
+
+	/// Basic check if input data are present
+	bool has_input()  const    {  return this->input.data.has_value();  }
+	/// Access key of input data
+	Key  input_key()  const    {  return this->input.key;               }
+	/// Access the input data type
+	const std::type_info& input_type()  const;
+	/// String form of the input data type
+	std::string input_type_name()  const;
+	/// Access input data by type
+	template <typename DATA> DATA* get_input(bool exc=false);
+	/// Access input data by type
+	template <typename DATA> const DATA* get_input(bool exc=false)  const;
+#if 0
+	/// Basic check if input data are present
+	bool has_output()  const   {  return this->output.data.has_value();  }
+	/// String form of the output data type
+	std::string output_type_name()  const;
+	/// Access the output data type
+	const std::type_info& output_type()  const;
+	/// Access output data by type
+	template <typename DATA> DATA* get_output();
 
 	/// Merge output data (thread safe, locked)
 	void merge_output(DepositVector&& data);
 	/// Merge output data (thread safe, locked)
 	void emplace_output(CellID cell, EnergyDeposit&& deposit);
+#endif
       };
     protected:
       /// Define standard assignments and constructors
@@ -86,21 +121,20 @@ namespace dd4hep {
      */
     class DigiContainerSequence : public DigiContainerProcessor  {
     protected:
-      /// Property to steer parallel processing
-      bool m_parallel { false };
-
-    protected:
-      using self_t = DigiContainerSequence;
+      using self_t      = DigiContainerSequence;
       using processor_t = DigiContainerProcessor;
-      using worker_t  = DigiParallelWorker<processor_t,work_t>;
-      using workers_t = DigiParallelWorkers<worker_t>;
+      using worker_t    = DigiParallelWorker<processor_t,work_t>;
+      using workers_t   = DigiParallelWorkers<worker_t>;
       friend class DigiParallelWorker<processor_t,work_t>;
 
-      /// Array of sub-workers
-      workers_t         m_workers;
+    protected:
+      /// Property to steer parallel processing
+      bool m_parallel { false };
 
+      /// Array of sub-workers
+      workers_t          m_workers;
       /// Lock for output merging
-      mutable std::mutex        m_output_lock;
+      mutable std::mutex m_output_lock;
 
     protected:
       /// Define standard assignments and constructors
@@ -130,8 +164,9 @@ namespace dd4hep {
 
     protected:
       /// Argument structure for client calls
-      using self_t = DigiContainerSequenceAction;
+      using self_t      = DigiContainerSequenceAction;
       using processor_t = DigiContainerProcessor;
+      using output_t    = processor_t::output_t;
       struct work_item_t  {
 	Key key;
 	std::any* data;
@@ -139,9 +174,7 @@ namespace dd4hep {
       struct work_t  {
 	DigiContext&             context;
 	std::vector<work_item_t> input_items;
-	/// Lock for secure output merging
-	std::mutex&              output_lock;
-	std::any                 output;
+	output_t&                output;
 	const self_t*            parent;
       };
       using worker_t         = DigiParallelWorker<processor_t, work_t>;
@@ -151,19 +184,23 @@ namespace dd4hep {
       friend class DigiParallelWorker<processor_t, work_t>;
 
       /// Array of sub-workers
-      workers_t         m_workers;
+      workers_t          m_workers;
       /// Registered action map
-      reg_processors_t  m_registered_processors;
+      reg_processors_t   m_registered_processors;
       /// Registered worker map
-      reg_workers_t     m_registered_workers;
+      reg_workers_t      m_registered_workers;
 
       /// Property: Input data segment name
-      std::string       m_input_segment { "inputs" };
+      std::string        m_input_segment  { "inputs" };
       /// Property: Input mask to be handled
-      int               m_mask { 0x0 };
+      int                m_input_mask     { 0x0 };
+      /// Property: Input data segment name
+      std::string        m_output_segment { "outputs" };
+      /// Property: event mask for output data
+      int                m_output_mask   { 0x0 };
 
       /// Lock for output merging
-      mutable std::mutex        m_output_lock;
+      mutable std::mutex m_output_lock;
 
     protected:
       /// Define standard assignments and constructors
@@ -172,13 +209,15 @@ namespace dd4hep {
       /// Default destructor
       virtual ~DigiContainerSequenceAction();
       /// Initialization callback
-      void initialize();
+      virtual void initialize();
 
     public:
       /// Standard constructor
       DigiContainerSequenceAction(const DigiKernel& kernel, const std::string& name);
-      /// Adopt new parallel worker
+      /// Adopt new parallel worker acting on one single container
       void adopt_processor(DigiContainerProcessor* action, const std::string& container);
+      /// Adopt new parallel worker acting on multiple containers
+      void adopt_processor(DigiContainerProcessor* action, const std::vector<std::string>& containers);
       /// Main functional callback if specific work is known
       virtual void execute(DigiContext& context)  const override;
     };
@@ -192,36 +231,41 @@ namespace dd4hep {
      */
     class DigiMultiContainerProcessor : virtual public DigiEventAction   {
     protected:
-      using self_t       = DigiMultiContainerProcessor;
-      using processor_t  = DigiContainerProcessor;
-      using work_items_t = std::vector<std::pair<Key, std::any*> >;
-      /// Argument structure for client calls
+      using self_t        = DigiMultiContainerProcessor;
+      using processor_t   = DigiContainerProcessor;
+      using worker_keys_t = std::vector<std::vector<Key> >;
+      using work_items_t  = std::vector<std::pair<Key, std::any*> >;
+      using output_t      = processor_t::output_t;
+
+      /// Argument structure required to support multiple client calls
       struct work_t  {
 	DigiContext&    context;
 	work_items_t&   items;
-	std::mutex&     output_lock;
-	std::any        output;
-	const self_t*   parent;
+	output_t&       output;
+	const self_t&   parent;
       };
-      using worker_t  = DigiParallelWorker<processor_t, work_t>;
-      using workers_t = DigiParallelWorkers<worker_t>;
+      using worker_t      = DigiParallelWorker<processor_t, work_t>;
+      using workers_t     = DigiParallelWorkers<worker_t>;
       friend class DigiParallelWorker<processor_t, work_t>;
 
     protected:
       /// Property: Input data segment name
-      std::string       m_input_segment { "inputs" };
+      std::string        m_input_segment { "inputs" };
       /// Property: event masks to be handled
-      std::vector<int>  m_input_masks  { };
+      std::vector<int>   m_input_masks  { };
+      /// Property: Input data segment name
+      std::string        m_output_segment { "outputs" };
+      /// Property: event mask for output data
+      int                m_output_mask  { 0x0 };
 
       /// Set of work items to be processed and passed to clients
-      std::set<Key>     m_work_items;
-
-      std::vector<std::vector<Key> > m_worker_keys;
+      std::set<Key>      m_work_items;
+      /// Set of keys required by each worker
+      worker_keys_t      m_worker_keys;
       /// Array of sub-workers
-      workers_t         m_workers;
-
+      workers_t          m_workers;
       /// Lock for output merging
-      mutable std::mutex        m_output_lock;
+      mutable std::mutex m_output_lock;
 
     protected:
        /// Define standard assignments and constructors
diff --git a/DDDigi/include/DDDigi/DigiData.h b/DDDigi/include/DDDigi/DigiData.h
index 519f9210a78b668e0e99440350f1ebc18dfe8cd0..bf0f6a062255e5e3a73a220464d706851e423b3e 100644
--- a/DDDigi/include/DDDigi/DigiData.h
+++ b/DDDigi/include/DDDigi/DigiData.h
@@ -98,7 +98,7 @@ namespace dd4hep {
       }
 
       /// Project the item part of the key
-      mask_type mask()  {
+      mask_type mask()  const {
 	return this->values.mask;
       }
       /// Set key mask
@@ -119,7 +119,7 @@ namespace dd4hep {
       }
 
       /// Project the mask part of the key
-      itemkey_type item()  {
+      itemkey_type item()  const  {
 	return this->values.item;
       }
       /// Set key item identifier
@@ -376,8 +376,8 @@ namespace dd4hep {
      */
     class DepositVector : public SegmentEntry  {
     public: 
-      using container_t = std::vector<std::pair<CellID, EnergyDeposit> >;
-      using iterator = container_t::iterator;
+      using container_t    = std::vector<std::pair<CellID, EnergyDeposit> >;
+      using iterator       = container_t::iterator;
       using const_iterator = container_t::const_iterator;
 
       container_t    data { };
@@ -397,10 +397,14 @@ namespace dd4hep {
       DepositVector& operator=(DepositVector&& copy) = default;
       /// Disable copy assignment
       DepositVector& operator=(const DepositVector& copy) = default;      
-      /// Merge new deposit map onto existing map (not thread safe!)
+      /// Merge new deposit map onto existing vector (destroys inputs. not thread safe!)
       std::size_t merge(DepositVector&& updates);
-      /// Merge new deposit map onto existing map (keep inputs. not thread safe!)
+      /// Merge new deposit map onto existing map (destroys inputs. not thread safe!)
+      std::size_t merge(DepositMapping&& updates);
+      /// Merge new deposit map onto existing vector (keep inputs. not thread safe!)
       std::size_t insert(const DepositVector& updates);
+      /// Merge new deposit map onto existing map (keep inputs. not thread safe!)
+      std::size_t insert(const DepositMapping& updates);
       /// Emplace entry
       void emplace(CellID cell, EnergyDeposit&& deposit);
 
@@ -440,8 +444,8 @@ namespace dd4hep {
      */
     class DepositMapping : public SegmentEntry  {
     public: 
-      using container_t = std::multimap<CellID, EnergyDeposit>;
-      using iterator = container_t::iterator;
+      using container_t    = std::multimap<CellID, EnergyDeposit>;
+      using iterator       = container_t::iterator;
       using const_iterator = container_t::const_iterator;
 
       container_t    data { };
@@ -508,8 +512,8 @@ namespace dd4hep {
     class DataSegment   {
     public:
       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;
+      using iterator        = container_map_t::iterator;
+      using const_iterator  = container_map_t::const_iterator;
 
     private:
       /// Call on failed any-casts
@@ -545,6 +549,8 @@ namespace dd4hep {
       /** Locked operations */
       /// Emplace data item (locked)
       bool emplace(Key key, std::any&& data);
+      /// Move data items other than std::any to the data segment
+      template <typename DATA> bool put(Key key, DATA&& data);
       /// Remove data item from segment (locked)
       bool erase(Key key);
       /// Remove data items from segment (locked)
@@ -621,13 +627,27 @@ namespace dd4hep {
      */
     class  DigiEvent  {
     private:
+      using segment_t = std::unique_ptr<DataSegment>;
+      /// Event lock
       std::mutex  m_lock;
+      /// String identifier of this event (for debug printouts)
       std::string m_id;
-      DataSegment m_data        { this->m_lock };
-      DataSegment m_inputs      { this->m_lock };
-      DataSegment m_deposits    { this->m_lock };
+      /// Reference to the general purpose data segment
+      segment_t m_data;
+      /// Reference to the counts data segment
+      segment_t m_counts;
+      /// Reference to the input data segment
+      segment_t m_inputs;
+      /// Reference to the output data segment
+      segment_t m_outputs;
+      /// Reference to the deposit data segment
+      segment_t m_deposits;
+
+      /// Helper: Save access with segment creation if it does not exist
+      DataSegment& access_segment(segment_t& seg);
 
     public:
+      /// Current event number
       int eventNumber  { 0 };
 
     public:
diff --git a/DDDigi/include/DDDigi/DigiHitAttenuatorExp.h b/DDDigi/include/DDDigi/DigiHitAttenuatorExp.h
deleted file mode 100644
index faadc0bff55f10b80ccee1402e8cbc0978253d78..0000000000000000000000000000000000000000
--- a/DDDigi/include/DDDigi/DigiHitAttenuatorExp.h
+++ /dev/null
@@ -1,66 +0,0 @@
-//==========================================================================
-//  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_DIGIHITATTENUATOREXP_H
-#define DDDIGI_DIGIHITATTENUATOREXP_H
-
-// Framework include files
-#include <DDDigi/DigiEventAction.h>
-
-/// Namespace for the AIDA detector description toolkit
-namespace dd4hep {
-
-  /// Namespace for the Digitization part of the AIDA detector description toolkit
-  namespace digi {
-
-    /// Default base class for all Digitizer actions and derivates thereof.
-    /**
-     *  This is a utility class supporting properties, output and access to
-     *  event and run objects through the context.
-     *
-     *  \author  M.Frank
-     *  \version 1.0
-     *  \ingroup DD4HEP_DIGITIZATION
-     */
-    class DigiHitAttenuatorExp : public DigiEventAction   {
-    protected:
-      /// Property: Input data segment name
-      std::string                    m_input_segment  { };
-      /// Property: Container names to be loaded
-      std::map<std::string, double>  m_container_attenuation  { };
-      /// Property: event masks to be handled
-      std::vector<int>               m_masks  { };
-      /// Property: T0 with respect to central crossing
-      double                         m_t0     { 0e0 };
-
-      /// Keys of all containers to be manipulated
-      std::map<unsigned long, double> m_attenuation  { };
-
-    protected:
-      /// Define standard assignments and constructors
-      DDDIGI_DEFINE_ACTION_CONSTRUCTORS(DigiHitAttenuatorExp);
-      /// Default destructor
-      virtual ~DigiHitAttenuatorExp();
-      /// Attenuator callback for single container
-      template <typename T> std::size_t attenuate(T* cont, double factor) const;
-
-    public:
-      /// Standard constructor
-      DigiHitAttenuatorExp(const DigiKernel& kernel, const std::string& nam);
-      /// Initialization callback
-      virtual void initialize();
-      /// Main functional callback
-      virtual void execute(DigiContext& context)  const;
-    };
-  }    // End namespace digi
-}      // End namespace dd4hep
-#endif // DDDIGI_DIGIHITATTENUATOREXP_H
diff --git a/DDDigi/include/DDDigi/DigiParallelWorker.h b/DDDigi/include/DDDigi/DigiParallelWorker.h
index e22cba7800e0ffe179fc0e390f72a980abcd8fb4..ae1316f1ab1562c1e404d176bd1b508c4af9b2f3 100644
--- a/DDDigi/include/DDDigi/DigiParallelWorker.h
+++ b/DDDigi/include/DDDigi/DigiParallelWorker.h
@@ -13,6 +13,9 @@
 #ifndef DDDIGI_DIGIPARALLELWORKER_H
 #define DDDIGI_DIGIPARALLELWORKER_H
 
+/// C/C++ include files
+#include <cstdint>
+
 /// Namespace for the AIDA detector description toolkit
 namespace dd4hep {
 
diff --git a/DDDigi/include/DDDigi/DigiParallelWorkerGroup.h b/DDDigi/include/DDDigi/DigiParallelWorkerGroup.h
index ebebd2a56049dc907fd5998dede35c73d43d49e9..e9e51ad76d58142f0fb33e7700fe3bbdb69da266 100644
--- a/DDDigi/include/DDDigi/DigiParallelWorkerGroup.h
+++ b/DDDigi/include/DDDigi/DigiParallelWorkerGroup.h
@@ -14,8 +14,10 @@
 #define DDDIGI_DIGIPARALLELWORKERGROUP_H
 
 /// Framework include files
+#include <DDDigi/DigiParallelWorker.h>
 
 /// C/C++ include files
+#include <cstdint>
 
 /// Namespace for the AIDA detector description toolkit
 namespace dd4hep {
@@ -52,7 +54,7 @@ namespace dd4hep {
       /// Default destructor. Releasing semaphore
       ~DigiParallelWorkerGroup();
       /// Access the worker array. As long as the object persists it shall not be altered
-      operator ParallelCall*const* ();
+      operator ParallelWorker*const* ();
     };
     
     /// Initializin constructor: aquire worker's semaphore
@@ -69,8 +71,8 @@ namespace dd4hep {
     }
 
     /// Access the worker array. As long as the object persists the array stays intact
-    template <typename T> inline DigiParallelWorkerGroup<T>::operator ParallelCall*const* ()   {
-      return (ParallelCall**)&this->workers.actors.at(0);
+    template <typename T> inline DigiParallelWorkerGroup<T>::operator ParallelWorker*const* ()   {
+      return (ParallelWorker**)&this->workers.actors.at(0);
     }
 
   }    // End namespace digi
diff --git a/DDDigi/include/DDDigi/DigiParallelWorkers.h b/DDDigi/include/DDDigi/DigiParallelWorkers.h
index ea2cbd76f204599ea30a5228ba2cb55ba5e1a94b..18dea5ad8173c8d6a934eed0cbb09368e47e5a5f 100644
--- a/DDDigi/include/DDDigi/DigiParallelWorkers.h
+++ b/DDDigi/include/DDDigi/DigiParallelWorkers.h
@@ -18,6 +18,8 @@
 #include <DDDigi/DigiParallelWorkerGroup.h>
 
 /// C/C++ include files
+#include <vector>
+#include <cstdint>
 
 /// Namespace for the AIDA detector description toolkit
 namespace dd4hep {
@@ -73,7 +75,7 @@ namespace dd4hep {
       std::size_t size()  const;
       bool empty()  const;
       bool insert(worker_t* entry)  const;
-      ParallelCall*const* get_calls()   const;
+      ParallelWorker*const* get_calls()   const;
     };
 
     template <typename T> inline
diff --git a/DDDigi/include/DDDigi/DigiSegmentSplitter.h b/DDDigi/include/DDDigi/DigiSegmentSplitter.h
index 25c7a9fd971b3dfd68df20487e4fe4519a4744ce..df720166574d037e546b9dd8e30e78fb0bd24621 100644
--- a/DDDigi/include/DDDigi/DigiSegmentSplitter.h
+++ b/DDDigi/include/DDDigi/DigiSegmentSplitter.h
@@ -37,10 +37,6 @@ namespace dd4hep {
     class DigiSegmentSplitter : public DigiContainerSequence   {
     protected:
       using self_t      = DigiSegmentSplitter;
-      using processor_t = DigiSegmentProcessor;
-      using work_t      = processor_t::work_t;
-      using worker_t    = DigiParallelWorker<processor_t, work_t, VolumeID>;
-      using workers_t   = DigiParallelWorkers<worker_t>;
       using split_t     = std::pair<DetElement, VolumeID>;
       using splits_t    = std::map<VolumeID, split_t>;
       friend class DigiParallelWorker<processor_t, work_t, VolumeID>;
@@ -57,17 +53,13 @@ namespace dd4hep {
 
       /**  Member variables  */
       /// Segmentation too instance
-      DigiSegmentationTool m_split_tool;
+      mutable DigiSegmentationTool m_split_tool;
       /// Segmentation split context
       DigiSegmentContext   m_split_context;
       /// Data keys from the readout collection names
       std::vector<Key>     m_keys;
       /// Split elements used to parallelize the processing
       splits_t             m_splits;
-      /// Array of sub-workers
-      workers_t            m_workers;
-      /// Need a lock for possible output merging
-      mutable std::mutex   m_output_lock;
 
     protected:
       /// Default destructor
@@ -81,6 +73,8 @@ namespace dd4hep {
     public:
       /// Standard constructor
       DigiSegmentSplitter(const DigiKernel& kernel, const std::string& name);
+      /// Access the readout collection keys
+      std::vector<std::string> collection_names()   const;
       /// Main functional callback
       virtual void execute(DigiContext& context, work_t& work)  const  override;
     };
diff --git a/DDDigi/include/DDDigi/DigiSegmentationTool.h b/DDDigi/include/DDDigi/DigiSegmentationTool.h
index eb2702b343c7f5a2aba4d2f5aaef1e48e1118e7d..18db270fa71d8e4d19a2382ae56274e75d2ea413 100644
--- a/DDDigi/include/DDDigi/DigiSegmentationTool.h
+++ b/DDDigi/include/DDDigi/DigiSegmentationTool.h
@@ -98,6 +98,8 @@ namespace dd4hep {
       /// Setup tool to handle a given detector of the geometry
       void set_detector(const std::string& det_name);
 
+      /// Access the readout collection keys
+      std::vector<std::string> collection_names()   const;
       /// Access the readout collection keys (mask is empty!)
       std::vector<Key> collection_keys()   const;
       /// Access the readout collection keys with predefined mask
diff --git a/DDDigi/plugins/Components.cpp b/DDDigi/plugins/Components.cpp
index 30a0234786375778fc8a63b2cdbd12e7c2b47ce2..abfe7880fc80658e1fc2a4a419a6817650d9fc98 100644
--- a/DDDigi/plugins/Components.cpp
+++ b/DDDigi/plugins/Components.cpp
@@ -47,8 +47,9 @@ DECLARE_DIGIACTION_NS(dd4hep::digi,DigiLockedAction)
 #include <DDDigi/DigiStoreDump.h>
 DECLARE_DIGIACTION_NS(dd4hep::digi,DigiStoreDump)
 
-#include <DDDigi/DigiHitAttenuatorExp.h>
-DECLARE_DIGIACTION_NS(dd4hep::digi,DigiHitAttenuatorExp)
+#include <DDDigi/DigiAttenuator.h>
+DECLARE_DIGIACTION_NS(dd4hep::digi,DigiAttenuator)
+DECLARE_DIGIACTION_NS(dd4hep::digi,DigiAttenuatorSequence)
 
 #include <DDDigi/DigiContainerCombine.h>
 DECLARE_DIGIACTION_NS(dd4hep::digi,DigiContainerCombine)
diff --git a/DDDigi/plugins/DigiCellMultiplicyCounter.cpp b/DDDigi/plugins/DigiCellMultiplicyCounter.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..843c735aade5540143eb4ba6dd75cbdcb30b5d3b
--- /dev/null
+++ b/DDDigi/plugins/DigiCellMultiplicyCounter.cpp
@@ -0,0 +1,62 @@
+//==========================================================================
+//  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 <DDDigi/DigiContext.h>
+#include <DDDigi/DigiContainerProcessor.h>
+
+/// Namespace for the AIDA detector description toolkit
+namespace dd4hep {
+
+  /// Namespace for the Digitization part of the AIDA detector description toolkit
+  namespace digi {
+
+    /// Actor to select energy deposits according to the supplied segmentation
+    /** Actor to select energy deposits according to the supplied segmentation
+     *
+     *  The selected deposits are placed in the output container
+     *  supplied by the arguments.
+     *
+     *  \author  M.Frank
+     *  \version 1.0
+     *  \ingroup DD4HEP_DIGITIZATION
+     */
+    class DigiCellMultiplicityCounter : public DigiContainerProcessor   {
+    public:
+      /// Standard constructor
+      using DigiContainerProcessor::DigiContainerProcessor;
+
+      template <typename T> void count_deposits(const T& cont)  const  {
+	std::map<CellID, std::size_t> entries;
+	for( const auto& dep : cont )   {
+	  CellID        cell = dep.first;
+	  entries[cell] += 1;
+	}
+	info("+++ %-32s has %6ld entries and %6ld unique cells",
+	     cont.name.c_str(), cont.size(), entries.size());
+      }
+      /// Main functional callback
+      virtual void execute(DigiContext&, work_t& work)  const override final  {
+	if ( const auto* m = work.get_input<DepositMapping>() )
+	  count_deposits(*m);
+	else if ( const auto* v = work.get_input<DepositVector>() )
+	  count_deposits(*v);
+	else
+	  except("Request to handle unknown data type: %s", work.input_type_name().c_str());
+      }
+    };
+  }    // End namespace digi
+}      // End namespace dd4hep
+
+#include <DDDigi/DigiFactories.h>
+DECLARE_DIGIACTION_NS(dd4hep::digi,DigiCellMultiplicityCounter)
diff --git a/DDDigi/plugins/DigiDepositMapCreator.cpp b/DDDigi/plugins/DigiDepositMapCreator.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d420822d33477f4dc8d8c87338ed3d3c4dbf686e
--- /dev/null
+++ b/DDDigi/plugins/DigiDepositMapCreator.cpp
@@ -0,0 +1,68 @@
+//==========================================================================
+//  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 <DDDigi/DigiContext.h>
+#include <DDDigi/DigiContainerProcessor.h>
+
+/// Namespace for the AIDA detector description toolkit
+namespace dd4hep {
+
+  /// Namespace for the Digitization part of the AIDA detector description toolkit
+  namespace digi {
+
+    /// Actor to select energy deposits according to the supplied segmentation
+    /** Actor to select energy deposits according to the supplied segmentation
+     *
+     *  The selected deposits are placed in the output container
+     *  supplied by the arguments.
+     *
+     *  \author  M.Frank
+     *  \version 1.0
+     *  \ingroup DD4HEP_DIGITIZATION
+     */
+    class DigiDepositMapCreator : public DigiContainerProcessor   {
+    public:
+      /// Standard constructor
+      using DigiContainerProcessor::DigiContainerProcessor;
+
+      template <typename T> void create_deposits(const T& cont, work_t& work)  const  {
+	Key key(cont.name, work.output.mask);
+	DepositMapping* mapping = work.output.data.pointer<DepositMapping>(key);
+	if ( !mapping )   {
+	  DepositMapping m(cont.name, work.output.mask);
+	  work.output.data.put(m.key, std::move(m));
+	  mapping = work.output.data.pointer<DepositMapping>(key);
+	}
+	std::size_t start = mapping->size();
+	for( const auto& dep : cont )
+	  mapping->data.emplace(dep.first, EnergyDeposit());
+	std::size_t end   = mapping->size();
+	info("+++ %-32s added %6ld entries (now: %6ld) from mask: %04X to mask: %04X",
+	     cont.name.c_str(), end-start, end, cont.key.mask(), mapping->key.mask());
+      }
+      /// Main functional callback
+      virtual void execute(DigiContext&, work_t& work)  const override final  {
+	if ( const auto* m = work.get_input<DepositMapping>() )
+	  create_deposits(*m, work);
+	else if ( const auto* v = work.get_input<DepositVector>() )
+	  create_deposits(*v, work);
+	else
+	  except("Request to handle unknown data type: %s", work.input_type_name().c_str());
+      }
+    };
+  }    // End namespace digi
+}      // End namespace dd4hep
+
+#include <DDDigi/DigiFactories.h>
+DECLARE_DIGIACTION_NS(dd4hep::digi,DigiDepositMapCreator)
diff --git a/DDDigi/plugins/DigiSegmentDepositExtractor.cpp b/DDDigi/plugins/DigiSegmentDepositExtractor.cpp
index 2f0999ddfeb1531b5e6cfb7e9afdc5276d02662d..ac3788d30bb034868695a24b1c694c46f0ee5f08 100644
--- a/DDDigi/plugins/DigiSegmentDepositExtractor.cpp
+++ b/DDDigi/plugins/DigiSegmentDepositExtractor.cpp
@@ -37,14 +37,24 @@ namespace dd4hep {
       DigiSegmentDepositExtractor(const DigiKernel& kernel, const std::string& nam)
 	: DigiSegmentProcessor(kernel, nam) {}
 
+      template <typename T> void copy_deposits(const T& cont, work_t& work)  const  {
+	DepositVector deposits(cont.name, work.output.mask);
+	for( const auto& dep : cont )   {
+	  CellID        cell = dep.first;
+	  EnergyDeposit depo = dep.second;
+	  deposits.data.emplace_back(cell, std::move(depo));
+	}
+        work.output.data.put(deposits.key, std::move(deposits));
+      }
       /// Main functional callback
       virtual void handle_segment(DigiContext&, work_t& work)  const override final  {
-	for( const auto& d : work.input )   {
-	  if ( segment.matches(d.first) )   {
-	    CellID        cell = d.first;
-	    EnergyDeposit depo = d.second;
-	    work.emplace_output(cell, std::move(depo));
-	  }
+	if ( segment.matches(work.input.key.key) )   {
+	  if ( const auto* m = work.get_input<DepositMapping>() )
+	    copy_deposits(*m, work);
+	  else if ( const auto* v = work.get_input<DepositVector>() )
+	    copy_deposits(*v, work);
+	  else
+	    except("Request to handle unknown data type: %s", work.input_type_name().c_str());
 	}
       }
     };
diff --git a/DDDigi/plugins/DigiSegmentDepositPrint.cpp b/DDDigi/plugins/DigiSegmentDepositPrint.cpp
index 6a5bd23cfc07b5ae6cc139031e55701cddd623ba..e4046cfe8feb851fc4eed362bea7fdfb71952de2 100644
--- a/DDDigi/plugins/DigiSegmentDepositPrint.cpp
+++ b/DDDigi/plugins/DigiSegmentDepositPrint.cpp
@@ -46,21 +46,17 @@ namespace dd4hep {
 	::snprintf(format, sizeof(format), 
 		   "%s[%s] %s-id: %%d [processor:%d] Cell: %%016lX mask: %016lX  hist:%%4ld hits %%4ld parts. entries deposit: %%f", 
 		   context.event->id(), segment.idspec.name(), segment.cname(), segment.id, segment.split_mask);
-	if ( const auto* m = std::any_cast<DepositMapping>(&work.input) )   {
-	  for( const auto& d : *m )   {
-	    if ( segment.matches(d.first) )
-	      print_deposit(format, d.first, d.second);
-	  }
-	}
-	else if ( const auto* v = std::any_cast<DepositVector>(&work.input) )   {
-	  for( const auto& d : *v )   {
-	    if ( segment.matches(d.first) )
-	      print_deposit(format, d.first, d.second);
-	  }
-	}
-	else   {
-	  error("+++ Request to dump an invalid container %s", Key::key_name(work.key.item()));
-	}
+	auto call = [this, format](const std::pair<CellID,EnergyDeposit>& d)   {
+	  if( this->segment.matches(d.first) )
+	    this->print_deposit(format, d.first, d.second); 
+	};
+	if ( const auto* m = work.get_input<DepositMapping>() )
+	  std::for_each(m->begin(), m->end(), call);
+	else if ( const auto* v = work.get_input<DepositVector>() )
+	  std::for_each(v->begin(), v->end(), call);
+	else
+	  error("+++ Request to dump an invalid container %s",
+		Key::key_name(work.input.key.item()));
       }
     };
   }    // End namespace digi
diff --git a/DDDigi/python/DDDigiDict.C b/DDDigi/python/DDDigiDict.C
index 83f196af506c48b90180ea77d618630db5a018f1..9ba59a6a1e40a066019a3b9e66d048ab1157c2a4 100644
--- a/DDDigi/python/DDDigiDict.C
+++ b/DDDigi/python/DDDigiDict.C
@@ -178,6 +178,7 @@ namespace dd4hep {
 
 #include <DDDigi/DigiSynchronize.h>
 #include <DDDigi/DigiInputAction.h>
+#include <DDDigi/DigiSegmentSplitter.h>
 #include <DDDigi/DigiSegmentProcessor.h>
 #include <DDDigi/DigiActionSequence.h>
 #include <DDDigi/DigiSignalProcessor.h>
@@ -203,14 +204,19 @@ using namespace std;
 #pragma link C++ class dd4hep::digi::DigiAction;
 #pragma link C++ class dd4hep::digi::DigiEventAction;
 #pragma link C++ class dd4hep::digi::DigiInputAction;
-#pragma link C++ class dd4hep::digi::DigiSegmentProcessor;
 #pragma link C++ class dd4hep::digi::DigiActionSequence;
 #pragma link C++ class dd4hep::digi::DigiSynchronize;
 #pragma link C++ class dd4hep::digi::DigiSignalProcessor;
+
 #pragma link C++ class dd4hep::digi::DigiContainerProcessor;
 #pragma link C++ class dd4hep::digi::DigiContainerSequence;
+#pragma link C++ class dd4hep::digi::DigiContainerSequenceAction;
 #pragma link C++ class dd4hep::digi::DigiMultiContainerProcessor;
 
+#pragma link C++ class dd4hep::digi::DigiSegmentProcessor;
+#pragma link C++ class dd4hep::digi::DigiSegmentSequence;
+#pragma link C++ class dd4hep::digi::DigiSegmentSplitter;
+
 /// Digi data item wrappers
 #pragma link C++ class dd4hep::digi::Particle+;
 #pragma link C++ class dd4hep::digi::EnergyDeposit+;
diff --git a/DDDigi/python/dddigi.py b/DDDigi/python/dddigi.py
index 1e45a0dbf47b2a7c358d4d61c1c13ed29b289759..323d6d9d0dd6a9b96682d14363cf0d5b2a5bd22b 100644
--- a/DDDigi/python/dddigi.py
+++ b/DDDigi/python/dddigi.py
@@ -201,13 +201,14 @@ def _adopt_processor_action(self, action, container):
   " Helper to convert DigiActions objects to DigiEventAction "
   print(str(action.__class__))
   attr = getattr(self, 'adopt_processor')
-  if hasattr(action,'I_am_a_ROOT_interface_handle'):
-    print('Entering handle branch')
+  if hasattr(action, 'I_am_a_ROOT_interface_handle'):
     proc = Interface.toContainerProcessor(action.get())
     attr(proc, container)
   else:
-    attr(action, container)
-  print('ContainerProcessor succesfully adopted')
+    proc = action ##Interface.toContainerProcessor(action)
+    print(str(proc.__class__))
+  attr(proc, container)
+  # print('ContainerProcessor succesfully adopted')
 # ---------------------------------------------------------------------------
 
 
diff --git a/DDDigi/python/digitize.py b/DDDigi/python/digitize.py
index b22c00dbc25c45274fb4aaca323619b0df2a5e69..5ba9fa0eec3d988d55d0632ff11872be052ee571 100644
--- a/DDDigi/python/digitize.py
+++ b/DDDigi/python/digitize.py
@@ -136,7 +136,7 @@ class Digitize(dd4hep.Logger):
     self.kernel().configure()
     self.kernel().initialize()
     self.kernel().run()
-    done = krnl.events_done()
+    done = self.kernel().events_done()
     self.kernel().terminate()
     return done
 
diff --git a/DDDigi/src/DigiAttenuator.cpp b/DDDigi/src/DigiAttenuator.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3eb43cde4887b27a65f7898672ce6ae6dbfc05ba
--- /dev/null
+++ b/DDDigi/src/DigiAttenuator.cpp
@@ -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
+//
+//==========================================================================
+
+// Framework include files
+#include <DD4hep/InstanceCount.h>
+#include <DDDigi/DigiData.h>
+#include <DDDigi/DigiKernel.h>
+#include <DDDigi/DigiContext.h>
+#include <DDDigi/DigiPlugins.h>
+#include <DDDigi/DigiAttenuator.h>
+
+/// C/C++ include files
+#include <cmath>
+
+using namespace dd4hep::digi;
+
+/// Exponential decay depending on time offset(t0) and mean signal decay time
+double DigiAttenuationTool::exponential(double t0, double decay_time)  const   {
+  return std::exp(-1e0 * std::abs(t0)/decay_time);
+}
+
+/// Standard constructor
+DigiAttenuator::DigiAttenuator(const DigiKernel& krnl, const std::string& nam)
+  : DigiContainerProcessor(krnl, nam)
+{
+  declareProperty("factor", m_factor);
+  InstanceCount::increment(this);
+}
+
+/// Default destructor
+DigiAttenuator::~DigiAttenuator() {
+  InstanceCount::decrement(this);
+}
+
+/// Attenuator callback for single container
+template <typename T> std::size_t DigiAttenuator::attenuate(T& cont) const {
+  for( auto& c : cont )
+    c.second.deposit *= m_factor;
+  return cont.size();
+}
+
+/// Main functional callback adapter
+void DigiAttenuator::execute(DigiContext& context, work_t& work)  const   {
+  std::size_t count = 0;
+  if ( auto* m = work.get_input<DepositMapping>() )
+    count = this->attenuate(*m);
+  else if ( auto* v = work.get_input<DepositVector>() )
+    count = this->attenuate(*v);
+  Key key { work.input.key };
+  std::string nam = Key::key_name(key)+":";
+  info("%s+++ %-32s mask:%04X item: %08X Attenuated %6ld hits by %8.5f",
+	context.event->id(), nam.c_str(), key.mask(), key.item(), count, m_factor); 
+}
+
+/// Standard constructor
+DigiAttenuatorSequence::DigiAttenuatorSequence(const DigiKernel& krnl, const std::string& nam)
+  : DigiContainerSequenceAction(krnl, nam)
+{
+  declareProperty("processor_type", m_processor_type = "DigiAttenuator");
+  declareProperty("containers",     m_container_attenuation);
+  declareProperty("signal_decay",   m_signal_decay = "exponential");
+  declareProperty("t0",             m_t0);
+  InstanceCount::increment(this);
+}
+
+/// Default destructor
+DigiAttenuatorSequence::~DigiAttenuatorSequence() {
+  InstanceCount::decrement(this);
+}
+
+/// Initialization callback
+void DigiAttenuatorSequence::initialize()   {
+  DigiAttenuationTool tool;
+  if ( m_container_attenuation.empty() )   {
+    warning("+++ No input containers given for attenuation action -- no action taken");
+    return;
+  }
+  for ( const auto& c : m_container_attenuation )   {
+    std::string nam = name() + "." + c.first;
+    double factor = 0e0;
+    switch( ::toupper(m_signal_decay[0]) )   {
+    case 'E':
+      factor = tool.exponential(m_t0, c.second);
+      break;
+    default:
+      except("+++ The attenuation function '%s' is not supported ---> STOP", 
+	     m_signal_decay.c_str());
+      break;
+    }
+    auto* att = createAction<DigiAttenuator>(m_processor_type, m_kernel, nam);
+    if ( !att )   {
+      except("+++ Failed to create signal attenuator: %s of type: %s",
+	     nam.c_str(), m_processor_type.c_str());
+    }
+    att->property("factor").set(factor);
+    adopt_processor(att, c.first);
+  }
+  this->DigiContainerSequenceAction::initialize();
+}
+
+/// Main functional callback
+void DigiAttenuatorSequence::execute(DigiContext& context)  const    {
+  this->DigiContainerSequenceAction::execute(context);
+}
diff --git a/DDDigi/src/DigiAttenuatorSequenceAction.cpp b/DDDigi/src/DigiAttenuatorSequenceAction.cpp
deleted file mode 100644
index 8df1448b9300e75ab723c71da5cb51bcf498f9eb..0000000000000000000000000000000000000000
--- a/DDDigi/src/DigiAttenuatorSequenceAction.cpp
+++ /dev/null
@@ -1,75 +0,0 @@
-//==========================================================================
-//  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
-//
-//==========================================================================
-
-
-///             TODO !
-
-
-// Framework include files
-#include <DD4hep/InstanceCount.h>
-
-#include <DDDigi/DigiData.h>
-#include <DDDigi/DigiKernel.h>
-#include <DDDigi/DigiContext.h>
-#include <DDDigi/DigiAttenuatorSequenceAction.h>
-
-/// C/C++ include files
-#include <cmath>
-
-/// Standard constructor
-dd4hep::digi::DigiAttenuatorSequenceAction::DigiAttenuatorSequenceAction(const DigiKernel& krnl, const std::string& nam)
-  : DigiEventAction(krnl, nam)
-{
-  declareProperty("input",      m_input_segment = "inputs");
-  declareProperty("processor",  m_processor_name);
-  declareProperty("containers", m_container_attenuation);
-  declareProperty("mask",       m_mask);
-  declareProperty("t0",         m_t0);
-  m_kernel.register_initialize(Callback(this).make(&DigiAttenuatorSequenceAction::initialize));
-  InstanceCount::increment(this);
-}
-
-/// Default destructor
-dd4hep::digi::DigiAttenuatorSequenceAction::~DigiAttenuatorSequenceAction() {
-  InstanceCount::decrement(this);
-}
-
-/// Initialization callback
-void dd4hep::digi::DigiAttenuatorSequenceAction::initialize()   {
-  for ( const auto& c : m_container_attenuation )   {
-    double factor = std::exp(-1e0 * m_t0/c.second);
-    m_attenuation.emplace(Key(c.first, m_mask), factor);
-  }
-}
-
-/// Main functional callback
-void dd4hep::digi::DigiAttenuatorSequenceAction::execute(DigiContext& context)  const    {
-  std::size_t count = 0, cnt = 0, cont = 0;
-  auto& event  = *context.event;
-  auto& inputs = event.get_segment(m_input_segment);
-  for ( const auto& k : m_attenuation )     {
-    Key key = k.first;
-    auto* data = inputs.entry(key);
-    if ( auto* m = std::any_cast<DepositMapping>(data) )
-      ++cont;
-    else if ( auto* v = std::any_cast<DepositVector>(data) )
-      cnt++, ++cont;
-    count += cnt;
-    std::string nam = Key::key_name(key)+":";
-    debug("%s+++ %-32s mask:%04X item: %08X Attenuated exponentially %6ld hits by %8.5f",
-	  event.id(), nam.c_str(), key.mask(), key.item(), cnt, k.second); 
-  }
-  info("%s+++ Attenuated exponentially %6ld hits from %4ld containers from segment %s",
-       event.id(), count, cont, m_input_segment.c_str());
-}
-
diff --git a/DDDigi/src/DigiContainerCombine.cpp b/DDDigi/src/DigiContainerCombine.cpp
index 0de723b764f6c285e59ffbe63b8678789cb1b7c3..8d9ec05859a6044c0564dd24e9af6a459306f52a 100644
--- a/DDDigi/src/DigiContainerCombine.cpp
+++ b/DDDigi/src/DigiContainerCombine.cpp
@@ -60,7 +60,7 @@ public:
     format[sizeof(format)-1] = 0;
   }
 
-  template<typename T> void merge_depos(DepositMapping& output, T& input, int thr)  {
+  template<typename T> void merge_depos(DepositVector& output, T& input, int thr)  {
     std::size_t cnt = 0;
     if ( combine->m_erase_combined )
       cnt = output.merge(std::move(input));
@@ -73,7 +73,7 @@ public:
 
   void merge(const std::string& nam, size_t start, int thr)  {
     Key key = keys[start];
-    DepositMapping out(nam, combine->m_deposit_mask);
+    DepositVector out(nam, combine->m_deposit_mask);
     for( std::size_t j = start; j < keys.size(); ++j )   {
       if ( keys[j].item() == key.item() )   {
 	if ( DepositMapping* m = std::any_cast<DepositMapping>(work[j]) )
@@ -157,7 +157,7 @@ DigiContainerCombine::DigiContainerCombine(const DigiKernel& krnl, const std::st
   declareProperty("input_masks",      m_input_masks);
   declareProperty("input_segment",    m_input  = "inputs");
   declareProperty("output_segment",   m_output = "deposits");
-  declareProperty("deposit_mask",     m_deposit_mask);
+  declareProperty("output_mask",      m_deposit_mask);
   declareProperty("output_name_flag", m_output_name_flag);
   declareProperty("erase_combined",   m_erase_combined);
   m_kernel.register_initialize(Callback(this).make(&DigiContainerCombine::initialize));
diff --git a/DDDigi/src/DigiContainerProcessor.cpp b/DDDigi/src/DigiContainerProcessor.cpp
index b3eaa9f10ce690952d4f77de43185f69f7256a24..fe22e51ed4c5bf18cbe6166d43444616aebd96d9 100644
--- a/DDDigi/src/DigiContainerProcessor.cpp
+++ b/DDDigi/src/DigiContainerProcessor.cpp
@@ -23,6 +23,105 @@
 
 using namespace dd4hep::digi;
 
+/// Namespace for the AIDA detector description toolkit
+namespace dd4hep {
+
+  /// Namespace for the Digitization part of the AIDA detector description toolkit
+  namespace digi {
+
+    template <typename T> T* DigiContainerProcessor::work_t::get_input(bool exc)   {
+      if ( input.data.has_value() )  {
+	T* object = std::any_cast<T>(&input.data);
+	if ( object )   {
+	  return object;
+	}
+      }
+      if ( exc )   {
+	dd4hep::except("DigiContainerProcessor",
+		       "+++ Cannot access input %s. Invalid data handle of type: %s",
+		       Key::key_name(input.key).c_str(), input_type_name().c_str());
+      }
+      return nullptr;
+    }
+
+    template <typename T> const T* DigiContainerProcessor::work_t::get_input(bool exc)  const  {
+      if ( input.data.has_value() )  {
+	const T* object = std::any_cast<T>(&input.data);
+	if ( object )   {
+	  return object;
+	}
+      }
+      if ( exc )   {
+	dd4hep::except("DigiContainerProcessor",
+		       "+++ Cannot access input %s. Invalid data handle of type: %s",
+		       Key::key_name(input.key).c_str(), input_type_name().c_str());
+      }
+      return nullptr;
+    }
+#if 0
+    template <typename T> T* DigiContainerProcessor::work_t::get_output()   {
+      if ( !output.data.has_value() )  {
+	T data;
+	output.data = std::move(data);
+      }
+      T* v = std::any_cast<T>(&output.data);
+      if ( v )   {
+	return v;
+      }
+      dd4hep::except("DigiContainerProcessor",
+		     "+++ Cannot access output. Invalid data handle of type: %s",
+		     output_type_name().c_str());
+      return nullptr;
+    }
+#endif
+
+  }    // End namespace digi
+}      // End namespace dd4hep
+
+template       DepositVector*   DigiContainerProcessor::work_t::get_input(bool exc);
+template const DepositVector*   DigiContainerProcessor::work_t::get_input(bool exc)  const;
+template       DepositMapping*  DigiContainerProcessor::work_t::get_input(bool exc);
+template const DepositMapping*  DigiContainerProcessor::work_t::get_input(bool exc)  const;
+template       ParticleMapping* DigiContainerProcessor::work_t::get_input(bool exc);
+template const ParticleMapping* DigiContainerProcessor::work_t::get_input(bool exc)  const;
+
+/// input data type
+const std::type_info& DigiContainerProcessor::work_t::input_type()  const   {
+  return input.data.type();
+}
+
+/// String form of the input data type
+std::string DigiContainerProcessor::work_t::input_type_name()  const   {
+  return typeName(input.data.type());
+}
+
+#if 0
+template       DepositVector*   DigiContainerProcessor::work_t::get_output();
+template       DepositMapping*  DigiContainerProcessor::work_t::get_output();
+template       ParticleMapping* DigiContainerProcessor::work_t::get_output();
+
+/// output data type
+const std::type_info& DigiContainerProcessor::work_t::output_type()  const   {
+  return output.data.type();
+}
+
+/// String form of the output data type
+std::string DigiContainerProcessor::work_t::output_type_name()  const   {
+  return typeName(input.data.type());
+}
+
+/// Merge output data
+void DigiContainerProcessor::work_t::merge_output(DepositVector&& data)   {
+  std::lock_guard<std::mutex> lock(output.lock);
+  this->get_output<DepositVector>()->merge(std::move(data));
+}
+
+void DigiContainerProcessor::work_t::emplace_output(CellID cell, EnergyDeposit&& data)   {
+  std::lock_guard<std::mutex> lock(output.lock);
+  this->get_output<DepositVector>()->emplace(cell, std::move(data));
+}
+#endif
+
 /// Standard constructor
 DigiContainerProcessor::DigiContainerProcessor(const DigiKernel& kernel, const std::string& name)   
   : DigiAction(kernel, name)
@@ -37,7 +136,7 @@ DigiContainerProcessor::~DigiContainerProcessor() {
 
 /// Main functional callback 
 void DigiContainerProcessor::execute(DigiContext& context, work_t& work)  const  {
-  this->execute(context, work.key, work.input);
+  this->execute(context, work.input.key, work.input.data);
 }
 
 /// Main functional callback if specific work is known
@@ -85,8 +184,10 @@ template <> void DigiParallelWorker<DigiContainerProcessor,
 DigiContainerSequenceAction::DigiContainerSequenceAction(const DigiKernel& krnl, const std::string& nam)
   : DigiEventAction(krnl, nam)
 {
-  declareProperty("mask",          m_mask);
+  declareProperty("input_mask",    m_input_mask);
   declareProperty("input_segment", m_input_segment);
+  declareProperty("output_mask",      m_output_mask);
+  declareProperty("output_segment",   m_output_segment);
   m_kernel.register_initialize(Callback(this).make(&DigiContainerSequenceAction::initialize));
   InstanceCount::increment(this);
 }
@@ -101,7 +202,7 @@ void dd4hep::digi::DigiContainerSequenceAction::initialize()   {
   size_t count = 0;
   for( auto& ent : m_registered_processors )   {
     Key key = ent.first;
-    key.set_mask(m_mask);
+    key.set_mask(m_input_mask);
     worker_t* w = new worker_t(ent.second, count++);
     m_registered_workers.emplace(key, w);
     m_workers.insert(w);
@@ -109,38 +210,63 @@ void dd4hep::digi::DigiContainerSequenceAction::initialize()   {
 }
 
 /// Adopt new parallel worker
-void DigiContainerSequenceAction::adopt_processor(DigiContainerProcessor* action, const std::string& container)   {
+void DigiContainerSequenceAction::adopt_processor(DigiContainerProcessor* action,
+						  const std::string& container)
+{
   Key key(container, 0x0);
   auto it = m_registered_processors.find(key);
   if ( it != m_registered_processors.end() )   {
-    except("+++ The action %s was already registered to mask:%04X container:%s!",
-	   action->c_name(), m_mask, container.c_str());
+    if ( action != it->second )   {
+      except("+++ The action %s was already registered to mask:%04X container:%s!",
+	     action->c_name(), m_input_mask, container.c_str());
+    }
+    else   {
+      warning("+++ The action %s was already registered to mask:%04X container:%s!",
+	      action->c_name(), m_input_mask, container.c_str());
+    }
     return;
   }
   action->addRef();
   m_registered_processors.emplace(key, action);
+  info("+++ Adding processor: %s for container: [%016lX] %s",
+       action->c_name(), key.key, container.c_str());
+}
+
+/// Adopt new parallel worker acting on multiple containers
+void DigiContainerSequenceAction::adopt_processor(DigiContainerProcessor* action,
+						  const std::vector<std::string>& containers)
+{
+  info("+++ Adding bulk processor: %s for %ld container", action->c_name(), containers.size());
+  for( const auto& cont : containers )   {
+    adopt_processor(action, cont);
+  }
 }
 
 /// Main functional callback if specific work is known
 void DigiContainerSequenceAction::execute(DigiContext& context)  const   {
-  auto& event  = *context.event;
-  auto& inputs = event.get_segment(m_input_segment);
+  auto& event   = *context.event;
+  auto& inputs  = event.get_segment(m_input_segment);
+  auto& outputs = event.get_segment(m_output_segment);
   std::vector<ParallelWorker*> event_workers;
-  work_t args { context, {}, m_output_lock, {}, this };
+  output_t output { m_output_mask, outputs };
+  work_t   args   { context, {}, output, this };
 
   args.input_items.resize(m_workers.size(), {0, nullptr});
   event_workers.reserve(inputs.size());
   for( auto& i : inputs )   {
     Key key(i.first);
-    auto it = m_registered_workers.find(key);
-    if ( it != m_registered_workers.end() )  {
-      worker_t* w = it->second;
-      //work_item_t itm { key, &(i.second) };
-      event_workers.emplace_back(w);
-      args.input_items[w->options] = { key, &(i.second) };
+    if ( key.mask() == m_input_mask )   {
+      auto it = m_registered_workers.find(key);
+      if ( it != m_registered_workers.end() )  {
+	worker_t* w = it->second;
+	event_workers.emplace_back(w);
+	args.input_items[w->options] = { key, &(i.second) };
+      }
     }
   }
-  m_kernel.submit(&event_workers.at(0), event_workers.size(), &args, m_parallel);
+  if ( !event_workers.empty() )   {
+    m_kernel.submit(&event_workers.at(0), event_workers.size(), &args, m_parallel);
+  }
 }
 
 /// Worker adaptor for caller DigiContainerSequenceAction
@@ -149,7 +275,7 @@ template <> void DigiParallelWorker<DigiContainerProcessor,
 				    std::size_t>::execute(void* data) const  {
   calldata_t* args  = reinterpret_cast<calldata_t*>(data);
   auto& item = args->input_items[this->options];
-  DigiContainerProcessor::work_t work { args->context, item.key, *item.data, args->output_lock, args->output};
+  DigiContainerProcessor::work_t  work { args->context, { item.key, *item.data }, args->output };
   action->execute(args->context, work);
 }
 
@@ -159,6 +285,8 @@ DigiMultiContainerProcessor::DigiMultiContainerProcessor(const DigiKernel& krnl,
 {
   this->declareProperty("input_masks",      m_input_masks);
   this->declareProperty("input_segment",    m_input_segment);
+  this->declareProperty("output_mask",      m_output_mask);
+  this->declareProperty("output_segment",   m_output_segment);
   InstanceCount::increment(this);
 }
 
@@ -208,7 +336,9 @@ void DigiMultiContainerProcessor::execute(DigiContext& context)  const  {
     }
   }
   if ( !work_items.empty() )   {
-    work_t args { context, work_items, m_output_lock, {}, this };
+    auto&    outputs = event.get_segment(m_output_segment);
+    output_t output { m_output_mask, outputs };
+    work_t   args   { context, work_items, output, *this };
     m_kernel.submit(m_workers.get_calls(), m_workers.size(), &args, m_parallel);
   }
 }
@@ -217,19 +347,19 @@ void DigiMultiContainerProcessor::execute(DigiContext& context)  const  {
 template <> void DigiParallelWorker<DigiContainerProcessor,
 				    DigiMultiContainerProcessor::work_t,
 				    std::size_t>::execute(void* data) const  {
-  calldata_t* arg  = reinterpret_cast<calldata_t*>(data);
-  const auto& keys  = arg->parent->worker_keys(this->options);
-  const auto& masks = arg->parent->input_masks();
+  calldata_t* arg   = reinterpret_cast<calldata_t*>(data);
+  const auto& keys  = arg->parent.worker_keys(this->options);
+  const auto& masks = arg->parent.input_masks();
   for( const auto& item : arg->items )  {
     Key key = item.first;
     if ( masks.empty() || std::find(masks.begin(), masks.end(), key.mask()) != masks.end() )  {
       if ( keys.empty() )  {
-	DigiContainerProcessor::work_t work {arg->context, key, *item.second, arg->output_lock, arg->output };
-	action->execute(arg->context, work);
+	DigiContainerProcessor::work_t  work {arg->context, {key, *item.second }, arg->output };
+	action->execute(work.context, work);
       }
       else if ( std::find(keys.begin(), keys.end(), Key(key.item())) != keys.end() )    {
-	DigiContainerProcessor::work_t work {arg->context, key, *item.second, arg->output_lock, arg->output };
-	action->execute(arg->context, work);
+	DigiContainerProcessor::work_t  work {arg->context, {key, *item.second }, arg->output };
+	action->execute(work.context, work);
       }
     }
   }
diff --git a/DDDigi/src/DigiData.cpp b/DDDigi/src/DigiData.cpp
index 2caea66de57ec34771106d2e7a2042d19915ccdb..b0038d7c9695faec00eee855025e14174150b01a 100644
--- a/DDDigi/src/DigiData.cpp
+++ b/DDDigi/src/DigiData.cpp
@@ -65,15 +65,37 @@ std::string Key::key_name(const Key& k)    {
 /// Merge new deposit map onto existing map
 std::size_t DepositVector::merge(DepositVector&& updates)    {
   std::size_t update_size = updates.size();
+  data.reserve(data.size()+updates.size());
   for( auto& c : updates )    {
     data.emplace_back(c);
   }
   return update_size;
 }
 
+/// Merge new deposit map onto existing map (keep inputs)
+std::size_t DepositVector::merge(DepositMapping&& updates)    {
+  std::size_t update_size = updates.size();
+  data.reserve(data.size()+updates.size());
+  for( const auto& c : updates )    {
+    data.emplace_back(c);
+  }
+  return update_size;
+}
+
 /// Merge new deposit map onto existing map (keep inputs)
 std::size_t DepositVector::insert(const DepositVector& updates)    {
   std::size_t update_size = updates.size();
+  data.reserve(data.size()+updates.size());
+  for( const auto& c : updates )    {
+    data.emplace_back(c);
+  }
+  return update_size;
+}
+
+/// Merge new deposit map onto existing map (keep inputs)
+std::size_t DepositVector::insert(const DepositMapping& updates)    {
+  std::size_t update_size = updates.size();
+  data.reserve(data.size()+updates.size());
   for( const auto& c : updates )    {
     data.emplace_back(c);
   }
@@ -85,7 +107,6 @@ std::size_t DepositMapping::merge(DepositVector&& updates)    {
   std::size_t update_size = updates.size();
   for( auto& c : updates )    {
     data.emplace(std::move(c));
-#if 0
     CellID         cell = c.first;
     EnergyDeposit& depo = c.second;
     auto iter = data.find(cell);
@@ -101,7 +122,6 @@ std::size_t DepositMapping::merge(DepositVector&& updates)    {
     to_update.particle_history.insert(to_update.particle_history.end(),
 				      depo.particle_history.begin(),
 				      depo.particle_history.end());
-#endif
   }
   return update_size;
 }
@@ -206,6 +226,16 @@ bool DataSegment::emplace(Key key, std::any&& item)    {
   return ret;
 }
 
+/// Move data items other than std::any to the data segment
+template <typename DATA> bool DataSegment::put(Key key, DATA&& value)   {
+  std::any item = std::make_any<DATA>(std::move(value));
+  return this->emplace(key, std::move(item));
+}
+
+template bool DataSegment::put(Key key, DepositVector&& data);
+template bool DataSegment::put(Key key, DepositMapping&& data);
+template bool DataSegment::put(Key key, ParticleMapping&& data);
+
 /// Remove data item from segment
 bool DataSegment::erase(Key key)    {
   std::lock_guard<std::mutex> l(lock);
@@ -291,19 +321,35 @@ DigiEvent::~DigiEvent()
   InstanceCount::decrement(this);
 }
 
+DataSegment& DigiEvent::access_segment(std::unique_ptr<DataSegment>& segment)   {
+  if ( segment )   {
+    return *segment;
+  }
+  std::lock_guard<std::mutex> guard(m_lock);
+  /// Check again after holding the lock:
+  if ( !segment )   {
+    segment = std::make_unique<DataSegment>(this->m_lock);
+  }
+  return *segment;
+}
+
 /// Retrieve data segment from the event structure
 DataSegment& DigiEvent::get_segment(const std::string& name)   {
   switch(::toupper(name[0]))   {
   case 'I':
-    return this->m_inputs;
+    return access_segment(m_inputs);
+  case 'C':
+    return access_segment(m_counts);
   case 'D':
     switch(::toupper(name[1]))   {
     case 'E':
-      return this->m_deposits;
+      return access_segment(m_deposits);
     default:
-      return this->m_data;
+      return access_segment(m_data);
     }
     break;
+  case 'O':
+    return access_segment(m_outputs);
   default:
     break;
   }
diff --git a/DDDigi/src/DigiHitAttenuatorExp.cpp b/DDDigi/src/DigiHitAttenuatorExp.cpp
deleted file mode 100644
index ffdae21a5cca9b1c3bfe382564193210a18d7ca0..0000000000000000000000000000000000000000
--- a/DDDigi/src/DigiHitAttenuatorExp.cpp
+++ /dev/null
@@ -1,82 +0,0 @@
-//==========================================================================
-//  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/InstanceCount.h>
-
-#include <DDDigi/DigiData.h>
-#include <DDDigi/DigiKernel.h>
-#include <DDDigi/DigiContext.h>
-#include <DDDigi/DigiHitAttenuatorExp.h>
-
-/// C/C++ include files
-#include <cmath>
-
-/// Standard constructor
-dd4hep::digi::DigiHitAttenuatorExp::DigiHitAttenuatorExp(const DigiKernel& krnl, const std::string& nam)
-  : DigiEventAction(krnl, nam)
-{
-  declareProperty("input",      m_input_segment = "inputs");
-  declareProperty("containers", m_container_attenuation);
-  declareProperty("masks",      m_masks);
-  declareProperty("t0",         m_t0);
-  m_kernel.register_initialize(Callback(this).make(&DigiHitAttenuatorExp::initialize));
-  InstanceCount::increment(this);
-}
-
-/// Default destructor
-dd4hep::digi::DigiHitAttenuatorExp::~DigiHitAttenuatorExp() {
-  InstanceCount::decrement(this);
-}
-
-/// Initialization callback
-void dd4hep::digi::DigiHitAttenuatorExp::initialize()   {
-  for ( const auto& c : m_container_attenuation )   {
-    Key key(c.first, 0x0);
-    for ( int m : m_masks )    {
-      double factor = std::exp(-1e0 * m_t0/c.second);
-      key.set_mask(m);
-      m_attenuation.emplace(key.key, factor);
-    }
-  }
-}
-
-/// Attenuator callback for single container
-template <typename T> std::size_t 
-dd4hep::digi::DigiHitAttenuatorExp::attenuate(T* cont, double factor) const {
-  for( auto& c : *cont )
-    c.second.deposit *= factor;
-  return cont->size();
-}
-
-/// Main functional callback
-void dd4hep::digi::DigiHitAttenuatorExp::execute(DigiContext& context)  const    {
-  std::size_t count = 0, cnt = 0, cont = 0;
-  auto& event  = *context.event;
-  auto& inputs = event.get_segment(m_input_segment);
-  for ( const auto& k : m_attenuation )     {
-    Key key = k.first;
-    auto* data = inputs.entry(key);
-    if ( auto* m = std::any_cast<DepositMapping>(data) )
-      cnt += this->attenuate(m, k.second), ++cont;
-    else if ( auto* v = std::any_cast<DepositVector>(data) )
-      cnt += this->attenuate(v, k.second), ++cont;
-    count += cnt;
-    std::string nam = Key::key_name(key)+":";
-    debug("%s+++ %-32s mask:%04X item: %08X Attenuated exponentially %6ld hits by %8.5f",
-	  event.id(), nam.c_str(), key.mask(), key.item(), cnt, k.second); 
-  }
-  info("%s+++ Attenuated exponentially %6ld hits from %4ld containers from segment %s",
-       event.id(), count, cont, m_input_segment.c_str());
-}
-
diff --git a/DDDigi/src/DigiSegmentProcessor.cpp b/DDDigi/src/DigiSegmentProcessor.cpp
index 07064d0cb6d64207fe2fe691278670d6d4116ba0..029753a8c2d1497d7af433a6e4a334e53d1a1387 100644
--- a/DDDigi/src/DigiSegmentProcessor.cpp
+++ b/DDDigi/src/DigiSegmentProcessor.cpp
@@ -18,28 +18,6 @@
 
 using namespace dd4hep::digi;
 
-void DigiSegmentProcessor::work_t::merge_output(DepositVector&& data)   {
-  std::lock_guard<std::mutex> lock(output_lock);
-#if 0
-  if ( !output.get() )   {
-    output.reset(new DepositVector(std::move(data)));
-  }
-  else   {
-    output->merge(std::move(data));
-  }
-#endif
-}
-
-void DigiSegmentProcessor::work_t::emplace_output(CellID cell, EnergyDeposit&& data)   {
-  std::lock_guard<std::mutex> lock(output_lock);
-#if 0
-  if ( !output.get() )   {
-    output.reset(new DepositVector());
-  }
-  output->emplace(cell, std::move(data));
-#endif
-}
-
 /// Standard constructor
 DigiSegmentProcessor::DigiSegmentProcessor(const DigiKernel& krnl, const std::string& nam)
   : DigiContainerProcessor(krnl, nam)
diff --git a/DDDigi/src/DigiSegmentSplitter.cpp b/DDDigi/src/DigiSegmentSplitter.cpp
index 7fbb9a5c332b2ea41be81f6eb84f205003c56fd4..f0cce33a9b094f7fb1b7cdc645db2578900579ec 100644
--- a/DDDigi/src/DigiSegmentSplitter.cpp
+++ b/DDDigi/src/DigiSegmentSplitter.cpp
@@ -39,6 +39,18 @@ DigiSegmentSplitter::~DigiSegmentSplitter() {
   InstanceCount::decrement(this);
 }
 
+/// Retrieve the names of all collection to be accessed
+std::vector<std::string> DigiSegmentSplitter::collection_names()  const   {
+  if ( !m_detector_name.empty() )   {
+    if ( m_splits.empty() )  {
+      m_split_tool.set_detector(m_detector_name);
+    }
+    return m_split_tool.collection_names();
+  }
+  except("+++ collection_names: The detector name is not set. Unable to access readout properties.");
+  return {};
+}
+
 /// Initialization function
 void DigiSegmentSplitter::initialize()   {
   char text[256];
@@ -58,7 +70,7 @@ void DigiSegmentSplitter::initialize()   {
       auto split_id = p.second.second;
       bool ok = false;
       for( const auto* w : workers )   {
-	if ( w->options == split_id )  { ok = true; break; }
+	if ( VolumeID(w->options) == split_id )  { ok = true; break; }
       }
       if ( !ok )   {
 	error("+++ Missing processor for plit ID: %08ld", split_id);
@@ -106,10 +118,10 @@ void DigiSegmentSplitter::adopt_processor(DigiContainerProcessor* action)   {
 
 /// Main functional callback
 void DigiSegmentSplitter::execute(DigiContext& /* context */, work_t& work)  const    {
-  Key unmasked_key(work.key.item());
+  Key key = work.input_key();
+  Key unmasked_key(key.item());
   if ( std::find(m_keys.begin(), m_keys.end(), unmasked_key) != m_keys.end() )   {
-    if ( work.input.has_value() )   {
-      Key key = work.key;
+    if ( work.has_input() )   {
       info("+++ Got hit collection %04X %08X. Prepare processors for %sparallel execution.",
 	   key.mask(), key.item(), m_parallel ? "" : "NON-");
       m_kernel.submit(m_workers.get_group(), m_workers.size(), &work, m_parallel);
diff --git a/DDDigi/src/DigiSegmentationTool.cpp b/DDDigi/src/DigiSegmentationTool.cpp
index 37026cfffad3f36f0b7f70378605dbdabcf5ec5b..be65a2afc2afdcf6ce4524169a56b315e09ef5b9 100644
--- a/DDDigi/src/DigiSegmentationTool.cpp
+++ b/DDDigi/src/DigiSegmentationTool.cpp
@@ -79,6 +79,19 @@ void DigiSegmentationTool::set_detector(const string& det_name)    {
   }
 }
 
+/// Access the readout collection keys
+vector<string> DigiSegmentationTool::collection_names()   const   {
+  if ( this->sensitive.isValid() )    {
+    Readout rd = this->sensitive.readout();
+    vector<string> names = rd.collectionNames();
+    if ( names.empty() ) names.emplace_back(rd.name());
+    return names;
+  }
+  except("DigiSegmentationTool",
+	 "+++ collection_names: Readout not valid. Is the proper detector set ?");
+  return {};
+}
+
 /// Access the readout collection keys
 vector<Key> DigiSegmentationTool::collection_keys()   const   {
   return collection_keys(0x0);
@@ -87,16 +100,9 @@ vector<Key> DigiSegmentationTool::collection_keys()   const   {
 /// 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 collection_names = rd.collectionNames();
-    if ( collection_names.empty() ) collection_names.emplace_back(rd.name());
-    for( const auto& collection : collection_names )
-      keys.emplace_back(Key(collection, mask));
-    return keys;
-  }
-  except("DigiSegmentationTool",
-	 "+++ collection_keys: Readout not valid. Is the proper detector set ?");
+  vector<string> names = collection_names();
+  for( const auto& collection : names )
+    keys.emplace_back(Key(collection, mask));
   return keys;
 }
 
@@ -175,11 +181,12 @@ DigiSegmentationTool::split_segmentation(const string& split_by)  const
 
   ::scan_detector(*this, split_by, segmentation_splits, this->detector, vid, msk);
   printout(INFO,"DigiSegmentationTool",
-	   "%-24s has %ld parallel entries in when splitting by \"%s\"",
+	   "%-24s has %ld parallel entries 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());
+  printout(INFO,"DigiSegmentationTool","%-24s --> Parallel Entries: %s",
+	   det, str.str().c_str());
   return segmentation_splits;
 }
diff --git a/DDDigi/src/DigiStoreDump.cpp b/DDDigi/src/DigiStoreDump.cpp
index 168cc9002232492b1939731bc6e39a3e41521579..f01ae514524a98f17e73503c6e0637561096ed6a 100644
--- a/DDDigi/src/DigiStoreDump.cpp
+++ b/DDDigi/src/DigiStoreDump.cpp
@@ -23,11 +23,13 @@
 dd4hep::digi::DigiStoreDump::DigiStoreDump(const DigiKernel& krnl, const std::string& nam)
   : DigiEventAction(krnl, nam)
 {
-  declareProperty("history",       this->m_dump_history  = false);
-  declareProperty("data_segments", this->m_data_segments);
-  this->m_data_segments.push_back("input");
-  this->m_data_segments.push_back("deposits");
-  this->m_data_segments.push_back("data");
+  declareProperty("history",       m_dump_history  = false);
+  declareProperty("data_segments", m_data_segments);
+  m_data_segments.push_back("input");
+  m_data_segments.push_back("deposits");
+  m_data_segments.push_back("data");
+  m_data_segments.push_back("counts");
+  m_data_segments.push_back("output");
   InstanceCount::increment(this);
 }
 
@@ -80,7 +82,7 @@ void dd4hep::digi::DigiStoreDump::dump(const std::string& tag,
   }
   std::lock_guard<std::mutex> record_lock(m_kernel.global_output_lock());
   for(const auto& s : records)
-    this->info(s.c_str());
+    info(s.c_str());
 }
 
 /// Main functional callback
@@ -88,6 +90,6 @@ void dd4hep::digi::DigiStoreDump::execute(DigiContext& context)  const    {
   const auto& event = context.event;
   for(const auto& segment : this->m_data_segments)   {
     std::string seg = detail::str_upper(segment);
-    this->dump(seg, *event, event->get_segment(segment));
+    dump(seg, *event, event->get_segment(segment));
   }
 }
diff --git a/examples/DDDigi/scripts/DigiTest.py b/examples/DDDigi/scripts/DigiTest.py
index 371608fda9a571bdb1bdbc52d65107182a5cb4b1..f0cfb73a3c7333d633d26973c56c983995319308 100644
--- a/examples/DDDigi/scripts/DigiTest.py
+++ b/examples/DDDigi/scripts/DigiTest.py
@@ -35,19 +35,19 @@ logger = logging.getLogger(__name__)
   F4183035 SiTrackerEndcapHits              : map<long long, EnergyDeposit>
 """
 
-attenuation = {'SiVertexEndcapHits': 15 * ns,
-               'SiVertexBarrelHits': 15 * ns,
-               'SiTrackerForwardHits': 15 * ns,
-               'SiTrackerEndcapHits': 15 * ns,
-               'SiTrackerBarrelHits': 15 * ns,
-               'HcalPlugHits': 15 * ns,
-               'HcalEndcapHits': 15 * ns,
-               'HcalBarrelHits': 15 * ns,
-               'EcalEndcapHits': 15 * ns,
-               'MuonEndcapHits': 15 * ns,
-               'MuonBarrelHits': 15 * ns,
-               'BeamCalHits': 15 * ns,
-               'LumiCalHits': 15 * ns,
+attenuation = {'SiVertexEndcapHits': 50 * ns,
+               'SiVertexBarrelHits': 50 * ns,
+               'SiTrackerForwardHits': 50 * ns,
+               'SiTrackerEndcapHits': 50 * ns,
+               'SiTrackerBarrelHits': 50 * ns,
+               'HcalPlugHits': 50 * ns,
+               'HcalEndcapHits': 50 * ns,
+               'HcalBarrelHits': 50 * ns,
+               'EcalEndcapHits': 50 * ns,
+               'MuonEndcapHits': 50 * ns,
+               'MuonBarrelHits': 50 * ns,
+               'BeamCalHits': 50 * ns,
+               'LumiCalHits': 50 * ns,
            }
 
 
@@ -82,16 +82,19 @@ class Test(dddigi.Digitize):
   def data_containers(self):
     return list(self.attenuation.keys())
 
-  def containers(self, count):
-    conts = []
-    result = []
-    for key in list(self.attenuation.keys()):
-      conts.append(key)
-      if len(conts) == count:
+  def containers(self, count=None):
+    if count:
+      conts = []
+      result = []
+      for key in list(self.attenuation.keys()):
+        conts.append(key)
+        if len(conts) == count:
+          result.append(conts)
+          conts = []
+      if len(conts) > 0:
         result.append(conts)
-        conts = []
-    if len(conts) > 0:
-      result.append(conts)
+    else:
+      result = list(self.attenuation.keys())
     return result
 
   def check_creation(self, objs):
diff --git a/examples/DDDigi/scripts/TestHitProcessing.py b/examples/DDDigi/scripts/TestHitProcessing.py
new file mode 100644
index 0000000000000000000000000000000000000000..ea61322503284434e4a9f86e143ee22e123774fb
--- /dev/null
+++ b/examples/DDDigi/scripts/TestHitProcessing.py
@@ -0,0 +1,66 @@
+# ==========================================================================
+#  AIDA Detector description implementation
+# --------------------------------------------------------------------------
+# Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
+# All rights reserved.
+#
+# For the licensing terms see $DD4hepINSTALL/LICENSE.
+# For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
+#
+# ==========================================================================
+from __future__ import absolute_import
+
+
+def run():
+  import DigiTest
+  digi = DigiTest.Test(geometry=None)
+
+  input = digi.input_action('DigiParallelActionSequence/READER')
+  # ========================================================================================================
+  digi.info('Created SIGNAL input')
+  signal = input.adopt_action('DigiROOTInput/SignalReader', mask=0x0, input=[digi.next_input()])
+  digi.check_creation([signal])
+  # ========================================================================================================
+  digi.info('Creating collision overlays....')
+  # ========================================================================================================
+  overlay = input.adopt_action('DigiSequentialActionSequence/Overlay-1')
+  evtreader = overlay.adopt_action('DigiROOTInput/Read-1', mask=0x1, input=[digi.next_input()])
+  hist_drop = overlay.adopt_action('DigiHitHistoryDrop/Drop-1', masks=[evtreader.mask])
+  digi.check_creation([overlay, evtreader, hist_drop])
+  digi.info('Created input.overlay-1')
+  # ========================================================================================================
+  overlay = input.adopt_action('DigiSequentialActionSequence/Overlay-2')
+  evtreader = overlay.adopt_action('DigiROOTInput/Read-2', mask=0x2, input=[digi.next_input()])
+  hist_drop = overlay.adopt_action('DigiHitHistoryDrop/Drop-2', masks=[evtreader.mask])
+  digi.check_creation([overlay, evtreader, hist_drop])
+  digi.info('Created input.overlay-2')
+  # ========================================================================================================
+  event = digi.event_action('DigiSequentialActionSequence/EventAction')
+  combine = event.adopt_action('DigiContainerCombine/Combine',
+                               parallel=True,
+                               input_masks=[0x0, 0x1, 0x2, 0x3],
+                               output_mask=0xFEED,
+                               output_segment='deposits',
+                               erase_combined=False)
+  combine.erase_combined = True
+  dump = event.adopt_action('DigiStoreDump/StoreDump')
+  proc = event.adopt_action('DigiContainerSequenceAction/HitP1', parallel=True, input_mask=0xFEED, input_segment='deposits')
+  count = digi.create_action('DigiCellMultiplicityCounter/CellCounter')
+  proc.adopt_container_processor(count, digi.containers())
+  proc = event.adopt_action('DigiContainerSequenceAction/HitP2', parallel=True,
+                            input_mask=0xFEED,
+                            input_segment='deposits',
+                            output_mask = 0x0,
+                            output_segment='output')
+  count = digi.create_action('DigiDepositMapCreator/CellCreator')
+  proc.adopt_container_processor(count, digi.containers())
+
+  digi.check_creation([combine, dump, proc])
+  digi.info('Created event.dump')
+
+  # ========================================================================================================
+  digi.run_checked(num_events=5, num_threads=5, parallel=3)
+
+
+if __name__ == '__main__':
+  run()
diff --git a/examples/DDDigi/scripts/TestMultiContainerParallel.py b/examples/DDDigi/scripts/TestMultiContainerParallel.py
index 33ded1c591a68eca15ffc0c483c29b12a26cfa6b..8934b1fb39a4e7089ee043f293a76f1fd7a78b43 100644
--- a/examples/DDDigi/scripts/TestMultiContainerParallel.py
+++ b/examples/DDDigi/scripts/TestMultiContainerParallel.py
@@ -29,10 +29,6 @@ def run():
   for i in range(len(conts)):
     merge = dddigi.Action(digi.kernel(), 'DigiContainerProcessor/SegmentPrint_%03d' % (i,))
     proc.adopt_processor(merge, conts[i])
-
-  # dump = event.adopt_action('DigiStoreDump/StoreDump')
-  # digi.check_creation([combine, dump, splitter])
-  # digi.info('Created event.dump')
   # ========================================================================
   digi.run_checked(num_events=5, num_threads=15, parallel=3)
 
diff --git a/examples/DDDigi/scripts/TestMultiInteractions.py b/examples/DDDigi/scripts/TestMultiInteractions.py
index 35f5152e3877bc7212aee1f6e2dada2640653259..b20a45553f06c12b9d93830499a55a45a9c0b87d 100644
--- a/examples/DDDigi/scripts/TestMultiInteractions.py
+++ b/examples/DDDigi/scripts/TestMultiInteractions.py
@@ -45,7 +45,8 @@ def run():
   combine = event.adopt_action('DigiContainerCombine/Combine',
                                parallel=True,
                                input_masks=[0x0, 0x1, 0x2, 0x3],
-                               deposit_mask=0xFEED,
+                               output_mask=0xFEED,
+                               output_segment='deposits',
                                erase_combined=False)
   combine.erase_combined = True  # Not thread-safe! only do in SequentialActionSequence
   dump = event.adopt_action('DigiStoreDump/StoreDump')
diff --git a/examples/DDDigi/scripts/TestSegmentationSplit.py b/examples/DDDigi/scripts/TestSegmentationSplit.py
index 5283350c200cb38b4f706d11718ade56e55e22d0..fde6a62666ffb1463a6c4d2734e8b0fb44026993 100644
--- a/examples/DDDigi/scripts/TestSegmentationSplit.py
+++ b/examples/DDDigi/scripts/TestSegmentationSplit.py
@@ -23,7 +23,7 @@ def run():
   # ========================================================================
   event = digi.event_action('DigiSequentialActionSequence/EventAction')
   combine = event.adopt_action('DigiContainerCombine/Combine', input_masks=[0x0], deposit_mask=0xFEED)
-  combine.erase_combined = True  # Not thread-safe! only do in SequentialActionSequence
+  combine.erase_combined = False  # Not thread-safe! only do in SequentialActionSequence
   split_action = event.adopt_action('DigiContainerSequenceAction/SplitSequence',
                                     parallel=True,
                                     input_segment='deposits',
@@ -33,7 +33,7 @@ def run():
                                 split_by='layer',
                                 detector='SiTrackerBarrel',
                                 processor_type='DigiSegmentDepositPrint')
-  split_action.adopt_container_processor(splitter, 'SiTrackerBarrelHits')
+  split_action.adopt_container_processor(splitter, splitter.collection_names())
 
   dump = event.adopt_action('DigiStoreDump/StoreDump')
   digi.check_creation([combine, dump, splitter])
diff --git a/examples/DDDigi/scripts/TestSpillover.py b/examples/DDDigi/scripts/TestSpillover.py
index 59471682d41ee49e06197db70d77eff9b07153db..e3ef4562d806ede03f2fd1dbeb5a6b8447383775 100644
--- a/examples/DDDigi/scripts/TestSpillover.py
+++ b/examples/DDDigi/scripts/TestSpillover.py
@@ -27,24 +27,28 @@ def run():
   # ========================================================================================================
   spillover = input.adopt_action('DigiSequentialActionSequence/Spillover-25')
   evtreader = spillover.adopt_action('DigiROOTInput/Reader-25ns', mask=0x1, input=[digi.next_input()])
-  attenuate = spillover.adopt_action('DigiHitAttenuatorExp/Attenuator-25ns',
-                                     t0=-25 * ns, masks=[evtreader.mask], containers=attenuation)
+  attenuate = spillover.adopt_action('DigiAttenuatorSequence/Att-25ns',
+                                     t0=-25 * ns, 
+                                     signal_decay='exponential',
+                                     processor_type='DigiAttenuator',
+                                     mask=evtreader.mask,
+                                     containers=attenuation)
   hist_drop = spillover.adopt_action('DigiHitHistoryDrop/Drop-25ns', masks=[evtreader.mask])
   digi.check_creation([spillover, evtreader, attenuate, hist_drop])
   digi.info('Created input.spillover25')
   # ========================================================================================================
   spillover = input.adopt_action('DigiSequentialActionSequence/Spillover-50')
   evtreader = spillover.adopt_action('DigiROOTInput/Reader-50ns', mask=0x2, input=[digi.next_input()])
-  attenuate = spillover.adopt_action('DigiHitAttenuatorExp/Attenuator-50ns',
-                                     t0=-50 * ns, masks=[evtreader.mask], containers=attenuation)
+  attenuate = spillover.adopt_action('DigiAttenuatorSequence/Att-50ns',
+                                     t0=-50 * ns, mask=evtreader.mask, containers=attenuation)
   hist_drop = spillover.adopt_action('DigiHitHistoryDrop/Drop-50ns', masks=[evtreader.mask])
   digi.check_creation([spillover, evtreader, attenuate, hist_drop])
   digi.info('Created input.spillover50')
   # ========================================================================================================
   spillover = input.adopt_action('DigiSequentialActionSequence/Spillover-75')
   evtreader = spillover.adopt_action('DigiROOTInput/Reader-75ns', mask=0x3, input=[digi.next_input()])
-  attenuate = spillover.adopt_action('DigiHitAttenuatorExp/Attenuator-75ns',
-                                     t0=-75 * ns, masks=[evtreader.mask], containers=attenuation)
+  attenuate = spillover.adopt_action('DigiAttenuatorSequence/Att-75ns',
+                                     t0=-75 * ns, mask=evtreader.mask, containers=attenuation)
   hist_drop = spillover.adopt_action('DigiHitHistoryDrop/Drop-75ns', masks=[evtreader.mask])
   digi.check_creation([spillover, evtreader, attenuate, hist_drop])
   digi.info('Created input.spillover75')
@@ -53,24 +57,24 @@ def run():
   # ========================================================================================================
   spillover = input.adopt_action('DigiSequentialActionSequence/Spillover+25')
   evtreader = spillover.adopt_action('DigiROOTInput/Reader+25ns', mask=0x4, input=[digi.next_input()])
-  attenuate = spillover.adopt_action('DigiHitAttenuatorExp/Attenuator+25ns',
-                                     t0=25 * ns, masks=[evtreader.mask], containers=attenuation)
+  attenuate = spillover.adopt_action('DigiAttenuatorSequence/Att+25ns',
+                                     t0=25 * ns, mask=evtreader.mask, containers=attenuation)
   hist_drop = spillover.adopt_action('DigiHitHistoryDrop/Drop+25ns', masks=[evtreader.mask])
   digi.check_creation([spillover, evtreader, attenuate, hist_drop])
   digi.info('Created input.spillover25')
   # ========================================================================================================
   spillover = input.adopt_action('DigiSequentialActionSequence/Spillover+50')
   evtreader = spillover.adopt_action('DigiROOTInput/Reader+50ns', mask=0x5, input=[digi.next_input()])
-  attenuate = spillover.adopt_action('DigiHitAttenuatorExp/Attenuator+50ns',
-                                     t0=50 * ns, masks=[evtreader.mask], containers=attenuation)
+  attenuate = spillover.adopt_action('DigiAttenuatorSequence/Att+50ns',
+                                     t0=50 * ns, mask=evtreader.mask, containers=attenuation)
   hist_drop = spillover.adopt_action('DigiHitHistoryDrop/Drop_50ns', masks=[evtreader.mask])
   digi.check_creation([spillover, evtreader, attenuate, hist_drop])
   digi.info('Created input.spillover50')
   # ========================================================================================================
   spillover = input.adopt_action('DigiSequentialActionSequence/Spillover+75')
   evtreader = spillover.adopt_action('DigiROOTInput/Reader+75ns', mask=0x6, input=[digi.next_input()])
-  attenuate = spillover.adopt_action('DigiHitAttenuatorExp/Attenuator+75ns',
-                                     t0=75 * ns, masks=[evtreader.mask], containers=attenuation)
+  attenuate = spillover.adopt_action('DigiAttenuatorSequence/Att+75ns',
+                                     t0=75 * ns, mask=evtreader.mask, containers=attenuation)
   hist_drop = spillover.adopt_action('DigiHitHistoryDrop/Drop+75ns', masks=[evtreader.mask])
   digi.check_creation([spillover, evtreader, attenuate, hist_drop])
   digi.info('Created input.spillover75')
@@ -78,7 +82,8 @@ def run():
   event = digi.event_action('DigiSequentialActionSequence/EventAction')
   combine = event.adopt_action('DigiContainerCombine/Combine',
                                input_masks=[0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6],
-                               deposit_mask=0xFEED)
+                               output_mask=0xFEED,
+                               output_segment='deposits')
   combine.erase_combined = True  # Not thread-safe! only do in SequentialActionSequence
   evtdump = event.adopt_action('DigiStoreDump/StoreDump')
   digi.check_creation([combine, evtdump])