From efc8f4cafad0a89e98bcde48ad7fb46cd0ffe0d7 Mon Sep 17 00:00:00 2001
From: Markus Frank <Markus.Frank@cern.ch>
Date: Tue, 3 Dec 2019 19:08:54 +0100
Subject: [PATCH] DDDigi: Add noise generators. plugin manager: inherit c++
 standard and compiler features from ROOT

---
 DDCore/src/gdml/DetElementCreator.cpp         |   5 +-
 DDDigi/include/DDDigi/DigiContext.h           |  16 +-
 DDDigi/include/DDDigi/DigiData.h              |  27 --
 DDDigi/include/DDDigi/DigiExponentialNoise.h  |  50 ++++
 DDDigi/include/DDDigi/DigiGaussianNoise.h     |   9 +-
 DDDigi/include/DDDigi/DigiLandauNoise.h       |  57 ++++
 DDDigi/include/DDDigi/DigiPoissonNoise.h      |  55 ++++
 DDDigi/include/DDDigi/DigiRandomEngine.h      |  64 +++++
 DDDigi/include/DDDigi/DigiRandomGenerator.h   |  77 ++++++
 DDDigi/include/DDDigi/DigiRandomNoise.h       |   2 +-
 DDDigi/include/DDDigi/DigiSegmentation.h      |  47 +++-
 DDDigi/include/DDDigi/DigiSignalProcessor.h   |   3 +-
 .../DDDigi/DigiSignalProcessorSequence.h      |   2 +-
 .../include/DDDigi/DigiSubdetectorSequence.h  |  10 +-
 DDDigi/include/DDDigi/DigiUniformNoise.h      |  52 ++++
 .../DDDigi/segmentations/CartesianGridXY.h    |   2 +-
 .../DDDigi/segmentations/CartesianGridXYZ.h   |   2 +-
 .../segmentations/SegmentationScanner.h       |   2 +-
 .../plugins/CellScanner_CartesianGridXY.cpp   |  32 ++-
 .../plugins/CellScanner_CartesianGridXYZ.cpp  |  14 +-
 DDDigi/src/DigiExponentialNoise.cpp           |  38 +++
 DDDigi/src/DigiGaussianNoise.cpp              |  17 +-
 DDDigi/src/DigiLandauNoise.cpp                |  42 +++
 DDDigi/src/DigiPoissonNoise.cpp               |  41 +++
 DDDigi/src/DigiRandomGenerator.cpp            | 245 ++++++++++++++++++
 DDDigi/src/DigiRandomNoise.cpp                |   2 +-
 DDDigi/src/DigiSignalProcessorSequence.cpp    |   7 +-
 DDDigi/src/DigiSubdetectorSequence.cpp        |  42 +--
 DDDigi/src/DigiUniformNoise.cpp               |  38 +++
 GaudiPluginService/CMakeLists.txt             |  10 +-
 .../DDDigi/src/DigiTestSignalProcessor.cpp    |   7 +-
 31 files changed, 900 insertions(+), 117 deletions(-)
 create mode 100644 DDDigi/include/DDDigi/DigiExponentialNoise.h
 create mode 100644 DDDigi/include/DDDigi/DigiLandauNoise.h
 create mode 100644 DDDigi/include/DDDigi/DigiPoissonNoise.h
 create mode 100644 DDDigi/include/DDDigi/DigiRandomEngine.h
 create mode 100644 DDDigi/include/DDDigi/DigiRandomGenerator.h
 create mode 100644 DDDigi/include/DDDigi/DigiUniformNoise.h
 create mode 100644 DDDigi/src/DigiExponentialNoise.cpp
 create mode 100644 DDDigi/src/DigiLandauNoise.cpp
 create mode 100644 DDDigi/src/DigiPoissonNoise.cpp
 create mode 100644 DDDigi/src/DigiRandomGenerator.cpp
 create mode 100644 DDDigi/src/DigiUniformNoise.cpp

diff --git a/DDCore/src/gdml/DetElementCreator.cpp b/DDCore/src/gdml/DetElementCreator.cpp
index 598217e4a..2edefa2c1 100644
--- a/DDCore/src/gdml/DetElementCreator.cpp
+++ b/DDCore/src/gdml/DetElementCreator.cpp
@@ -96,7 +96,7 @@ namespace dd4hep {
                       int sd_lvl,
                       PrintLevel p);
     /// Default destructor
-    virtual ~DetElementCreator()  throw();
+    virtual ~DetElementCreator();
     /// Callback to output PlacedVolume information of an single Placement
     virtual int operator()(PlacedVolume pv, int level);
     /// Callback to output PlacedVolume information of an entire Placement
@@ -140,8 +140,7 @@ DetElementCreator::DetElementCreator(Detector& desc,
 }
 
 /// Default destructor
-DetElementCreator::~DetElementCreator()  throw()
-{
+DetElementCreator::~DetElementCreator()  {
   Count total;
   stringstream str, id_str;
   const char* pref = detector_volume_match.c_str();
diff --git a/DDDigi/include/DDDigi/DigiContext.h b/DDDigi/include/DDDigi/DigiContext.h
index aac4561ac..3c5c73a89 100644
--- a/DDDigi/include/DDDigi/DigiContext.h
+++ b/DDDigi/include/DDDigi/DigiContext.h
@@ -15,8 +15,12 @@
 
 // Framework incloude files
 #include "DD4hep/Primitives.h"
+#include "DDDigi/DigiRandomGenerator.h"
 #include "DDDigi/DigiData.h"
 
+/// C/C++ include files
+#include <memory>
+
 /// Namespace for the AIDA detector description toolkit
 namespace dd4hep {
 
@@ -82,10 +86,11 @@ namespace dd4hep {
       typedef std::pair<void*, const std::type_info*>   UserFramework;
     protected:
       /// Transient context variable - depending on the thread context: event reference
-      const DigiKernel* m_kernel = 0;
+      const DigiKernel*                 m_kernel = 0;
       /// Reference to transient event
-      DigiEvent*        m_event  = 0;
-
+      DigiEvent*                        m_event  = 0;
+      /// Reference to the random engine for this event
+      std::shared_ptr<DigiRandomGenerator> m_random;
       /// Inhibit default constructor
       DigiContext() = delete;
       /// Inhibit move constructor
@@ -104,8 +109,9 @@ namespace dd4hep {
       /// Access the geant4 event -- valid only between BeginEvent() and EndEvent()!
       DigiEvent& event()  const;
       /// Access the geant4 event by ptr. Must be checked by clients!
-      DigiEvent* eventPtr()  const     { return m_event; }
-
+      DigiEvent* eventPtr()  const                   { return m_event;   }
+      /// Access to the random engine for this event
+      DigiRandomGenerator& randomGenerator()  const  { return *m_random; }
       /// Access to the user framework. Specialized function to be implemented by the client
       template <typename T> T& framework()  const;
       /// Generic framework access
diff --git a/DDDigi/include/DDDigi/DigiData.h b/DDDigi/include/DDDigi/DigiData.h
index 69e739c49..f5cbda932 100644
--- a/DDDigi/include/DDDigi/DigiData.h
+++ b/DDDigi/include/DDDigi/DigiData.h
@@ -201,33 +201,6 @@ namespace dd4hep {
       : object(ptr, vtable<CaloDeposit::FunctionTable,T>())
     {
     }
-
-    /// 
-    /*
-     *
-     *  \author  M.Frank
-     *  \version 1.0
-     *  \ingroup DD4HEP_DIGITIZATION
-     */
-    class DigiCellData   {
-    public:
-      double raw_value  { 0.0 };
-      double delay      { 0.0 };
-      mutable bool kill { false };
-
-      /// Default constructor
-      DigiCellData() = default;
-      /// Default move constructor
-      DigiCellData(DigiCellData&& copy) = default;
-      /// Default copy constructor
-      DigiCellData(const DigiCellData& copy) = default;
-      /// Default destructor
-      virtual ~DigiCellData() = default;
-      /// Default move assignment
-      DigiCellData& operator=(DigiCellData&& copy) = delete;
-      /// Default copy assignment
-      DigiCellData& operator=(const DigiCellData& copy) = delete;      
-    };
     
     /// 
     /*
diff --git a/DDDigi/include/DDDigi/DigiExponentialNoise.h b/DDDigi/include/DDDigi/DigiExponentialNoise.h
new file mode 100644
index 000000000..de131aa51
--- /dev/null
+++ b/DDDigi/include/DDDigi/DigiExponentialNoise.h
@@ -0,0 +1,50 @@
+//==========================================================================
+//  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 DD4HEP_DDDIGI_DIGIEXPONENTIALNOISE_H
+#define DD4HEP_DDDIGI_DIGIEXPONENTIALNOISE_H
+
+/// Framework include files
+#include "DDDigi/DigiSignalProcessor.h"
+
+/// Namespace for the AIDA detector description toolkit
+namespace dd4hep {
+
+  /// Namespace for the Digitization part of the AIDA detector description toolkit
+  namespace digi {
+
+    /// Generic noise source with a exponential distribution with decay to 1/e in tau
+    /**
+     *  \author  M.Frank
+     *  \version 1.0
+     *  \ingroup DD4HEP_DIGITIZATION
+     */
+    class DigiExponentialNoise : public DigiSignalProcessor  {
+    protected:
+      /// Property: Exponential decay time
+      double    m_tau     = 1.0;
+      
+    protected:
+      /// Define standard assignments and constructors
+      DDDIGI_DEFINE_ACTION_CONSTRUCTORS(DigiExponentialNoise);
+
+    public:
+      /// Standard constructor
+      DigiExponentialNoise(const DigiKernel& kernel, const std::string& nam);
+      /// Default destructor
+      virtual ~DigiExponentialNoise();
+      /// Callback to read event exponentialnoise
+      virtual double operator()(DigiContext& context, const DigiCellData& data)  const  override;
+    };
+  }    // End namespace digi
+}      // End namespace dd4hep
+#endif // DD4HEP_DDDIGI_DIGIEXPONENTIALNOISE_H
diff --git a/DDDigi/include/DDDigi/DigiGaussianNoise.h b/DDDigi/include/DDDigi/DigiGaussianNoise.h
index 8b36d807e..e0933b27a 100644
--- a/DDDigi/include/DDDigi/DigiGaussianNoise.h
+++ b/DDDigi/include/DDDigi/DigiGaussianNoise.h
@@ -22,9 +22,6 @@ namespace dd4hep {
   /// Namespace for the Digitization part of the AIDA detector description toolkit
   namespace digi {
 
-    // Forward declarations
-    class DigiGaussianNoise;
-
     /// Generic noise source with a gaussian distribution
     /**
      *  Generate gaussian noise as it appears e.g. from electronic noise
@@ -42,7 +39,7 @@ namespace dd4hep {
       double    m_sigma   = -1.0;
       /// Property: Cut-off parameter. Do nothing if existing energy deposit is below threshold
       double    m_cutoff  = -1.0;
-
+      
     protected:
       /// Define standard assignments and constructors
       DDDIGI_DEFINE_ACTION_CONSTRUCTORS(DigiGaussianNoise);
@@ -52,10 +49,8 @@ namespace dd4hep {
       DigiGaussianNoise(const DigiKernel& kernel, const std::string& nam);
       /// Default destructor
       virtual ~DigiGaussianNoise();
-      /// Initialize the noise source
-      virtual void initialize()  override;
       /// Callback to read event gaussiannoise
-      virtual double operator()(const DigiCellData& data)  const  override;
+      virtual double operator()(DigiContext& context, const DigiCellData& data)  const  override;
     };
   }    // End namespace digi
 }      // End namespace dd4hep
diff --git a/DDDigi/include/DDDigi/DigiLandauNoise.h b/DDDigi/include/DDDigi/DigiLandauNoise.h
new file mode 100644
index 000000000..0d9b268bd
--- /dev/null
+++ b/DDDigi/include/DDDigi/DigiLandauNoise.h
@@ -0,0 +1,57 @@
+//==========================================================================
+//  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 DD4HEP_DDDIGI_DIGILANDAUNOISE_H
+#define DD4HEP_DDDIGI_DIGILANDAUNOISE_H
+
+/// Framework include files
+#include "DDDigi/DigiSignalProcessor.h"
+
+/// Namespace for the AIDA detector description toolkit
+namespace dd4hep {
+
+  /// Namespace for the Digitization part of the AIDA detector description toolkit
+  namespace digi {
+
+    /// Generic noise source with a landau distribution
+    /**
+     *  Generate landau noise as it appears e.g. from electronic noise
+     *  with a given mean and a given sigma
+     *
+     *  \author  M.Frank
+     *  \version 1.0
+     *  \ingroup DD4HEP_DIGITIZATION
+     */
+    class DigiLandauNoise : public DigiSignalProcessor  {
+    protected:
+      /// Property: Mean value of the 
+      double    m_mean    = 0.0;
+      /// Property: Variance of the energy distribution in electron Volt. MANDATORY!
+      double    m_sigma   = -1.0;
+      /// Property: Cut-off parameter. Do nothing if existing energy deposit is below threshold
+      double    m_cutoff  = -1.0;
+      
+    protected:
+      /// Define standard assignments and constructors
+      DDDIGI_DEFINE_ACTION_CONSTRUCTORS(DigiLandauNoise);
+
+    public:
+      /// Standard constructor
+      DigiLandauNoise(const DigiKernel& kernel, const std::string& nam);
+      /// Default destructor
+      virtual ~DigiLandauNoise();
+      /// Callback to read event landaunoise
+      virtual double operator()(DigiContext& context, const DigiCellData& data)  const  override;
+    };
+  }    // End namespace digi
+}      // End namespace dd4hep
+#endif // DD4HEP_DDDIGI_DIGILANDAUNOISE_H
diff --git a/DDDigi/include/DDDigi/DigiPoissonNoise.h b/DDDigi/include/DDDigi/DigiPoissonNoise.h
new file mode 100644
index 000000000..6cb3957ce
--- /dev/null
+++ b/DDDigi/include/DDDigi/DigiPoissonNoise.h
@@ -0,0 +1,55 @@
+//==========================================================================
+//  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 DD4HEP_DDDIGI_DIGIPOISSONNOISE_H
+#define DD4HEP_DDDIGI_DIGIPOISSONNOISE_H
+
+/// Framework include files
+#include "DDDigi/DigiSignalProcessor.h"
+
+/// Namespace for the AIDA detector description toolkit
+namespace dd4hep {
+
+  /// Namespace for the Digitization part of the AIDA detector description toolkit
+  namespace digi {
+
+    /// Generic noise source with a poisson distribution
+    /**
+     *  Generate poisson noise as it appears e.g. from electronic noise
+     *  with a given mean and a given sigma
+     *
+     *  \author  M.Frank
+     *  \version 1.0
+     *  \ingroup DD4HEP_DIGITIZATION
+     */
+    class DigiPoissonNoise : public DigiSignalProcessor  {
+    protected:
+      /// Property: Mean value of the 
+      double    m_mean    = 0.0;
+      /// Property: Cut-off parameter. Do nothing if existing energy deposit is above threshold
+      double    m_cutoff  = -1.0;
+      
+    protected:
+      /// Define standard assignments and constructors
+      DDDIGI_DEFINE_ACTION_CONSTRUCTORS(DigiPoissonNoise);
+
+    public:
+      /// Standard constructor
+      DigiPoissonNoise(const DigiKernel& kernel, const std::string& nam);
+      /// Default destructor
+      virtual ~DigiPoissonNoise();
+      /// Callback to read event poissonnoise
+      virtual double operator()(DigiContext& context, const DigiCellData& data)  const  override;
+    };
+  }    // End namespace digi
+}      // End namespace dd4hep
+#endif // DD4HEP_DDDIGI_DIGIPOISSONNOISE_H
diff --git a/DDDigi/include/DDDigi/DigiRandomEngine.h b/DDDigi/include/DDDigi/DigiRandomEngine.h
new file mode 100644
index 000000000..6b0a2defc
--- /dev/null
+++ b/DDDigi/include/DDDigi/DigiRandomEngine.h
@@ -0,0 +1,64 @@
+//==========================================================================
+//  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 DD4HEP_DDDIGI_DIGIRANDOMENGINE_H
+#define DD4HEP_DDDIGI_DIGIRANDOMENGINE_H
+#if 0
+/// Framework include files
+
+
+/// C/C++ include files
+#include <random>
+#include <functional>
+
+/// Namespace for the AIDA detector description toolkit
+namespace dd4hep {
+
+  /// Namespace for the Digitization part of the AIDA detector description toolkit
+  namespace digi {
+
+    /// Generic engine source with a random distribution
+    /**
+     *  Generate random engine as it appears e.g. from electronic engine
+     *  with a given mean and a given sigma
+     *
+     *  \author  M.Frank
+     *  \version 1.0
+     *  \ingroup DD4HEP_DIGITIZATION
+     */
+    class DigiRandomEngine {
+    public:
+      typedef unsigned int result_type;
+      std::function<double()> m_generator;
+    public:
+      /// Initializing constructor
+      template <typename ENGINE> DigiRandomEngine(ENGINE* engine);
+      /// Default destructor
+      virtual ~DigiRandomEngine();
+      static constexpr result_type min()   { return std::default_random_engine::min(); }
+      static constexpr result_type max()   { return std::default_random_engine::max(); }
+      static constexpr double      range() { return double(max()) - double(min());     }
+      /// Callback to read event randomengine
+      unsigned int operator()()  const     { return m_generator();                     }
+    };
+    /// Initializing constructor
+    template <typename ENGINE> DigiRandomEngine::DigiRandomEngine(ENGINE* engine)   {
+      m_generator = [this,engine]()  {
+        static constexpr double norm =
+          DigiRandomEngine::range() / (double(ENGINE::max() - ENGINE::min()));
+        return result_type(double((*engine())) * norm);
+      };
+    }
+  }    // End namespace digi
+}      // End namespace dd4hep
+#endif
+#endif // DD4HEP_DDDIGI_DIGIRANDOMENGINE_H
diff --git a/DDDigi/include/DDDigi/DigiRandomGenerator.h b/DDDigi/include/DDDigi/DigiRandomGenerator.h
new file mode 100644
index 000000000..a479c4c7b
--- /dev/null
+++ b/DDDigi/include/DDDigi/DigiRandomGenerator.h
@@ -0,0 +1,77 @@
+//==========================================================================
+//  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 DD4HEP_DDDIGI_DIGIRANDOMGENERATOR_H
+#define DD4HEP_DDDIGI_DIGIRANDOMGENERATOR_H
+
+/// Framework include files
+
+/// C/C++ include files
+#include <functional>
+
+/// Namespace for the AIDA detector description toolkit
+namespace dd4hep {
+
+  /// Namespace for the Digitization part of the AIDA detector description toolkit
+  namespace digi {
+
+    /// Generic generator source with a random distribution
+    /**
+     *  Generate random numbers according to a given distribution
+     *
+     *  Attention:
+     *  ================================================================ 
+     *  Before this distribution generator is usable, the 
+     *  function object 'engine' must be validated!
+     *  ================================================================ 
+     *
+     *  Please note:
+     *  ============
+     *  This code comes straight from the TRandom class of ROOT
+     *  See for details:  https:* root.cern.ch/root/html534/TRandom.html
+     * 
+     *  The basic [0...1] generator is a std::function object to allow users
+     *  to plug their own implementations
+     * 
+     *  I know this is not nice, but I did not see any other way to overcome
+     *  the virtualization mechanism
+     * 
+     *
+     *  \author  M.Frank
+     *  \version 1.0
+     *  \ingroup DD4HEP_DIGITIZATION
+     */
+    class DigiRandomGenerator {
+    public:
+      std::function<double()>  engine;
+    public:
+      /// Initializing constructor
+      DigiRandomGenerator() = default;
+      /// Default destructor
+      virtual ~DigiRandomGenerator() = default;
+      double random()  const;
+      double uniform(double x1 = 1.0)   const;
+      double uniform(double x1, double x2)   const;
+      int    binomial(int ntotal, double probabaility)  const;
+      double exponential(double tau)  const;
+      double gaussian(double mean = 0.0, double sigma = 1.0)  const;
+      double landau  (double mean = 0.0, double sigma = 1.0)  const;
+      double breitWigner(double mean = 0.0, double gamma = 1.0)  const;
+      double poisson(double mean)  const;
+      void	 rannor(float& a, float& b)   const;
+      void	 rannor(double& a, double& b)   const;
+      void   sphere(double& x, double& y, double& z, double r)   const;
+      void   circle(double &x, double &y, double r)  const;
+    };
+  }    // End namespace digi
+}      // End namespace dd4hep
+#endif // DD4HEP_DDDIGI_DIGIRANDOMGENERATOR_H
diff --git a/DDDigi/include/DDDigi/DigiRandomNoise.h b/DDDigi/include/DDDigi/DigiRandomNoise.h
index 8527796a6..bbaf484f1 100644
--- a/DDDigi/include/DDDigi/DigiRandomNoise.h
+++ b/DDDigi/include/DDDigi/DigiRandomNoise.h
@@ -64,7 +64,7 @@ namespace dd4hep {
       /// Initialize the noise source
       virtual void initialize()  override;
       /// Callback to read event randomnoise
-      virtual double operator()(const DigiCellData& data)  const;
+      virtual double operator()(DigiContext& context, const DigiCellData& data)  const  override;
     };
   }    // End namespace digi
 }      // End namespace dd4hep
diff --git a/DDDigi/include/DDDigi/DigiSegmentation.h b/DDDigi/include/DDDigi/DigiSegmentation.h
index cdad0fa57..aa04d9e6c 100644
--- a/DDDigi/include/DDDigi/DigiSegmentation.h
+++ b/DDDigi/include/DDDigi/DigiSegmentation.h
@@ -27,18 +27,41 @@ namespace dd4hep {
   /// Namespace for the Digitization part of the AIDA detector description toolkit
   namespace digi {
 
-    // Forward declarations
-
-    class CellDataBase  {
-    public:
-      CellID cell_id {0};
-      PlacedVolume  placement;
-      Volume        volume;
-      Solid         solid;
-    };
+    /// Forward declarations
+    class DigiContext;
+    class DigiSegmentation;
     template <typename SEGMENTATION> class cell_data;
-    template <typename SEGMENTATION> class segmentation_data;
+    template <typename SEGMENTATION> class segmentation_data;    
     
+    /// 
+    /*
+     *
+     *  \author  M.Frank
+     *  \version 1.0
+     *  \ingroup DD4HEP_DIGITIZATION
+     */
+    class DigiCellData   {
+    public:
+      PlacedVolume  placement  { };
+      Volume        volume     { };
+      Solid         solid      { };
+      CellID        cell_id    { 0 };
+      double        signal     { 0.0 };
+      mutable bool  kill       { false };
+      /// Default constructor
+      DigiCellData() = default;
+      /// Default move constructor
+      DigiCellData(DigiCellData&& copy) = default;
+      /// Default copy constructor
+      DigiCellData(const DigiCellData& copy) = default;
+      /// Default destructor
+      virtual ~DigiCellData() = default;
+      /// Default move assignment
+      DigiCellData& operator=(DigiCellData&& copy) = delete;
+      /// Default copy assignment
+      DigiCellData& operator=(const DigiCellData& copy) = delete;      
+    };
+
     template <typename SEGMENTATION> 
     void init_segmentation_data(segmentation_data<SEGMENTATION>& data, const Segmentation& seg);
 
@@ -51,11 +74,11 @@ namespace dd4hep {
      */
     class DigiCellScanner  {
     public:
-      typedef std::function<void(const DigiCellScanner& env, const CellDataBase&)> cell_handler_t;
+      typedef std::function<void(DigiContext& context, const DigiCellScanner& env, const DigiCellData&)> cell_handler_t;
     public:
       DigiCellScanner() = default;
       virtual ~DigiCellScanner() = default;
-      virtual void operator()(PlacedVolume pv, VolumeID vid, const cell_handler_t& cell_handler) = 0;
+      virtual void operator()(DigiContext& context, PlacedVolume pv, VolumeID vid, const cell_handler_t& cell_handler) = 0;
     };
     std::shared_ptr<DigiCellScanner> create_cell_scanner(Solid solid, Segmentation segment);
     std::shared_ptr<DigiCellScanner> create_cell_scanner(const std::string& typ, Segmentation segment);
diff --git a/DDDigi/include/DDDigi/DigiSignalProcessor.h b/DDDigi/include/DDDigi/DigiSignalProcessor.h
index 782d63182..e12b19976 100644
--- a/DDDigi/include/DDDigi/DigiSignalProcessor.h
+++ b/DDDigi/include/DDDigi/DigiSignalProcessor.h
@@ -25,6 +25,7 @@ namespace dd4hep {
 
     // Forward declarations
     class DigiAction;
+    class DigiContext;
     class DigiCellData;
     class DigiSignalProcessor;
 
@@ -51,7 +52,7 @@ namespace dd4hep {
       /// Initialize the noise source
       virtual void initialize();
       /// Callback to read event signalprocessor
-      virtual double operator()(const DigiCellData& data)  const = 0;
+      virtual double operator()(DigiContext& context, const DigiCellData& data)  const = 0;
     };
   }    // End namespace digi
 }      // End namespace dd4hep
diff --git a/DDDigi/include/DDDigi/DigiSignalProcessorSequence.h b/DDDigi/include/DDDigi/DigiSignalProcessorSequence.h
index 0a55aea2b..34637842c 100644
--- a/DDDigi/include/DDDigi/DigiSignalProcessorSequence.h
+++ b/DDDigi/include/DDDigi/DigiSignalProcessorSequence.h
@@ -57,7 +57,7 @@ namespace dd4hep {
       /// Adopt a new action as part of the sequence. Sequence takes ownership.
       void adopt(DigiSignalProcessor* action);
       /// Begin-of-event callback
-      virtual double operator()(const DigiCellData& data)  const override;
+      virtual double operator()(DigiContext& context, const DigiCellData& data)  const override;
     };
 
   }    // End namespace digi
diff --git a/DDDigi/include/DDDigi/DigiSubdetectorSequence.h b/DDDigi/include/DDDigi/DigiSubdetectorSequence.h
index 03ffaed76..6efbfcd06 100644
--- a/DDDigi/include/DDDigi/DigiSubdetectorSequence.h
+++ b/DDDigi/include/DDDigi/DigiSubdetectorSequence.h
@@ -35,8 +35,8 @@ namespace dd4hep {
   namespace digi {
 
     // Forward declarations
+    class DigiCellData;
     class DigiCellScanner;
-    class CellDataBase;
     class DigiEventAction;
     class DigiSubdetectorSequence;
 
@@ -76,7 +76,7 @@ namespace dd4hep {
       std::map<VolumeID, Context>    m_parallelVid;
       Scanners                       m_scanners;
 
-      std::function<void(const DigiCellScanner&, const CellDataBase&)> m_cellHandler;
+      std::function<void(DigiContext& context, const DigiCellScanner&, const DigiCellData&)> m_cellHandler;
 
     protected:
       /// Define standard assignments and constructors
@@ -90,10 +90,12 @@ namespace dd4hep {
 
       typedef PlacedVolume::VolIDs             VolIDs;
 
-      void process_cell(const DigiCellScanner& , const CellDataBase& data)  const;
+      void process_cell(DigiContext&           context,
+                        const DigiCellScanner& scanner,
+                        const DigiCellData&    data)  const;
       void scan_detector(DetElement de, VolumeID vid, VolumeID mask);
       void scan_sensitive(PlacedVolume pv, VolumeID vid, VolumeID mask);
-      void process_context(const Context& c, PlacedVolume pv, VolumeID vid, VolumeID mask)   const;
+      void process_context(DigiContext& context, const Context& c, PlacedVolume pv, VolumeID vid, VolumeID mask)   const;
       
     public:
       /// Standard constructor
diff --git a/DDDigi/include/DDDigi/DigiUniformNoise.h b/DDDigi/include/DDDigi/DigiUniformNoise.h
new file mode 100644
index 000000000..1fcadf463
--- /dev/null
+++ b/DDDigi/include/DDDigi/DigiUniformNoise.h
@@ -0,0 +1,52 @@
+//==========================================================================
+//  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 DD4HEP_DDDIGI_DIGIUNIFORMNOISE_H
+#define DD4HEP_DDDIGI_DIGIUNIFORMNOISE_H
+
+/// Framework include files
+#include "DDDigi/DigiSignalProcessor.h"
+
+/// Namespace for the AIDA detector description toolkit
+namespace dd4hep {
+
+  /// Namespace for the Digitization part of the AIDA detector description toolkit
+  namespace digi {
+
+    /// Generic noise source with a uniform distribution in interval [m_min, m_max]
+    /**
+     *  \author  M.Frank
+     *  \version 1.0
+     *  \ingroup DD4HEP_DIGITIZATION
+     */
+    class DigiUniformNoise : public DigiSignalProcessor  {
+    protected:
+      /// Property: Mean value of the 
+      double    m_min     = 0.0;
+      /// Property: Variance of the energy distribution in electron Volt. MANDATORY!
+      double    m_max     = -1.0;
+      
+    protected:
+      /// Define standard assignments and constructors
+      DDDIGI_DEFINE_ACTION_CONSTRUCTORS(DigiUniformNoise);
+
+    public:
+      /// Standard constructor
+      DigiUniformNoise(const DigiKernel& kernel, const std::string& nam);
+      /// Default destructor
+      virtual ~DigiUniformNoise();
+      /// Callback to read event uniformnoise
+      virtual double operator()(DigiContext& context, const DigiCellData& data)  const  override;
+    };
+  }    // End namespace digi
+}      // End namespace dd4hep
+#endif // DD4HEP_DDDIGI_DIGIUNIFORMNOISE_H
diff --git a/DDDigi/include/DDDigi/segmentations/CartesianGridXY.h b/DDDigi/include/DDDigi/segmentations/CartesianGridXY.h
index 3030bf5bf..0c8b1a095 100644
--- a/DDDigi/include/DDDigi/segmentations/CartesianGridXY.h
+++ b/DDDigi/include/DDDigi/segmentations/CartesianGridXY.h
@@ -24,7 +24,7 @@ namespace dd4hep {
   /// Namespace for the Digitization part of the AIDA detector description toolkit
   namespace digi {
 
-    template <> class cell_data<CartesianGridXY> : public CellDataBase {
+    template <> class cell_data<CartesianGridXY> : public DigiCellData {
     public:
       CellID x_cid {0}, y_cid {0};
       CellID x_bin {0}, y_bin {0};
diff --git a/DDDigi/include/DDDigi/segmentations/CartesianGridXYZ.h b/DDDigi/include/DDDigi/segmentations/CartesianGridXYZ.h
index 6c65a9cab..050cb02bf 100644
--- a/DDDigi/include/DDDigi/segmentations/CartesianGridXYZ.h
+++ b/DDDigi/include/DDDigi/segmentations/CartesianGridXYZ.h
@@ -27,7 +27,7 @@ namespace dd4hep {
   /// Namespace for the Digitization part of the AIDA detector description toolkit
   namespace digi {
 
-    template <> class cell_data<CartesianGridXYZ> : public CellDataBase {
+    template <> class cell_data<CartesianGridXYZ> : public DigiCellData {
     public:
       CellID x_cid {0}, y_cid {0}, z_cid {0};
       CellID x_bin {0}, y_bin {0}, z_bin {0};
diff --git a/DDDigi/include/DDDigi/segmentations/SegmentationScanner.h b/DDDigi/include/DDDigi/segmentations/SegmentationScanner.h
index 80ce58378..ff7b15eb5 100644
--- a/DDDigi/include/DDDigi/segmentations/SegmentationScanner.h
+++ b/DDDigi/include/DDDigi/segmentations/SegmentationScanner.h
@@ -43,7 +43,7 @@ namespace dd4hep {
       CellScanner(segmentation_t seg)   {
         init_segmentation_data<segmentation_t>(segment, seg);
       }
-      virtual void operator()(PlacedVolume pv, VolumeID vid, const cell_handler_t& cell_handler)  override;
+      virtual void operator()(DigiContext& context, PlacedVolume pv, VolumeID vid, const cell_handler_t& cell_handler)  override;
     };
   }    // End namespace digi
 }      // End namespace dd4hep
diff --git a/DDDigi/plugins/CellScanner_CartesianGridXY.cpp b/DDDigi/plugins/CellScanner_CartesianGridXY.cpp
index 365d6590b..fc09db9da 100644
--- a/DDDigi/plugins/CellScanner_CartesianGridXY.cpp
+++ b/DDDigi/plugins/CellScanner_CartesianGridXY.cpp
@@ -42,7 +42,7 @@ namespace dd4hep {
     }
     
     template <typename SEGMENTATION, typename SOLID> void
-    CellScanner<SEGMENTATION,SOLID>::operator()(PlacedVolume pv, VolumeID vid, const cell_handler_t& cell_handler) {
+    CellScanner<SEGMENTATION,SOLID>::operator()(DigiContext& context, PlacedVolume pv, VolumeID vid, const cell_handler_t& cell_handler) {
       typename self_t::cell_data_t e;
       e.placement     = pv;
       e.volume        = pv.volume();
@@ -60,7 +60,7 @@ namespace dd4hep {
           if ( !sol->Contains(pos) ) continue;
           e.y_cid = (e.y_bin << segment.y_f_offset) & segment.y_mask;
           e.cell_id = vid | e.x_cid | e.y_cid;
-          cell_handler(*this, e);
+          cell_handler(context, *this, e);
         }
       }
     }
@@ -74,7 +74,7 @@ namespace dd4hep {
   namespace digi {
 
     template <> void
-    CellScanner<CartesianGridXY,Box>::operator()(PlacedVolume pv, VolumeID vid, const cell_handler_t& cell_handler)
+    CellScanner<CartesianGridXY,Box>::operator()(DigiContext& context, PlacedVolume pv, VolumeID vid, const cell_handler_t& cell_handler)
     {
       cell_data_t e;
       e.placement = pv;
@@ -88,7 +88,7 @@ namespace dd4hep {
         for ( e.y_bin = 0; e.y_bin < ny; ++e.y_bin )   {
           e.y_cid = (e.y_bin << segment.y_f_offset) & segment.y_mask;
           e.cell_id = vid | e.x_cid | e.y_cid;
-          cell_handler(*this, e);
+          cell_handler(context, *this, e);
         }
       }
     }
@@ -103,7 +103,12 @@ namespace dd4hep {
   namespace digi {
 
     template <typename self_t> void
-    scan_poly(PlacedVolume pv, VolumeID vid, const typename self_t::cell_handler_t& cell_handler, const self_t& scanner)   {
+    scan_poly(DigiContext& context,
+              PlacedVolume pv,
+              VolumeID vid,
+              const typename self_t::cell_handler_t& cell_handler,
+              const self_t& scanner)
+    {
       typename self_t::cell_data_t e;
       const auto& segment = scanner.segment;
       e.placement     = pv;
@@ -129,22 +134,25 @@ namespace dd4hep {
           if ( !h->Contains(pos)    ) continue;
           e.y_cid = (e.y_bin << segment.y_f_offset) & segment.y_mask;
           e.cell_id = vid | e.x_cid | e.y_cid;
-          cell_handler(scanner, e);
+          cell_handler(context, scanner, e);
         }
       }
     }
 
     template <> void
-    CellScanner<CartesianGridXY,PolyhedraRegular>::operator()(PlacedVolume pv, VolumeID vid, const cell_handler_t& cell_handler) {
-      scan_poly<self_t>(pv, vid, cell_handler, *this);
+    CellScanner<CartesianGridXY,PolyhedraRegular>::operator()(DigiContext& ct, PlacedVolume pv,
+                                                              VolumeID vid, const cell_handler_t& cell_handler) {
+      scan_poly<self_t>(ct, pv, vid, cell_handler, *this);
     }
     template <> void
-    CellScanner<CartesianGridXY,Polyhedra>::operator()(PlacedVolume pv, VolumeID vid, const cell_handler_t& cell_handler) {
-      scan_poly<self_t>(pv, vid, cell_handler, *this);
+    CellScanner<CartesianGridXY,Polyhedra>::operator()(DigiContext& ct, PlacedVolume pv, VolumeID vid,
+                                                       const cell_handler_t& cell_handler) {
+      scan_poly<self_t>(ct, pv, vid, cell_handler, *this);
     }
     template <> void
-    CellScanner<CartesianGridXY,Polycone>::operator()(PlacedVolume pv, VolumeID vid, const cell_handler_t& cell_handler) {
-      scan_poly<self_t>(pv, vid, cell_handler, *this);
+    CellScanner<CartesianGridXY,Polycone>::operator()(DigiContext& ct, PlacedVolume pv, VolumeID vid,
+                                                      const cell_handler_t& cell_handler) {
+      scan_poly<self_t>(ct, pv, vid, cell_handler, *this);
     }
   }    // End namespace digi
 }      // End namespace dd4hep
diff --git a/DDDigi/plugins/CellScanner_CartesianGridXYZ.cpp b/DDDigi/plugins/CellScanner_CartesianGridXYZ.cpp
index 5352303dc..337588d90 100644
--- a/DDDigi/plugins/CellScanner_CartesianGridXYZ.cpp
+++ b/DDDigi/plugins/CellScanner_CartesianGridXYZ.cpp
@@ -46,7 +46,10 @@ namespace dd4hep {
     }
 
     template <typename SEGMENTATION, typename SOLID> void
-    CellScanner<SEGMENTATION,SOLID>::operator()(PlacedVolume pv, VolumeID vid, const cell_handler_t& cell_handler) {
+    CellScanner<SEGMENTATION,SOLID>::operator()(DigiContext&          ct,
+                                                PlacedVolume          pv,
+                                                VolumeID              vid,
+                                                const cell_handler_t& cell_handler) {
       typename self_t::cell_data_t e;
       e.placement     = pv;
       e.volume        = pv.volume();
@@ -69,7 +72,7 @@ namespace dd4hep {
             if ( !sol->Contains(pos) ) continue;
             e.cell_id = vid | e.x_cid | e.y_cid | e.y_cid;
             e.cell_id = vid | e.x_cid | e.y_cid;
-            cell_handler(*this, e);
+            cell_handler(ct, *this, e);
           }
         }
       }
@@ -84,7 +87,10 @@ namespace dd4hep {
   namespace digi {
 
     template <> void
-    CellScanner<CartesianGridXYZ,Box>::operator()(PlacedVolume pv, VolumeID vid, const cell_handler_t& cell_handler)
+    CellScanner<CartesianGridXYZ,Box>::operator()(DigiContext& ct,
+                                                  PlacedVolume pv,
+                                                  VolumeID vid,
+                                                  const cell_handler_t& cell_handler)
     {
       cell_data_t e;
       e.placement = pv;
@@ -101,7 +107,7 @@ namespace dd4hep {
           for ( e.z_bin=0; e.z_bin < nz; ++e.z_bin )   {
             e.z_cid = (e.z_bin << segment.z_f_offset) & segment.z_mask;
             e.cell_id = vid | e.x_cid | e.y_cid | e.y_cid;
-            cell_handler(*this, e);
+            cell_handler(ct, *this, e);
           }
         }
       }
diff --git a/DDDigi/src/DigiExponentialNoise.cpp b/DDDigi/src/DigiExponentialNoise.cpp
new file mode 100644
index 000000000..226bffb11
--- /dev/null
+++ b/DDDigi/src/DigiExponentialNoise.cpp
@@ -0,0 +1,38 @@
+//==========================================================================
+//  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/DigiSegmentation.h"
+#include "DDDigi/DigiRandomGenerator.h"
+#include "DDDigi/DigiExponentialNoise.h"
+
+using namespace dd4hep::digi;
+
+/// Standard constructor
+DigiExponentialNoise::DigiExponentialNoise(const DigiKernel& krnl, const std::string& nam)
+  : DigiSignalProcessor(krnl, nam)
+{
+  declareProperty("tau",     m_tau);
+  InstanceCount::increment(this);
+}
+
+/// Default destructor
+DigiExponentialNoise::~DigiExponentialNoise() {
+  InstanceCount::decrement(this);
+}
+
+/// Callback to read event exponentialnoise
+double DigiExponentialNoise::operator()(DigiContext& context, const DigiCellData&)  const  {
+  return context.randomGenerator().exponential(m_tau);
+}
diff --git a/DDDigi/src/DigiGaussianNoise.cpp b/DDDigi/src/DigiGaussianNoise.cpp
index 054bfd2f2..c07cfe1ee 100644
--- a/DDDigi/src/DigiGaussianNoise.cpp
+++ b/DDDigi/src/DigiGaussianNoise.cpp
@@ -13,6 +13,8 @@
 
 // Framework include files
 #include "DD4hep/InstanceCount.h"
+#include "DDDigi/DigiSegmentation.h"
+#include "DDDigi/DigiRandomGenerator.h"
 #include "DDDigi/DigiGaussianNoise.h"
 
 using namespace dd4hep::digi;
@@ -21,6 +23,9 @@ using namespace dd4hep::digi;
 DigiGaussianNoise::DigiGaussianNoise(const DigiKernel& krnl, const std::string& nam)
   : DigiSignalProcessor(krnl, nam)
 {
+  declareProperty("meam",    m_mean);
+  declareProperty("sigma",   m_sigma);
+  declareProperty("cutoff",  m_cutoff);
   InstanceCount::increment(this);
 }
 
@@ -29,13 +34,9 @@ DigiGaussianNoise::~DigiGaussianNoise() {
   InstanceCount::decrement(this);
 }
 
-/// Initialize the noise source
-void DigiGaussianNoise::initialize()   {
-
-  DigiSignalProcessor::initialize();
-}
-
 /// Callback to read event gaussiannoise
-double DigiGaussianNoise::operator()(const DigiCellData& /* data */)  const    {
-  return 0.0;
+double DigiGaussianNoise::operator()(DigiContext& context, const DigiCellData& data)  const  {
+  if ( data.signal < m_cutoff )
+    return 0;
+  return context.randomGenerator().gaussian(m_mean,m_sigma);
 }
diff --git a/DDDigi/src/DigiLandauNoise.cpp b/DDDigi/src/DigiLandauNoise.cpp
new file mode 100644
index 000000000..cafd804fc
--- /dev/null
+++ b/DDDigi/src/DigiLandauNoise.cpp
@@ -0,0 +1,42 @@
+//==========================================================================
+//  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/DigiLandauNoise.h"
+#include "DDDigi/DigiSegmentation.h"
+#include "DDDigi/DigiRandomGenerator.h"
+
+using namespace dd4hep::digi;
+
+/// Standard constructor
+DigiLandauNoise::DigiLandauNoise(const DigiKernel& krnl, const std::string& nam)
+  : DigiSignalProcessor(krnl, nam)
+{
+  declareProperty("meam",    m_mean);
+  declareProperty("sigma",   m_sigma);
+  declareProperty("cutoff",  m_cutoff);
+  InstanceCount::increment(this);
+}
+
+/// Default destructor
+DigiLandauNoise::~DigiLandauNoise() {
+  InstanceCount::decrement(this);
+}
+
+/// Callback to read event landaunoise
+double DigiLandauNoise::operator()(DigiContext& context, const DigiCellData& data)  const  {
+  if ( data.signal < m_cutoff )
+    return 0;
+  return context.randomGenerator().landau(m_mean,m_sigma);
+}
diff --git a/DDDigi/src/DigiPoissonNoise.cpp b/DDDigi/src/DigiPoissonNoise.cpp
new file mode 100644
index 000000000..85d7acbd4
--- /dev/null
+++ b/DDDigi/src/DigiPoissonNoise.cpp
@@ -0,0 +1,41 @@
+//==========================================================================
+//  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/DigiPoissonNoise.h"
+#include "DDDigi/DigiSegmentation.h"
+#include "DDDigi/DigiRandomGenerator.h"
+
+using namespace dd4hep::digi;
+
+/// Standard constructor
+DigiPoissonNoise::DigiPoissonNoise(const DigiKernel& krnl, const std::string& nam)
+  : DigiSignalProcessor(krnl, nam)
+{
+  declareProperty("meam",    m_mean);
+  declareProperty("cutoff",  m_cutoff);
+  InstanceCount::increment(this);
+}
+
+/// Default destructor
+DigiPoissonNoise::~DigiPoissonNoise() {
+  InstanceCount::decrement(this);
+}
+
+/// Callback to read event poissonnoise
+double DigiPoissonNoise::operator()(DigiContext& context, const DigiCellData& data)  const  {
+  if ( data.signal >= m_cutoff )
+    return 0;
+  return context.randomGenerator().poisson(m_mean);
+}
diff --git a/DDDigi/src/DigiRandomGenerator.cpp b/DDDigi/src/DigiRandomGenerator.cpp
new file mode 100644
index 000000000..984ba26d3
--- /dev/null
+++ b/DDDigi/src/DigiRandomGenerator.cpp
@@ -0,0 +1,245 @@
+//==========================================================================
+//  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
+//
+//==========================================================================
+//
+// Please note: This code comes straight from the TRandom class of ROOT
+// See for details:  https://root.cern.ch/root/html534/TRandom.html
+//
+// The basic [0...1] generator is a std::function object to allow users
+// to plug their own implementations
+//
+// I know this is not nice, but I did not see any other way to overcome
+// the virtualization mechanism
+//
+// M.Frank
+//==========================================================================
+
+// Framework include files
+#include "DDDigi/DigiRandomGenerator.h"
+#include <Math/ProbFuncMathCore.h>
+#include <Math/SpecFuncMathCore.h>
+#include "Math/QuantFuncMathCore.h"
+#include <cmath>
+
+
+using namespace dd4hep::digi;
+
+static constexpr double PIOVER2 = M_PI / 2.0;
+static constexpr double TWOPI   = M_PI * 2.0;
+
+double DigiRandomGenerator::random()  const   {
+  return engine();
+}
+
+double DigiRandomGenerator::uniform(double x1)   const   {
+  double ans = engine();
+  return x1*ans;
+}
+
+double DigiRandomGenerator::uniform(double x1, double x2)   const   {
+  double ans= engine();
+  return x1 + (x2-x1)*ans;
+}
+
+int    DigiRandomGenerator::binomial(int ntot, double prob)  const   {
+  if (prob < 0 || prob > 1) return 0;
+  int n = 0;
+  for (int i=0;i<ntot;i++) {
+    if (engine() > prob) continue;
+    n++;
+  }
+  return n;
+}
+
+double DigiRandomGenerator::exponential(double tau)  const   {
+  double x = engine();              // uniform on ] 0, 1 ]
+  double t = -tau * std::log( x ); // convert to exponential distribution
+  return t;
+}
+
+double DigiRandomGenerator::gaussian(double mean, double sigma)  const   {
+  const double kC1 = 1.448242853;
+  const double kC2 = 3.307147487;
+  const double kC3 = 1.46754004;
+  const double kD1 = 1.036467755;
+  const double kD2 = 5.295844968;
+  const double kD3 = 3.631288474;
+  const double kHm = 0.483941449;
+  const double kZm = 0.107981933;
+  const double kHp = 4.132731354;
+  const double kZp = 18.52161694;
+  const double kPhln = 0.4515827053;
+  const double kHm1 = 0.516058551;
+  const double kHp1 = 3.132731354;
+  const double kHzm = 0.375959516;
+  const double kHzmp = 0.591923442;
+  /*zhm 0.967882898*/
+
+  const double kAs = 0.8853395638;
+  const double kBs = 0.2452635696;
+  const double kCs = 0.2770276848;
+  const double kB  = 0.5029324303;
+  const double kX0 = 0.4571828819;
+  const double kYm = 0.187308492 ;
+  const double kS  = 0.7270572718 ;
+  const double kT  = 0.03895759111;
+
+  double result;
+  double rn,x,y,z;
+
+  do {
+    y = engine();
+
+    if (y>kHm1) {
+      result = kHp*y-kHp1; break; }
+
+    else if (y<kZm) {
+      rn = kZp*y-1;
+      result = (rn>0) ? (1+rn) : (-1+rn);
+      break;
+    }
+
+    else if (y<kHm) {
+      rn = engine();
+      rn = rn-1+rn;
+      z = (rn>0) ? 2-rn : -2-rn;
+      if ((kC1-y)*(kC3+std::abs(z))<kC2) {
+        result = z; break; }
+      else {
+        x = rn*rn;
+        if ((y+kD1)*(kD3+x)<kD2) {
+          result = rn; break; }
+        else if (kHzmp-y<exp(-(z*z+kPhln)/2)) {
+          result = z; break; }
+        else if (y+kHzm<exp(-(x+kPhln)/2)) {
+          result = rn; break; }
+      }
+    }
+
+    while (1) {
+      x = engine();
+      y = kYm * engine();
+      z = kX0 - kS*x - y;
+      if (z>0)
+        rn = 2+y/x;
+      else {
+        x = 1-x;
+        y = kYm-y;
+        rn = -(2+y/x);
+      }
+      if ((y-kAs+x)*(kCs+x)+kBs<0) {
+        result = rn; break; }
+      else if (y<x+kT)
+        if (rn*rn<4*(kB-log(x))) {
+          result = rn; break; }
+    }
+  } while(0);
+
+  return mean + sigma * result;
+}
+
+double DigiRandomGenerator::landau  (double mu, double sigma)  const   {
+  if (sigma <= 0) return 0;
+  double x = engine();
+  double res = mu + ROOT::Math::landau_quantile(x, sigma);
+  return res;
+}
+
+double DigiRandomGenerator::breitWigner(double mean, double gamma)  const   {
+  double rval = 2*engine() - 1;
+  double displ = 0.5*gamma*std::tan(rval*PIOVER2);
+  return (mean+displ);
+}
+
+double DigiRandomGenerator::poisson(double mean)  const   {
+  int n;
+  if (mean <= 0) return 0;
+  if (mean < 25) {
+    double expmean = std::exp(-mean);
+    double pir = 1;
+    n = -1;
+    while(1) {
+      n++;
+      pir *= engine();
+      if (pir <= expmean) break;
+    }
+    return static_cast<double>(n);
+  }
+  // for large value we use inversion method
+  else if (mean < 1E9) {
+    double em, t, y;
+    double sq, alxm, g;
+    double pi = M_PI;
+
+    sq = std::sqrt(2.0*mean);
+    alxm = std::log(mean);
+    g = mean*alxm - ::ROOT::Math::lgamma(mean + 1.0);
+
+    do {
+      do {
+        y = std::tan(pi*engine());
+        em = sq*y + mean;
+      } while( em < 0.0 );
+
+      em = std::floor(em);
+      t = 0.9*(1.0 + y*y)* std::exp(em*alxm - ::ROOT::Math::lgamma(em + 1.0) - g);
+    } while( engine() > t );
+
+    return em;
+
+  } else {
+    // use Gaussian approximation vor very large values
+    return gaussian(0,1)*std::sqrt(mean) + mean +0.5;
+  }
+}
+
+void	 DigiRandomGenerator::rannor(float& a, float& b)   const   {
+  double r, x, y, z;
+
+  y = engine();
+  z = engine();
+  x = z * 6.28318530717958623;
+  r = std::sqrt(-2*std::log(y));
+  a = (float)(r * std::sin(x));
+  b = (float)(r * std::cos(x));
+}
+
+void	 DigiRandomGenerator::rannor(double& a, double& b)   const   {
+  double r, x, y, z;
+
+  y = engine();
+  z = engine();
+  x = z * 6.28318530717958623;
+  r = std::sqrt(-2*std::log(y));
+  a = (float)(r * std::sin(x));
+  b = (float)(r * std::cos(x));
+}
+
+void   DigiRandomGenerator::sphere(double& x, double& y, double& z, double r)   const   {
+  double a=0,b=0,r2=1;
+  while (r2 > 0.25) {
+    a  = engine() - 0.5;
+    b  = engine() - 0.5;
+    r2 =  a*a + b*b;
+  }
+  z = r* ( -1. + 8.0 * r2 );
+
+  double scale = 8.0 * r * std::sqrt(0.25 - r2);
+  x = a*scale;
+  y = b*scale;
+}
+
+void   DigiRandomGenerator::circle(double &x, double &y, double r)   const  {
+  double phi = uniform(0,TWOPI);
+  x = r*std::cos(phi);
+  y = r*std::sin(phi);
+}
diff --git a/DDDigi/src/DigiRandomNoise.cpp b/DDDigi/src/DigiRandomNoise.cpp
index fcfd38675..10ca4b596 100644
--- a/DDDigi/src/DigiRandomNoise.cpp
+++ b/DDDigi/src/DigiRandomNoise.cpp
@@ -38,6 +38,6 @@ void DigiRandomNoise::initialize()   {
 }
 
 /// Callback to read event randomnoise
-double DigiRandomNoise::operator()(const DigiCellData& /* data */)  const    {
+double DigiRandomNoise::operator()(DigiContext& /* context */, const DigiCellData& /* data */)  const {
   return 0.0;
 }
diff --git a/DDDigi/src/DigiSignalProcessorSequence.cpp b/DDDigi/src/DigiSignalProcessorSequence.cpp
index 388ce9ff5..83bc995d4 100644
--- a/DDDigi/src/DigiSignalProcessorSequence.cpp
+++ b/DDDigi/src/DigiSignalProcessorSequence.cpp
@@ -13,6 +13,7 @@
 
 // Framework include files
 #include "DD4hep/InstanceCount.h"
+#include "DDDigi/DigiSegmentation.h"
 #include "DDDigi/DigiSignalProcessorSequence.h"
 
 // C/C++ include files
@@ -43,9 +44,9 @@ void DigiSignalProcessorSequence::adopt(DigiSignalProcessor* action)    {
 }
 
 /// Pre-track action callback
-double DigiSignalProcessorSequence::operator()(const DigiCellData& data)  const   {
-  double result = data.raw_value;
+double DigiSignalProcessorSequence::operator()(DigiContext& context, const DigiCellData& data)  const   {
+  double result = data.signal;
   for ( const auto* p : m_actors )
-    result += p->operator()(data);
+    result += p->operator()(context, data);
   return data.kill ? 0e0 : result;
 }
diff --git a/DDDigi/src/DigiSubdetectorSequence.cpp b/DDDigi/src/DigiSubdetectorSequence.cpp
index e49f4d3da..d2018ac2b 100644
--- a/DDDigi/src/DigiSubdetectorSequence.cpp
+++ b/DDDigi/src/DigiSubdetectorSequence.cpp
@@ -33,8 +33,8 @@ DigiSubdetectorSequence::DigiSubdetectorSequence(const DigiKernel& kernel, const
 {
   declareProperty("detector",m_detectorName);
   declareProperty("parallize_by",m_segmentName);
-  m_cellHandler = [this](const DigiCellScanner& scanner, const CellDataBase& data)  {
-    this->process_cell(scanner, data);
+  m_cellHandler = [this](DigiContext& context, const DigiCellScanner& scanner, const DigiCellData& data)  {
+    this->process_cell(context, scanner, data);
   };
   InstanceCount::increment(this);
 }
@@ -106,7 +106,7 @@ void DigiSubdetectorSequence::scan_detector(DetElement de, VolumeID vid, VolumeI
 }
 
 
-void DigiSubdetectorSequence::process_cell(const DigiCellScanner& , const CellDataBase& data)  const   {
+void DigiSubdetectorSequence::process_cell(DigiContext&, const DigiCellScanner& , const DigiCellData& data)  const   {
 #if 0
   Segmentation seg  = m_sensDet.readout().segmentation();
     string       desc = m_idDesc.str(data.cell_id);
@@ -120,7 +120,12 @@ void DigiSubdetectorSequence::process_cell(const DigiCellScanner& , const CellDa
   }
 }
 
-void DigiSubdetectorSequence::process_context(const Context& c, PlacedVolume pv, VolumeID vid, VolumeID mask)   const  {
+void DigiSubdetectorSequence::process_context(DigiContext& context,
+                                              const Context& c,
+                                              PlacedVolume pv,
+                                              VolumeID vid,
+                                              VolumeID mask)   const
+{
   Volume vol = pv.volume();
   if ( vol.isSensitive() )    {
     auto key = make_pair(vol->GetShape()->IsA(), m_segmentation);
@@ -128,38 +133,33 @@ void DigiSubdetectorSequence::process_context(const Context& c, PlacedVolume pv,
     if ( is == m_scanners.end() )   {
       except("Fatal error in process_context: Invalid cell scanner. vid: %016X",vid);
     }
-    (*(is->second))(pv, vid, m_cellHandler);
+    (*(is->second))(context, pv, vid, m_cellHandler);
     return;
   }
   for (int idau = 0, ndau = pv->GetNdaughters(); idau < ndau; ++idau) {
     PlacedVolume p(pv->GetDaughter(idau));
     const VolIDs& new_ids = p.volIDs();
     if ( !new_ids.empty() )
-      process_context(c, p, vid | m_idDesc.encode(new_ids), mask | m_idDesc.get_mask(new_ids));
+      process_context(context, c, p, vid | m_idDesc.encode(new_ids), mask | m_idDesc.get_mask(new_ids));
     else
-      process_context(c, p, vid, mask);
+      process_context(context, c, p, vid, mask);
   }
 }
 
 /// Pre-track action callback
 void DigiSubdetectorSequence::execute(DigiContext& context)  const   {
-  //static bool first = true;
-  //if ( first )    {
-    for( const auto& d : m_parallelVid )   {
-      const Context& c = d.second;
-      auto vid = c.detector_id;
-      auto det = c.detector;
-      string id_desc   = m_idDesc.str(vid);
-      info("  Order:%-64s    vid:%s %s %s",
-           det.path().c_str(), volumeID(d.first).c_str(), volumeID(vid).c_str(), id_desc.c_str());
-      process_context(c, c.detector.placement(), c.detector_id, c.detector_mask);
-    }
-    //}
-  
+  for( const auto& d : m_parallelVid )   {
+    const Context& c = d.second;
+    auto vid = c.detector_id;
+    auto det = c.detector;
+    string id_desc   = m_idDesc.str(vid);
+    info("  Order:%-64s    vid:%s %s %s",
+         det.path().c_str(), volumeID(d.first).c_str(), volumeID(vid).c_str(), id_desc.c_str());
+    process_context(context, c, c.detector.placement(), c.detector_id, c.detector_mask);
+  }
   this->DigiSynchronize::execute(context);
   debug("+++ Event: %8d (DigiSubdetectorSequence) Parallel: %s Done.",
         context.event().eventNumber, yes_no(m_parallel));
-  //m_end(&context);
 }
 
 /// Access subdetector from the detector description
diff --git a/DDDigi/src/DigiUniformNoise.cpp b/DDDigi/src/DigiUniformNoise.cpp
new file mode 100644
index 000000000..4653560a5
--- /dev/null
+++ b/DDDigi/src/DigiUniformNoise.cpp
@@ -0,0 +1,38 @@
+//==========================================================================
+//  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/DigiRandomGenerator.h"
+#include "DDDigi/DigiUniformNoise.h"
+
+using namespace dd4hep::digi;
+
+/// Standard constructor
+DigiUniformNoise::DigiUniformNoise(const DigiKernel& krnl, const std::string& nam)
+  : DigiSignalProcessor(krnl, nam)
+{
+  declareProperty("minimum", m_min);
+  declareProperty("maximum", m_max);
+  InstanceCount::increment(this);
+}
+
+/// Default destructor
+DigiUniformNoise::~DigiUniformNoise() {
+  InstanceCount::decrement(this);
+}
+
+/// Callback to read event uniformnoise
+double DigiUniformNoise::operator()(DigiContext& context, const DigiCellData& /* data */)  const  {
+  return context.randomGenerator().uniform(m_min,m_max);
+}
diff --git a/GaudiPluginService/CMakeLists.txt b/GaudiPluginService/CMakeLists.txt
index b3196eaa6..30b7cb4e7 100644
--- a/GaudiPluginService/CMakeLists.txt
+++ b/GaudiPluginService/CMakeLists.txt
@@ -1,6 +1,8 @@
 cmake_minimum_required(VERSION 3.3 FATAL_ERROR)
 
 project(GaudiPluginService)
+find_package(ROOT REQUIRED)
+
 add_library(DD4hepGaudiPluginMgr src/PluginServiceV1.cpp src/PluginServiceV2.cpp interface/DD4hepV1.cpp interface/DD4hepV2.cpp)
 add_library(DD4hep::DD4hepGaudiPluginMgr ALIAS DD4hepGaudiPluginMgr)
 
@@ -13,6 +15,9 @@ target_include_directories(DD4hepGaudiPluginMgr PUBLIC
 if( APPLE ) 
   target_compile_definitions(DD4hepGaudiPluginMgr PUBLIC APPLE)
 endif()
+target_compile_features(DD4hepGaudiPluginMgr PRIVATE
+  $<TARGET_PROPERTY:ROOT::Core,INTERFACE_COMPILE_FEATURES>
+)
 target_compile_options(DD4hepGaudiPluginMgr PRIVATE -Wno-shadow
   -Wno-unused
   -Wno-unused-parameter
@@ -28,8 +33,11 @@ add_executable(listcomponents src/listcomponents.cpp )
 add_executable(DD4hep::listcomponents ALIAS listcomponents)
 target_link_libraries(listcomponents PUBLIC DD4hepGaudiPluginMgr ${FS_LIBRARIES} ${CMAKE_DL_LIBS})
 target_compile_options(listcomponents PRIVATE -Wno-deprecated)
+target_compile_features(listcomponents PRIVATE
+  $<TARGET_PROPERTY:ROOT::Core,INTERFACE_COMPILE_FEATURES>
+)
 
 INSTALL(TARGETS listcomponents DD4hepGaudiPluginMgr EXPORT DD4hep
   RUNTIME DESTINATION bin
   ARCHIVE DESTINATION lib
-  LIBRARY DESTINATION lib)
\ No newline at end of file
+  LIBRARY DESTINATION lib)
diff --git a/examples/DDDigi/src/DigiTestSignalProcessor.cpp b/examples/DDDigi/src/DigiTestSignalProcessor.cpp
index e1c24f7da..130818475 100644
--- a/examples/DDDigi/src/DigiTestSignalProcessor.cpp
+++ b/examples/DDDigi/src/DigiTestSignalProcessor.cpp
@@ -48,7 +48,7 @@ namespace dd4hep {
       /// Default destructor
       virtual ~DigiTestSignalProcessor();
       /// Process signal data
-      virtual double operator()(const DigiCellData& data)   const  override;
+      virtual double operator()(DigiContext& context, const DigiCellData& data)   const  override;
     };
 
   }    // End namespace digi
@@ -72,6 +72,7 @@ namespace dd4hep {
 #include "DD4hep/Printout.h"
 #include "DD4hep/InstanceCount.h"
 #include "DDDigi/DigiFactories.h"
+#include "DDDigi/DigiSegmentation.h"
 //#include "DDDigi/DigiTestSignalProcessor.h"
 
 // C/C++ include files
@@ -95,6 +96,6 @@ DigiTestSignalProcessor::~DigiTestSignalProcessor() {
 }
 
 /// Process signal data
-double DigiTestSignalProcessor::operator()(const DigiCellData& data)   const   {
-  return m_attenuation * data.raw_value;
+double DigiTestSignalProcessor::operator()(DigiContext&, const DigiCellData& data)   const   {
+  return m_attenuation * data.signal;
 }
-- 
GitLab