From a6fd70403e60c6592cbbde89e5ef4de4b141be86 Mon Sep 17 00:00:00 2001
From: Chris Jones <jonesc@hep.phy.cam.ac.uk>
Date: Thu, 7 Nov 2024 10:50:08 +0000
Subject: [PATCH] RICH - Add support for using new histograms

---
 Rich/RichFutureKernel/CMakeLists.txt          |  22 +-
 .../RichFutureKernel/RichHistoAlgBase.h       |  11 +-
 .../include/RichFutureKernel/RichHistoBase.h  | 536 +++++++++---------
 .../include/RichFutureKernel/RichHistoUtils.h |  28 -
 Rich/RichFutureKernel/src/RichHistoBase.icpp  | 269 ---------
 .../src/component/RichBaseTests.cpp           | 136 +++++
 .../src/{ => lib}/RichAlgBase.cpp             |   0
 .../src/{ => lib}/RichCommonBase.icpp         |   0
 .../src/{ => lib}/RichHistoAlgBase.cpp        |   2 -
 .../src/lib/RichHistoBase.icpp                |  61 ++
 .../src/{ => lib}/RichHistoToolBase.cpp       |   0
 .../src/{ => lib}/RichToolBase.cpp            |   0
 .../src/{ => lib}/RichTupleAlgBase.cpp        |   0
 .../src/{ => lib}/RichTupleToolBase.cpp       |   0
 .../tests/options/Histograms.py               |  62 ++
 .../tests/qmtest/histograms.qmt               |  22 +
 Rich/RichFutureKernel/tests/refs/empty.ref    |   0
 .../tests/refs/histograms.ref                 | 113 ++++
 18 files changed, 696 insertions(+), 566 deletions(-)
 delete mode 100644 Rich/RichFutureKernel/include/RichFutureKernel/RichHistoUtils.h
 delete mode 100644 Rich/RichFutureKernel/src/RichHistoBase.icpp
 create mode 100644 Rich/RichFutureKernel/src/component/RichBaseTests.cpp
 rename Rich/RichFutureKernel/src/{ => lib}/RichAlgBase.cpp (100%)
 rename Rich/RichFutureKernel/src/{ => lib}/RichCommonBase.icpp (100%)
 rename Rich/RichFutureKernel/src/{ => lib}/RichHistoAlgBase.cpp (94%)
 create mode 100644 Rich/RichFutureKernel/src/lib/RichHistoBase.icpp
 rename Rich/RichFutureKernel/src/{ => lib}/RichHistoToolBase.cpp (100%)
 rename Rich/RichFutureKernel/src/{ => lib}/RichToolBase.cpp (100%)
 rename Rich/RichFutureKernel/src/{ => lib}/RichTupleAlgBase.cpp (100%)
 rename Rich/RichFutureKernel/src/{ => lib}/RichTupleToolBase.cpp (100%)
 create mode 100644 Rich/RichFutureKernel/tests/options/Histograms.py
 create mode 100644 Rich/RichFutureKernel/tests/qmtest/histograms.qmt
 create mode 100644 Rich/RichFutureKernel/tests/refs/empty.ref
 create mode 100644 Rich/RichFutureKernel/tests/refs/histograms.ref

diff --git a/Rich/RichFutureKernel/CMakeLists.txt b/Rich/RichFutureKernel/CMakeLists.txt
index 9cfa4e65356..dda20128527 100644
--- a/Rich/RichFutureKernel/CMakeLists.txt
+++ b/Rich/RichFutureKernel/CMakeLists.txt
@@ -15,12 +15,12 @@ Rich/RichFutureKernel
 
 gaudi_add_library(RichFutureKernel
     SOURCES
-        src/RichAlgBase.cpp
-        src/RichHistoAlgBase.cpp
-        src/RichHistoToolBase.cpp
-        src/RichToolBase.cpp
-        src/RichTupleAlgBase.cpp
-        src/RichTupleToolBase.cpp
+        src/lib/RichAlgBase.cpp
+        src/lib/RichHistoAlgBase.cpp
+        src/lib/RichHistoToolBase.cpp
+        src/lib/RichToolBase.cpp
+        src/lib/RichTupleAlgBase.cpp
+        src/lib/RichTupleToolBase.cpp
     LINK
         PUBLIC
             AIDA::aida
@@ -32,3 +32,13 @@ gaudi_add_library(RichFutureKernel
         PRIVATE
             Gaudi::GaudiUtilsLib
 )
+
+gaudi_add_module(RichFutureKernelTests
+   SOURCES
+        src/component/RichBaseTests.cpp
+   LINK
+        LHCb::LHCbAlgsLib
+        LHCb::RichFutureKernel
+)
+
+gaudi_add_tests(QMTest)
diff --git a/Rich/RichFutureKernel/include/RichFutureKernel/RichHistoAlgBase.h b/Rich/RichFutureKernel/include/RichFutureKernel/RichHistoAlgBase.h
index 30304f3a387..34444215be8 100644
--- a/Rich/RichFutureKernel/include/RichFutureKernel/RichHistoAlgBase.h
+++ b/Rich/RichFutureKernel/include/RichFutureKernel/RichHistoAlgBase.h
@@ -24,7 +24,6 @@
 // Gaudi
 #include "Gaudi/Algorithm.h"
 #include "GaudiAlg/FixTESPath.h"
-#include "GaudiAlg/GaudiHistoAlg.h"
 
 // local
 #include "RichFutureKernel/RichHistoBase.h"
@@ -36,8 +35,10 @@ namespace Rich::Future {
 
   namespace Details {
     /// Basic algorithm class with minimum functionality from legacy GaudiAlg needed by GaudiHistos
-    struct GAUDI_API BaseAlg : FixTESPath<Gaudi::Algorithm> {
+    struct GAUDI_API HistoBaseAlg : FixTESPath<Gaudi::Algorithm> {
       using FixTESPath<Gaudi::Algorithm>::FixTESPath;
+      using FixTESPath<Gaudi::Algorithm>::initialize;
+      using FixTESPath<Gaudi::Algorithm>::finalize;
       StatusCode Print( const std::string& msg,                       //
                         const StatusCode   st  = StatusCode::SUCCESS, //
                         const MSG::Level   lev = MSG::INFO ) const {
@@ -55,12 +56,6 @@ namespace Rich::Future {
         return st;
       }
     };
-    /// Histogramming base a la GaudiAlg, but based on Gaudi::Algorithm
-    struct GAUDI_API HistoBaseAlg : GaudiHistos<BaseAlg> {
-      using GaudiHistos<BaseAlg>::GaudiHistos;
-      using GaudiHistos<BaseAlg>::initialize;
-      using GaudiHistos<BaseAlg>::finalize;
-    };
   } // namespace Details
 
   //-----------------------------------------------------------------------------
diff --git a/Rich/RichFutureKernel/include/RichFutureKernel/RichHistoBase.h b/Rich/RichFutureKernel/include/RichFutureKernel/RichHistoBase.h
index d0030a97669..e7d37a47c05 100644
--- a/Rich/RichFutureKernel/include/RichFutureKernel/RichHistoBase.h
+++ b/Rich/RichFutureKernel/include/RichFutureKernel/RichHistoBase.h
@@ -23,7 +23,6 @@
 
 // Local
 #include "RichFutureKernel/RichCommonBase.h"
-#include "RichFutureKernel/RichHistoUtils.h"
 
 // RichUtils
 #include "RichUtils/RichException.h"
@@ -32,29 +31,234 @@
 #include "RichUtils/RichMap.h"
 
 // Gaudi
+#include "GAUDI_VERSION.h"
 #include "Gaudi/Property.h"
-
-// boost
-#include "boost/array.hpp"
-
-// AIDA
-#include "AIDA/IHistogram1D.h"
-#include "AIDA/IHistogram2D.h"
-//#include "AIDA/IHistogram3D.h"
-#include "AIDA/IProfile1D.h"
-#include "AIDA/IProfile2D.h"
+#if GAUDI_MAJOR_VERSION < 39
+#  include "Gaudi/Accumulators/Histogram.h"
+#else
+#  include "Gaudi/Accumulators/StaticHistogram.h"
+#endif
 
 // STL
+#include <array>
 #include <cassert>
+#include <cstdint>
 #include <mutex>
+#include <optional>
 #include <string>
+#include <tuple>
+#include <type_traits>
 #include <utility>
 #include <vector>
 
 namespace Rich::Future {
 
-  // import histogram utils
-  using namespace Rich::Future::HistoUtils;
+  namespace Hist {
+
+    namespace details {
+      /// Check if a given type is one of a given list.
+      template <typename T, typename... Types>
+      using is_one_of = std::disjunction<std::is_base_of<std::remove_pointer_t<T>, std::remove_pointer_t<Types>>...>;
+      template <typename T, typename... Types>
+      constexpr bool is_one_of_v = is_one_of<T, Types...>::value;
+      ///  Check if it is 'OK' to cast a parameter From -> To
+      template <typename From, typename To>
+      constexpr bool is_safe_cast() {
+        // eventually would like to add proper 'narrowing' type traits here but for now do a few checks
+        constexpr bool is_fp_to_int    = std::is_floating_point_v<From> && std::is_integral_v<To>;
+        constexpr bool is_big_to_small = ( sizeof( From ) > sizeof( To ) );
+        constexpr bool is_signed_int_mismatch =
+            std::is_integral_v<From> && std::is_integral_v<To> && ( std::is_signed_v<From> != std::is_signed_v<To> );
+        constexpr bool from_is_int_or_enum = std::is_arithmetic_v<From> || std::is_enum_v<From>;
+        return ( !is_fp_to_int && !is_big_to_small && !is_signed_int_mismatch && from_is_int_or_enum &&
+                 std::is_arithmetic_v<To> && std::is_convertible_v<From, To> );
+      }
+      /// Check histogram dimensions
+      template <typename T, unsigned int ND, typename I = typename T::value_type::NumberDimensions::value_type>
+      constexpr bool is_dim_v = std::is_same_v<typename T::value_type::NumberDimensions, std::integral_constant<I, ND>>;
+      /// Check histogram types for various arthemtic emplate types
+      template <typename T, template <typename, Gaudi::Accumulators::atomicity> typename H,
+                Gaudi::Accumulators::atomicity ATOMICITY = Gaudi::Accumulators::atomicity::full>
+      constexpr bool is_hist_type_v =
+          is_one_of_v<T, H<float, ATOMICITY>, H<double, ATOMICITY>,                                       //
+                      H<std::int64_t, ATOMICITY>, H<std::int32_t, ATOMICITY>, H<std::int16_t, ATOMICITY>, //
+                      H<std::uint64_t, ATOMICITY>, H<std::uint32_t, ATOMICITY>, H<std::uint16_t, ATOMICITY>>;
+      template <typename T, template <typename, Gaudi::Accumulators::atomicity> typename... Hs>
+      constexpr bool is_one_of_hist_types_v = ( ... || is_hist_type_v<T, Hs> );
+      /// Base class wrapper for all histograms, making them optional.
+      template <typename H>
+      struct BaseH : std::optional<H> {
+        using std::optional<H>::value;
+        using std::optional<H>::has_value;
+        using std::optional<H>::emplace;
+#if GAUDI_MAJOR_VERSION < 39
+        using X = typename H::AxisArithmeticType;
+        [[nodiscard]] auto operator[]( const X arg ) { return this->value()[arg]; }
+        [[nodiscard]] auto operator[]( const std::pair<X, X> arg ) { return this->value()[{arg.first, arg.second}]; }
+#else
+        [[nodiscard]] auto operator[]( typename H::AxisTupleArithmeticType arg ) {
+          return this->value()[std::move( arg )];
+        }
+#endif
+
+        template <unsigned int N>
+        [[nodiscard]] auto& axis() const {
+#if GAUDI_MAJOR_VERSION < 39
+          return this->value().axis()[N];
+#else
+          return this->value().template axis<N>();
+#endif
+        }
+        // Gaudi version here needs updating after
+        // https://gitlab.cern.ch/gaudi/Gaudi/-/merge_requests/1651 is in a release
+#if GAUDI_VERSION >= CALC_GAUDI_VERSION( 39, 0 )
+        template <typename B>
+        struct Buffer : std::optional<B> {
+          [[nodiscard]] auto operator[]( typename H::AxisTupleArithmeticType arg ) {
+            return this->value()[std::move( arg )];
+          }
+        };
+        [[nodiscard]] auto buffer() {
+          using BuffT = decltype( this->value().buffer() );
+          return ( this->has_value() ? Buffer<BuffT>{this->value().buffer()} : Buffer<BuffT>{} );
+        }
+#else
+        // workaround for older v38 Gaudi release where there isa bug in the move semantics
+        // for histograms buffers, that prevents the use of std::optional with them.
+        // Just as a stop gap to allow builds to work here fake a buffer with just references to originals
+        template <typename B>
+        struct Buffer {
+        public:
+          Buffer() = default;
+          Buffer( B& b ) : m_b{&b} {}
+#  if GAUDI_MAJOR_VERSION < 39
+          [[nodiscard]] auto operator[]( const X arg ) { return ( *m_b )[arg]; }
+          [[nodiscard]] auto operator[]( const std::pair<X, X> arg ) { return ( *m_b )[{arg.first, arg.second}]; }
+#  else
+          [[nodiscard]] auto operator[]( typename H::AxisTupleArithmeticType arg ) {
+            return ( *m_b )[std::move( arg )];
+          }
+#  endif
+
+        private:
+          B* m_b = nullptr;
+        };
+        [[nodiscard]] auto buffer() { return ( this->has_value() ? Buffer<H>( this->value() ) : Buffer<H>() ); }
+#endif
+      };
+    } // namespace details
+
+    using DefaultArithmeticType = double;
+
+// Use different gaudi histogram implementation in different Gaudi versions
+#if GAUDI_MAJOR_VERSION < 39
+
+    // 1D histogram types
+    template <typename TYPE                            = DefaultArithmeticType,
+              Gaudi::Accumulators::atomicity ATOMICITY = Gaudi::Accumulators::atomicity::full>
+    using H1D = details::BaseH<Gaudi::Accumulators::Histogram<1, ATOMICITY, TYPE>>;
+    template <typename TYPE                            = DefaultArithmeticType,
+              Gaudi::Accumulators::atomicity ATOMICITY = Gaudi::Accumulators::atomicity::full>
+    using WH1D = details::BaseH<Gaudi::Accumulators::WeightedHistogram<1, ATOMICITY, TYPE>>;
+    template <typename TYPE                            = DefaultArithmeticType,
+              Gaudi::Accumulators::atomicity ATOMICITY = Gaudi::Accumulators::atomicity::full>
+    using P1D = details::BaseH<Gaudi::Accumulators::ProfileHistogram<1, ATOMICITY, TYPE>>;
+    template <typename TYPE                            = DefaultArithmeticType,
+              Gaudi::Accumulators::atomicity ATOMICITY = Gaudi::Accumulators::atomicity::full>
+    using WP1D = details::BaseH<Gaudi::Accumulators::WeightedProfileHistogram<1, ATOMICITY, TYPE>>;
+
+    // 2D histogram types
+    template <typename TYPE                            = DefaultArithmeticType,
+              Gaudi::Accumulators::atomicity ATOMICITY = Gaudi::Accumulators::atomicity::full>
+    using H2D = details::BaseH<Gaudi::Accumulators::Histogram<2, ATOMICITY, TYPE>>;
+    template <typename TYPE                            = DefaultArithmeticType,
+              Gaudi::Accumulators::atomicity ATOMICITY = Gaudi::Accumulators::atomicity::full>
+    using WH2D = details::BaseH<Gaudi::Accumulators::WeightedHistogram<2, ATOMICITY, TYPE>>;
+    template <typename TYPE                            = DefaultArithmeticType,
+              Gaudi::Accumulators::atomicity ATOMICITY = Gaudi::Accumulators::atomicity::full>
+    using P2D = details::BaseH<Gaudi::Accumulators::ProfileHistogram<2, ATOMICITY, TYPE>>;
+    template <typename TYPE                            = DefaultArithmeticType,
+              Gaudi::Accumulators::atomicity ATOMICITY = Gaudi::Accumulators::atomicity::full>
+    using WP2D = details::BaseH<Gaudi::Accumulators::WeightedProfileHistogram<2, ATOMICITY, TYPE>>;
+
+#else
+
+    // 1D histogram types
+    template <typename TYPE = DefaultArithmeticType,
+              Gaudi::Accumulators::atomicity ATOMICITY = Gaudi::Accumulators::atomicity::full>
+    using H1D = details::BaseH<Gaudi::Accumulators::StaticHistogram<1, ATOMICITY, TYPE>>;
+    template <typename TYPE = DefaultArithmeticType,
+              Gaudi::Accumulators::atomicity ATOMICITY = Gaudi::Accumulators::atomicity::full>
+    using WH1D = details::BaseH<Gaudi::Accumulators::StaticWeightedHistogram<1, ATOMICITY, TYPE>>;
+    template <typename TYPE = DefaultArithmeticType,
+              Gaudi::Accumulators::atomicity ATOMICITY = Gaudi::Accumulators::atomicity::full>
+    using P1D = details::BaseH<Gaudi::Accumulators::StaticProfileHistogram<1, ATOMICITY, TYPE>>;
+    template <typename TYPE = DefaultArithmeticType,
+              Gaudi::Accumulators::atomicity ATOMICITY = Gaudi::Accumulators::atomicity::full>
+    using WP1D = details::BaseH<Gaudi::Accumulators::StaticWeightedProfileHistogram<1, ATOMICITY, TYPE>>;
+
+    // 2D histogram types
+    template <typename TYPE = DefaultArithmeticType,
+              Gaudi::Accumulators::atomicity ATOMICITY = Gaudi::Accumulators::atomicity::full>
+    using H2D = details::BaseH<Gaudi::Accumulators::StaticHistogram<2, ATOMICITY, TYPE>>;
+    template <typename TYPE = DefaultArithmeticType,
+              Gaudi::Accumulators::atomicity ATOMICITY = Gaudi::Accumulators::atomicity::full>
+    using WH2D = details::BaseH<Gaudi::Accumulators::StaticWeightedHistogram<2, ATOMICITY, TYPE>>;
+    template <typename TYPE = DefaultArithmeticType,
+              Gaudi::Accumulators::atomicity ATOMICITY = Gaudi::Accumulators::atomicity::full>
+    using P2D = details::BaseH<Gaudi::Accumulators::StaticProfileHistogram<2, ATOMICITY, TYPE>>;
+    template <typename TYPE = DefaultArithmeticType,
+              Gaudi::Accumulators::atomicity ATOMICITY = Gaudi::Accumulators::atomicity::full>
+    using WP2D = details::BaseH<Gaudi::Accumulators::StaticWeightedProfileHistogram<2, ATOMICITY, TYPE>>;
+
+#endif
+
+    // some type traits
+
+    // Histogram Dimensionality
+    template <typename T>
+    constexpr bool is_1d_v = details::is_dim_v<T, 1>;
+    template <typename T>
+    constexpr bool is_2d_v = details::is_dim_v<T, 2>;
+
+    // Profile versus regular histogram
+    template <typename T>
+    constexpr bool is_profile_v = details::is_one_of_hist_types_v<T, WP1D, WP2D, P1D, P2D>;
+    template <typename T>
+    constexpr bool is_hist_v = details::is_one_of_hist_types_v<T, WH1D, WH2D, H1D, H2D>;
+
+    // Weighted versus non-weighted types
+    template <typename T>
+    constexpr bool is_weighted_v = details::is_one_of_hist_types_v<T, WH1D, WH2D, WP1D, WP2D>;
+    template <typename T>
+    constexpr bool is_not_weighted_v = details::is_one_of_hist_types_v<T, H1D, H2D, P1D, P2D>;
+
+    /// Get histogram arithemtic type
+    template <typename T>
+    using param_t = typename T::value_type::AxisArithmeticType;
+
+    template <typename PARAM, typename Z>
+    constexpr bool param_check_v = details::is_safe_cast<PARAM, Z>();
+
+    /// Array storage for histograms with buffer support
+    template <typename T, std::size_t N>
+    struct Array : public std::array<T, N> {
+      auto buffer() {
+        return std::apply( []( auto&... i ) { return std::array{i.buffer()...}; },
+                           static_cast<std::array<T, N>&>( *this ) );
+      }
+    };
+
+    template <typename HIST>
+    using RadArray = Array<HIST, Rich::NRadiatorTypes>;
+    template <typename HIST>
+    using DetArray = Array<HIST, Rich::NRiches>;
+    template <typename HIST>
+    using PanelArray = Array<HIST, Rich::NPDPanelsPerRICH>;
+    template <typename HIST>
+    using PartArray = Array<HIST, Rich::NParticleTypes>;
+
+  } // namespace Hist
 
   //-----------------------------------------------------------------------------
   /** @class HistoBase RichFutureKernel/RichHistoBase.h
@@ -69,6 +273,14 @@ namespace Rich::Future {
   template <class PBASE>
   class HistoBase : public CommonBase<PBASE> {
 
+  protected:
+    // definitions
+
+    /// short name for bin labels
+    using BinLabels = std::vector<std::string>;
+    /// short name for axis label
+    using AxisLabel = std::string;
+
   public:
     // inherit constructors
     using CommonBase<PBASE>::CommonBase;
@@ -76,18 +288,8 @@ namespace Rich::Future {
   protected:
     /// Histogram Constructor initisalisations
     inline void initRichHistoConstructor() {
-      const auto sc =
-          // Place all histograms under RICH/ sub-dir
-          this->setProperty( "HistoTopDir", "RICH/" ) &&
-          // Expand printout table size a bit
-          this->setProperty( "ShortFormatFor1DHistoTable", " | %1$-45.45s %2%" ) &&
-          this->setProperty( "FormatFor1DHistoTable",
-                             "| %2$-75.75s | %3$=7d |%8$11.5g | %10$-11.5g|%12$11.5g |%14$11.5g |" ) &&
-          this->setProperty(
-              "HeaderFor1DHistoTable",
-              "|   Title                                                                     |    #    |     Mean   |  "
-              "  RMS     |  Skewness  |  Kurtosis  |" );
-      if ( !sc ) { throw Rich::Exception( "Failed to set histogramming properties" ); }
+      // Nothing at the moment ...
+      // keep for now in case needed, but if not eventually should just remove.
     }
 
     /// Tuple Constructor initisalisations
@@ -131,245 +333,73 @@ namespace Rich::Future {
     virtual StatusCode prebookHistograms();
 
   protected:
-    // definitions
+    // Histogram initialisation
 
-    /// short name for bin labels
-    using BinLabels = std::vector<std::string>;
-    /// short name for axis label
-    using AxisLabel = std::string;
-
-  protected:
-    /** Book a 1D histogram
-     *
-     * @param id         Histogram identifier
-     * @param title      Histogram title
-     * @param low        Lower histogram edge
-     * @param high       Upper histogram edge
-     * @param bins       Number of bins
-     * @param xAxisLabel Label for the X Axis
-     * @param yAxisLabel Label for the Y Axis
-     * @param binLabels  Labels for the X axis bins
-     *
-     * @return Pointer to booked histogram
-     */
-    AIDA::IHistogram1D* richHisto1D( const Rich::HistogramID& id,              //
-                                     const std::string&       title,           //
-                                     const double             low,             //
-                                     const double             high,            //
-                                     const unsigned int       bins,            //
-                                     const AxisLabel&         xAxisLabel = "", //
-                                     const AxisLabel&         yAxisLabel = "", //
-                                     const BinLabels&         binLabels  = BinLabels() ) const;
-
-    /** Book a 2D histogram
-     *
-     * @param id         Histogram identifier
-     * @param title      Histogram title
-     * @param lowX       Lower histogram edge in X
-     * @param highX      Upper histogram edge in X
-     * @param binsX      Number of bins in X
-     * @param lowY       Lower histogram edge in Y
-     * @param highY      Upper histogram edge in Y
-     * @param binsY      Number of bins in Y
-     * @param xAxisLabel Label for the X Axis
-     * @param yAxisLabel Label for the Y Axis
-     * @param zAxisLabel Label for the Z Axis
-     * @param xBinLabels Labels for the X axis bins
-     * @param yBinLabels Labels for the Y axis bins
-     *
-     * @return Pointer to booked histogram
-     */
-    AIDA::IHistogram2D* richHisto2D( const Rich::HistogramID& id,                       //
-                                     const std::string&       title,                    //
-                                     const double             lowX,                     //
-                                     const double             highX,                    //
-                                     const unsigned int       binsX,                    //
-                                     const double             lowY,                     //
-                                     const double             highY,                    //
-                                     const unsigned int       binsY,                    //
-                                     const AxisLabel&         xAxisLabel = "",          //
-                                     const AxisLabel&         yAxisLabel = "",          //
-                                     const AxisLabel&         zAxisLabel = "",          //
-                                     const BinLabels&         xBinLabels = BinLabels(), //
-                                     const BinLabels&         yBinLabels = BinLabels() ) const;
-
-    /** Book a 1D profile histogram
-     *
-     * @param id         Histogram identifier
-     * @param title      Histogram title
-     * @param low        Lower hisstogram edge
-     * @param high       Upper histogram edge
-     * @param bins       Number of bins
-     * @param xAxisLabel Label for the X Axis
-     * @param yAxisLabel Label for the Y Axis
-     * €param binLabels  Labels for the X axis bins
-     *
-     * @return Pointer to booked histogram
-     */
-    AIDA::IProfile1D* richProfile1D( const Rich::HistogramID& id,              //
-                                     const std::string&       title,           //
-                                     const double             low,             //
-                                     const double             high,            //
-                                     const unsigned int       bins,            //
-                                     const AxisLabel&         xAxisLabel = "", //
-                                     const AxisLabel&         yAxisLabel = "", //
-                                     const BinLabels&         binLabels  = BinLabels() ) const;
-
-    /** Book a 2D profile histogram
-     *
-     * @param id         Histogram identifier
-     * @param title      Histogram title
-     * @param lowX       Lower histogram edge in X
-     * @param highX      Upper histogram edge in X
-     * @param binsX      Number of bins in X
-     * @param lowY       Lower histogram edge in Y
-     * @param highY      Upper histogram edge in Y
-     * @param binsY      Number of bins in Y
-     * @param xAxisLabel Label for the X Axis
-     * @param yAxisLabel Label for the Y Axis
-     * @param zAxisLabel Label for the Z Axis
-     * @param xBinLabels Labels for the X axis bins
-     * @param yBinLabels Labels for the Y axis bins
-     *
-     * @return Pointer to booked histogram
-     */
-    AIDA::IProfile2D* richProfile2D( const Rich::HistogramID& id,                       //
-                                     const std::string&       title,                    //
-                                     const double             lowX,                     //
-                                     const double             highX,                    //
-                                     const unsigned int       binsX,                    //
-                                     const double             lowY,                     //
-                                     const double             highY,                    //
-                                     const unsigned int       binsY,                    //
-                                     const AxisLabel&         xAxisLabel = "",          //
-                                     const AxisLabel&         yAxisLabel = "",          //
-                                     const AxisLabel&         zAxisLabel = "",          //
-                                     const BinLabels&         xBinLabels = BinLabels(), //
-                                     const BinLabels&         yBinLabels = BinLabels() ) const;
-
-    //-----------------------------------------------------------------------------------------
+    template <typename H, typename... Args>
+    bool initHist( H& h, Args&&... args ) const {
+      if constexpr ( Hist::is_1d_v<H> ) { return init1D( h, std::forward<Args>( args )... ); }
+      if constexpr ( Hist::is_2d_v<H> ) { return init2D( h, std::forward<Args>( args )... ); }
+    }
 
-  protected:
-    /// Safe histogram filling
-    template <typename HIST, typename... Args>
-    inline void fillHisto( HIST* h, Args&&... args ) const {
-      if ( h ) {
-        h->fill( std::forward<Args>( args )... );
-      } else {
-        throw Rich::Exception( "Attempt to fill NULL histogram pointer" );
+    /// 1D histogram
+    template <typename H1D>
+    bool init1D( H1D&                     h,               //
+                 const Rich::HistogramID& id,              //
+                 std::string              title,           //
+                 const Hist::param_t<H1D> low,             //
+                 const Hist::param_t<H1D> high,            //
+                 const unsigned int       bins,            //
+                 AxisLabel                xAxisLabel = "", //
+                 AxisLabel                yAxisLabel = "", //
+                 BinLabels                binLabels  = {} ) const {
+      using Axis = Gaudi::Accumulators::Axis<Hist::param_t<H1D>>;
+      title      = id.fullTitle( title );
+      if ( !xAxisLabel.empty() ) {
+        title += ";" + xAxisLabel;
+        // Only allow y Axis label if we also have an X axis label
+        if ( !yAxisLabel.empty() ) { title += ";" + yAxisLabel; }
       }
+      h.emplace( this, "/RICH/" + this->name() + "/" + id.fullid(), std::move( title ),
+                 Axis( bins, low, high, std::move( xAxisLabel ), std::move( binLabels ) ) );
+      return h.has_value();
     }
 
-    //-----------------------------------------------------------------------------------------
-
-  private:
-    // Types for histogram lookup
-
-    /** @class HistoMap RichFutureKernel/RichHistoBase.h
-     *
-     *  Private class to implement mapping between RICH classes and histograms
-     *
-     *  @author Chris Jones   Christopher.Rob.Jones@cern.ch
-     *  @date   2009-07-27
-     */
-    template <class HTYPE>
-    class HistoMap {
-    public:
-      using StringToHist = Rich::HashMap<std::string, HTYPE*>;
-
-    private:
-      using Map = Rich::Map<Rich::PackedPIDInfo::Pack32_t, StringToHist>;
-
-    private:
-      mutable Map        m_map;
-      mutable std::mutex m_mutex;
-
-    public:
-      inline StringToHist& getmap( const Rich::PackedPIDInfo& info ) const {
-        auto i = m_map.find( info.raw() );
-        if ( i != m_map.end() ) {
-          return i->second;
-        } else {
-          // lock to create map
-          std::scoped_lock lock( m_mutex );
-          // still missing ?
-          i = m_map.find( info.raw() );
-          return ( i != m_map.end() ? i->second : m_map[info.raw()] );
+    /// 2D histogram
+    template <typename H2D>
+    bool init2D( H2D&                     h,               //
+                 const Rich::HistogramID& id,              //
+                 std::string              title,           //
+                 const Hist::param_t<H2D> lowX,            //
+                 const Hist::param_t<H2D> highX,           //
+                 const unsigned int       binsX,           //
+                 const Hist::param_t<H2D> lowY,            //
+                 const Hist::param_t<H2D> highY,           //
+                 const unsigned int       binsY,           //
+                 AxisLabel                xAxisLabel = "", //
+                 AxisLabel                yAxisLabel = "", //
+                 AxisLabel                zAxisLabel = "", //
+                 BinLabels                xBinLabels = {}, //
+                 BinLabels                yBinLabels = {} ) const {
+      using Axis = Gaudi::Accumulators::Axis<Hist::param_t<H2D>>;
+      title      = id.fullTitle( title );
+      if ( !xAxisLabel.empty() ) {
+        title += ";" + xAxisLabel;
+        // Only allow y Axis label if we also have an X axis label
+        if ( !yAxisLabel.empty() ) {
+          title += ";" + yAxisLabel;
+          // Only allow z Axis label if we also have an X and Y axis labels
+          if ( !zAxisLabel.empty() ) { title += ";" + zAxisLabel; }
         }
       }
-      inline HTYPE*& gethist( const Rich::HistogramID& id ) const { return getmap( id.packedData() )[id.id()]; }
-    };
-
-    /// Mapping between IDs and 1D histogram pointers
-    using Map1DH = HistoMap<AIDA::IHistogram1D>;
-
-    /// Mapping between IDs and 2D histogram pointers
-    using Map2DH = HistoMap<AIDA::IHistogram2D>;
-
-    /// Mapping between IDs and 1D Profile histogram pointers
-    using Map1DP = HistoMap<AIDA::IProfile1D>;
-
-    /// Mapping between IDs and 2D Profile histogram pointers
-    using Map2DP = HistoMap<AIDA::IProfile2D>;
+      h.emplace( this, "/RICH/" + this->name() + "/" + id.fullid(), std::move( title ),
+                 Axis( binsX, lowX, highX, std::move( xAxisLabel ), std::move( xBinLabels ) ),
+                 Axis( binsY, lowY, highY, std::move( yAxisLabel ), std::move( yBinLabels ) ) );
+      return h.has_value();
+    }
 
   private:
     /// Flag to indicate if histograms have been booked or not
     bool m_histosAreBooked{false};
-
-    /// 1D histo map
-    Map1DH m_1dhmap;
-
-    /// 2D histo map
-    Map2DH m_2dhmap;
-
-    /// 1D Profile map
-    Map1DP m_1dpmap;
-
-    /// 2D Profile map
-    Map2DP m_2dpmap;
-
-    /// Booking locks
-    mutable std::mutex m_mutex1DH;
-    mutable std::mutex m_mutex1DP;
-    mutable std::mutex m_mutex2DH;
-    mutable std::mutex m_mutex2DP;
-
-  protected:
-    //-----------------------------------------------------------------------------------------
-
-    /** Access 1D histogram by id
-     *
-     * @param id      Histogram identifier
-     *
-     * @return Pointer to booked histogram
-     */
-    AIDA::IHistogram1D* richHisto1D( const Rich::HistogramID& id ) const;
-
-    /** Access 2D histogram by id
-     *
-     * @param id      Histogram identifier
-     *
-     * @return Pointer to booked histogram
-     */
-    AIDA::IHistogram2D* richHisto2D( const Rich::HistogramID& id ) const;
-
-    /** Access 1D profile histogram by id
-     *
-     * @param id      Histogram identifier
-     *
-     * @return Pointer to booked histogram
-     */
-    AIDA::IProfile1D* richProfile1D( const Rich::HistogramID& id ) const;
-
-    /** Access 2D profile histogram by id
-     *
-     * @param id      Histogram identifier
-     *
-     * @return Pointer to booked histogram
-     */
-    AIDA::IProfile2D* richProfile2D( const Rich::HistogramID& id ) const;
-
-    //-----------------------------------------------------------------------------------------
   };
 
 } // namespace Rich::Future
diff --git a/Rich/RichFutureKernel/include/RichFutureKernel/RichHistoUtils.h b/Rich/RichFutureKernel/include/RichFutureKernel/RichHistoUtils.h
deleted file mode 100644
index fea7291e677..00000000000
--- a/Rich/RichFutureKernel/include/RichFutureKernel/RichHistoUtils.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*****************************************************************************\
-* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
-*                                                                             *
-* This software is distributed under the terms of the GNU General Public      *
-* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
-*                                                                             *
-* In applying this licence, CERN does not waive the privileges and immunities *
-* granted to it by virtue of its status as an Intergovernmental Organization  *
-* or submit itself to any jurisdiction.                                       *
-\*****************************************************************************/
-
-#pragma once
-
-#include "RichUtils/RichException.h"
-#include <cassert>
-
-namespace Rich::Future::HistoUtils {
-
-  /// Utility method to save a histogram pointer with checks
-  template <typename HISTO>
-  [[nodiscard]] inline bool saveAndCheck( HISTO*& h1, HISTO* h2 ) {
-    // assert( h1 == nullptr );  // should never overwrite a previously cached valid pointer
-    if ( h1 && h1 != h2 ) { throw Rich::Exception( "Attempt to overwrite existing histogram '" + h1->title() + "'" ); }
-    h1 = h2;                  // save input
-    return ( h1 != nullptr ); // input should always be valid
-  }
-
-} // namespace Rich::Future::HistoUtils
diff --git a/Rich/RichFutureKernel/src/RichHistoBase.icpp b/Rich/RichFutureKernel/src/RichHistoBase.icpp
deleted file mode 100644
index c13fb3903b3..00000000000
--- a/Rich/RichFutureKernel/src/RichHistoBase.icpp
+++ /dev/null
@@ -1,269 +0,0 @@
-/*****************************************************************************\
-* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
-*                                                                             *
-* This software is distributed under the terms of the GNU General Public      *
-* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
-*                                                                             *
-* In applying this licence, CERN does not waive the privileges and immunities *
-* granted to it by virtue of its status as an Intergovernmental Organization  *
-* or submit itself to any jurisdiction.                                       *
-\*****************************************************************************/
-
-//-----------------------------------------------------------------------------
-/** @file RichHistoBase.icpp
- *
- *  Implementation file for RICH base class : Rich::HistoBase
- *
- *  @author Chris Jones   Christopher.Rob.Jones@cern.ch
- *  @date   2009-07-27
- */
-//-----------------------------------------------------------------------------
-
-#pragma once
-
-// local
-#include "RichFutureKernel/RichHistoBase.h"
-
-// Utils
-#include "RichUtils/RichException.h"
-
-// GaudiUtils
-#include "GaudiUtils/HistoLabels.h"
-using namespace Gaudi::Utils::Histos;
-
-// Base class methods
-#include "RichCommonBase.icpp"
-
-//=============================================================================
-// System Initialisation
-//=============================================================================
-template <class PBASE>
-StatusCode Rich::Future::HistoBase<PBASE>::sysInitialize() {
-  // run base clase method
-  auto sc = CommonBase<PBASE>::sysInitialize();
-  if ( sc ) {
-    // as last thing book any histos (only once)
-    if ( !m_histosAreBooked ) {
-      try {
-        sc                = prebookHistograms();
-        m_histosAreBooked = true;
-      } catch ( const Rich::Exception& excp ) {
-        this->error() << "Problem prebooking histograms : Error = '" << excp.message() << "'" << endmsg;
-        sc = StatusCode::FAILURE;
-      }
-    }
-  }
-  // return
-  return sc;
-}
-//=============================================================================
-
-template <class PBASE>
-StatusCode Rich::Future::HistoBase<PBASE>::prebookHistograms() {
-  // Default implementation does nothing
-  return StatusCode::SUCCESS;
-}
-
-//=============================================================================
-
-namespace {
-  template <typename MAP, typename ID>
-  decltype( auto ) findHistoImpl( const MAP& hmap, const ID& id ) {
-    const auto& map = hmap.getmap( id.packedData() );
-    const auto  iH  = map.find( id.id() );
-    if ( iH == map.end() ) { //
-      throw Rich::Exception( "Cannot find pre-booked histogram '" + id.fullid() + "'" );
-    }
-    return iH->second;
-  }
-} // namespace
-
-template <class PBASE>
-AIDA::IHistogram1D* //
-Rich::Future::HistoBase<PBASE>::richHisto1D( const Rich::HistogramID& id ) const {
-  return findHistoImpl( m_1dhmap, id );
-}
-
-template <class PBASE>
-AIDA::IHistogram2D* //
-Rich::Future::HistoBase<PBASE>::richHisto2D( const Rich::HistogramID& id ) const {
-  return findHistoImpl( m_2dhmap, id );
-}
-
-template <class PBASE>
-AIDA::IProfile1D* //
-Rich::Future::HistoBase<PBASE>::richProfile1D( const Rich::HistogramID& id ) const {
-  return findHistoImpl( m_1dpmap, id );
-}
-
-template <class PBASE>
-AIDA::IProfile2D* //
-Rich::Future::HistoBase<PBASE>::richProfile2D( const Rich::HistogramID& id ) const {
-  return findHistoImpl( m_2dpmap, id );
-}
-
-//=============================================================================
-
-namespace {
-  template <typename HISTO, typename LABEL>
-  void axisLabelsImpl( HISTO*       h,          //
-                       const LABEL& xAxisLabel, //
-                       const LABEL& yAxisLabel, //
-                       const LABEL& zAxisLabel = "" ) {
-    if ( !zAxisLabel.empty() ) {
-      // Bug in GaudiUtils (to be fixed) with no way to set z axis. Ignore for the moment
-      //_ri_debug << "Setting Z axis label currently not supported : " << zAxisLabel << endmsg;
-    }
-    // set the axis labels
-    if ( !xAxisLabel.empty() || !yAxisLabel.empty() ) {
-      if ( !setAxisLabels( h, xAxisLabel, yAxisLabel ) ) {
-        throw Rich::Exception( "Problem Setting Histogram Axis Labels" );
-      }
-    }
-  }
-  template <typename HISTO, typename LABELS>
-  void binLabelsImpl( HISTO*        h, //
-                      const LABELS& binLabels ) {
-    if ( !binLabels.empty() ) {
-      if ( !setBinLabels( h, binLabels ) ) { throw Rich::Exception( "Problem Setting Histogram Bin Labels" ); }
-    }
-  }
-  template <typename HISTO, typename LABELS>
-  void binLabelsImpl( HISTO*        h,          //
-                      const LABELS& xBinLabels, //
-                      const LABELS& yBinLabels ) {
-    if ( !xBinLabels.empty() || !yBinLabels.empty() ) {
-      if ( !setBinLabels( h, xBinLabels, yBinLabels ) ) {
-        throw Rich::Exception( "Problem Setting Histogram Bin Labels" );
-      }
-    }
-  }
-} // namespace
-
-template <class PBASE>
-AIDA::IHistogram1D*                                                               //
-Rich::Future::HistoBase<PBASE>::richHisto1D( const Rich::HistogramID& id,         //
-                                             const std::string&       title,      //
-                                             const double             low,        //
-                                             const double             high,       //
-                                             const unsigned int       bins,       //
-                                             const AxisLabel&         xAxisLabel, //
-                                             const AxisLabel&         yAxisLabel, //
-                                             const BinLabels&         binLabels ) const {
-  // Already been booked ?
-  auto*& h = m_1dhmap.gethist( id );
-  if ( !h ) {
-    // Lock for new histo creation
-    std::scoped_lock lock( m_mutex1DH );
-    // Still missing ?
-    h = m_1dhmap.gethist( id );
-    if ( !h ) {
-      // Book the histo
-      h = PBASE::book1D( id.fullid(), id.fullTitle( title ), low, high, bins );
-      // set the labels
-      axisLabelsImpl( h, xAxisLabel, yAxisLabel );
-      binLabelsImpl( h, binLabels );
-    }
-  }
-  // return the histo
-  return h;
-}
-
-template <class PBASE>
-AIDA::IHistogram2D*                                                               //
-Rich::Future::HistoBase<PBASE>::richHisto2D( const Rich::HistogramID& id,         //
-                                             const std::string&       title,      //
-                                             const double             lowX,       //
-                                             const double             highX,      //
-                                             const unsigned int       binsX,      //
-                                             const double             lowY,       //
-                                             const double             highY,      //
-                                             const unsigned int       binsY,      //
-                                             const AxisLabel&         xAxisLabel, //
-                                             const AxisLabel&         yAxisLabel, //
-                                             const AxisLabel&         zAxisLabel, //
-                                             const BinLabels&         xBinLabels, //
-                                             const BinLabels&         yBinLabels ) const {
-  // Already been booked ?
-  auto*& h = m_2dhmap.gethist( id );
-  if ( !h ) {
-    // Lock for new histo creation
-    std::scoped_lock lock( m_mutex2DH );
-    // still missing ?
-    h = m_2dhmap.gethist( id );
-    if ( !h ) {
-      // Book the histo
-      h = PBASE::book2D( id.fullid(), id.fullTitle( title ), lowX, highX, binsX, lowY, highY, binsY );
-      // set the labels
-      axisLabelsImpl( h, xAxisLabel, yAxisLabel, zAxisLabel );
-      binLabelsImpl( h, xBinLabels, yBinLabels );
-    }
-  }
-  // return the histo
-  return h;
-}
-
-template <class PBASE>
-AIDA::IProfile1D*                                                                   //
-Rich::Future::HistoBase<PBASE>::richProfile1D( const Rich::HistogramID& id,         //
-                                               const std::string&       title,      //
-                                               const double             low,        //
-                                               const double             high,       //
-                                               const unsigned int       bins,       //
-                                               const AxisLabel&         xAxisLabel, //
-                                               const AxisLabel&         yAxisLabel, //
-                                               const BinLabels&         binLabels ) const {
-  // Already been booked ?
-  auto*& h = m_1dpmap.gethist( id );
-  if ( !h ) {
-    // Lock for new histo creation
-    std::scoped_lock lock( m_mutex1DP );
-    // still missing ?
-    h = m_1dpmap.gethist( id );
-    if ( !h ) {
-      // Book the histo
-      h = PBASE::bookProfile1D( id.fullid(), id.fullTitle( title ), low, high, bins );
-      // set the labels
-      axisLabelsImpl( h, xAxisLabel, yAxisLabel );
-      binLabelsImpl( h, binLabels );
-    }
-  }
-  // return the histo
-  return h;
-}
-
-template <class PBASE>
-AIDA::IProfile2D*                                                                   //
-Rich::Future::HistoBase<PBASE>::richProfile2D( const Rich::HistogramID& id,         //
-                                               const std::string&       title,      //
-                                               const double             lowX,       //
-                                               const double             highX,      //
-                                               const unsigned int       binsX,      //
-                                               const double             lowY,       //
-                                               const double             highY,      //
-                                               const unsigned int       binsY,      //
-                                               const AxisLabel&         xAxisLabel, //
-                                               const AxisLabel&         yAxisLabel, //
-                                               const AxisLabel&         zAxisLabel, //
-                                               const BinLabels&         xBinLabels, //
-                                               const BinLabels&         yBinLabels ) const {
-  // Already been booked ?
-  auto*& h = m_2dpmap.gethist( id );
-  if ( !h ) {
-    // Lock for new histo creation
-    std::scoped_lock lock( m_mutex2DP );
-    // still missing ?
-    h = m_2dpmap.gethist( id );
-    if ( !h ) {
-      // Book the histo
-      h = PBASE::bookProfile2D( id.fullid(), id.fullTitle( title ), lowX, highX, binsX, lowY, highY, binsY );
-      // set the labels
-      axisLabelsImpl( h, xAxisLabel, yAxisLabel, zAxisLabel );
-      binLabelsImpl( h, xBinLabels, yBinLabels );
-    }
-  }
-  // return the histo
-  return h;
-}
-
-//=============================================================================
diff --git a/Rich/RichFutureKernel/src/component/RichBaseTests.cpp b/Rich/RichFutureKernel/src/component/RichBaseTests.cpp
new file mode 100644
index 00000000000..833e454731b
--- /dev/null
+++ b/Rich/RichFutureKernel/src/component/RichBaseTests.cpp
@@ -0,0 +1,136 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+
+#include "GaudiKernel/RndmGenerators.h"
+#include "LHCbAlgs/Consumer.h"
+#include "RichFutureKernel/RichHistoAlgBase.h"
+
+#include <cmath>
+#include <cstdint>
+#include <type_traits>
+
+namespace Rich::Future::Tests {
+
+  using namespace Rich::Future::Hist;
+
+  template <typename HIST>
+  class HistoTestBase final
+      : public LHCb::Algorithm::Consumer<void(), Gaudi::Functional::Traits::BaseClass_t<HistoAlgBase>> {
+  public:
+    HistoTestBase( const std::string& name, ISvcLocator* pSvcLocator ) : Consumer( name, pSvcLocator ) {
+      setProperty( "HistoPrint", true ).ignore();
+    }
+    auto shoot() const {
+      using T      = param_t<HIST>;
+      static T var = 0;
+      if constexpr ( std::is_floating_point_v<T> ) {
+        return std::remainder( var++, T{100} );
+      } else {
+        return var++ % T{100};
+      }
+    }
+    void operator()() const override {
+      std::size_t iFill = 0;
+      auto        h_b   = m_h.buffer(); // test buffers
+      while ( iFill++ < 50 ) {
+        const auto i = ( iFill % 2 );
+        if constexpr ( is_1d_v<HIST> ) {
+          if constexpr ( is_weighted_v<HIST> ) {
+            if constexpr ( is_profile_v<HIST> ) {
+              m_h[i][shoot()] += {shoot(), shoot()};
+              h_b[i][shoot()] += {shoot(), shoot()};
+            } else if constexpr ( is_hist_v<HIST> ) {
+              m_h[i][shoot()] += shoot();
+              h_b[i][shoot()] += shoot();
+            }
+          } else if constexpr ( is_not_weighted_v<HIST> ) {
+            if constexpr ( is_profile_v<HIST> ) {
+              m_h[i][shoot()] += shoot();
+              h_b[i][shoot()] += shoot();
+            } else if constexpr ( is_hist_v<HIST> ) {
+              ++m_h[i][shoot()];
+              ++h_b[i][shoot()];
+            }
+          }
+        } else if constexpr ( is_2d_v<HIST> ) {
+          if constexpr ( is_weighted_v<HIST> ) {
+            if constexpr ( is_profile_v<HIST> ) {
+              m_h[i][{shoot(), shoot()}] += {shoot(), shoot()};
+              h_b[i][{shoot(), shoot()}] += {shoot(), shoot()};
+            } else if constexpr ( is_hist_v<HIST> ) {
+              m_h[i][{shoot(), shoot()}] += shoot();
+              h_b[i][{shoot(), shoot()}] += shoot();
+            }
+          } else if constexpr ( is_not_weighted_v<HIST> ) {
+            if constexpr ( is_profile_v<HIST> ) {
+              m_h[i][{shoot(), shoot()}] += shoot();
+              h_b[i][{shoot(), shoot()}] += shoot();
+            } else if constexpr ( is_hist_v<HIST> ) {
+              ++m_h[i][{shoot(), shoot()}];
+              ++h_b[i][{shoot(), shoot()}];
+            }
+          }
+        }
+      }
+    }
+
+  protected:
+    StatusCode prebookHistograms() override {
+      info() << "1D=" << is_1d_v<HIST> << " 2D=" << is_2d_v<HIST>       //
+             << " H=" << is_hist_v<HIST> << " P=" << is_profile_v<HIST> //
+             << " W=" << is_weighted_v<HIST> << " NW=" << is_not_weighted_v<HIST> << endmsg;
+      bool ok = true;
+      if constexpr ( is_1d_v<HIST> ) {
+        ok &= initHist( m_h[0], HID( "testH1D0" ), "Test 1D Histogram 0", 0, 100, 100, "Rand Number", "Entries" );
+        ok &= initHist( m_h[1], HID( "testH1D1" ), "Test 1D Histogram 1", 0, 100, 100, "Rand Number", "Entries" );
+      }
+      if constexpr ( is_2d_v<HIST> ) {
+        ok &= initHist( m_h[0], HID( "testH2D0" ), "Test 2D Histogram 0", //
+                        0, 100, 100, 0, 100, 100, "Rand Number", "Rand Number", "Entries" );
+        ok &= initHist( m_h[1], HID( "testH2D1" ), "Test 2D Histogram 1", //
+                        0, 100, 100, 0, 100, 100, "Rand Number", "Rand Number", "Entries" );
+      }
+      return StatusCode{ok};
+    }
+
+  private:
+    /// test array of (optional) hists.
+    /// Note last entry is intentionally uninitialised to test handling this scenario.
+    mutable Hist::Array<HIST, 3> m_h;
+  };
+
+  DECLARE_COMPONENT_WITH_ID( HistoTestBase<H1D<>>, "RichTestH1DD" )
+  DECLARE_COMPONENT_WITH_ID( HistoTestBase<WH1D<>>, "RichTestWH1DD" )
+  DECLARE_COMPONENT_WITH_ID( HistoTestBase<P1D<>>, "RichTestP1DD" )
+  DECLARE_COMPONENT_WITH_ID( HistoTestBase<WP1D<>>, "RichTestWP1DD" )
+
+  DECLARE_COMPONENT_WITH_ID( HistoTestBase<H2D<>>, "RichTestH2DD" )
+  DECLARE_COMPONENT_WITH_ID( HistoTestBase<WH2D<>>, "RichTestWH2DD" )
+  DECLARE_COMPONENT_WITH_ID( HistoTestBase<P2D<>>, "RichTestP2DD" )
+  DECLARE_COMPONENT_WITH_ID( HistoTestBase<WP2D<>>, "RichTestWP2DD" )
+
+  DECLARE_COMPONENT_WITH_ID( HistoTestBase<H1D<float>>, "RichTestH1DF" )
+  DECLARE_COMPONENT_WITH_ID( HistoTestBase<WH1D<float>>, "RichTestWH1DF" )
+  DECLARE_COMPONENT_WITH_ID( HistoTestBase<P1D<float>>, "RichTestP1DF" )
+  DECLARE_COMPONENT_WITH_ID( HistoTestBase<WP1D<float>>, "RichTestWP1DF" )
+
+  DECLARE_COMPONENT_WITH_ID( HistoTestBase<H2D<float>>, "RichTestH2DF" )
+  DECLARE_COMPONENT_WITH_ID( HistoTestBase<WH2D<float>>, "RichTestWH2DF" )
+  DECLARE_COMPONENT_WITH_ID( HistoTestBase<P2D<float>>, "RichTestP2DF" )
+  DECLARE_COMPONENT_WITH_ID( HistoTestBase<WP2D<float>>, "RichTestWP2DF" )
+
+  DECLARE_COMPONENT_WITH_ID( HistoTestBase<H1D<std::int32_t>>, "RichTestH1DI" )
+  DECLARE_COMPONENT_WITH_ID( HistoTestBase<P1D<std::int32_t>>, "RichTestP1DI" )
+
+  DECLARE_COMPONENT_WITH_ID( HistoTestBase<H2D<std::int32_t>>, "RichTestH2DI" )
+  DECLARE_COMPONENT_WITH_ID( HistoTestBase<P2D<std::int32_t>>, "RichTestP2DI" )
+
+} // namespace Rich::Future::Tests
diff --git a/Rich/RichFutureKernel/src/RichAlgBase.cpp b/Rich/RichFutureKernel/src/lib/RichAlgBase.cpp
similarity index 100%
rename from Rich/RichFutureKernel/src/RichAlgBase.cpp
rename to Rich/RichFutureKernel/src/lib/RichAlgBase.cpp
diff --git a/Rich/RichFutureKernel/src/RichCommonBase.icpp b/Rich/RichFutureKernel/src/lib/RichCommonBase.icpp
similarity index 100%
rename from Rich/RichFutureKernel/src/RichCommonBase.icpp
rename to Rich/RichFutureKernel/src/lib/RichCommonBase.icpp
diff --git a/Rich/RichFutureKernel/src/RichHistoAlgBase.cpp b/Rich/RichFutureKernel/src/lib/RichHistoAlgBase.cpp
similarity index 94%
rename from Rich/RichFutureKernel/src/RichHistoAlgBase.cpp
rename to Rich/RichFutureKernel/src/lib/RichHistoAlgBase.cpp
index 7439f256d59..937183f5b40 100644
--- a/Rich/RichFutureKernel/src/RichHistoAlgBase.cpp
+++ b/Rich/RichFutureKernel/src/lib/RichHistoAlgBase.cpp
@@ -24,8 +24,6 @@
 
 // ============================================================================
 // Force creation of templated classes
-#include "GaudiAlg/GaudiHistos.icpp"
-template class GaudiHistos<Rich::Future::Details::BaseAlg>;
 #include "RichHistoBase.icpp"
 template class Rich::Future::CommonBase<Rich::Future::Details::HistoBaseAlg>;
 template class Rich::Future::HistoBase<Rich::Future::Details::HistoBaseAlg>;
diff --git a/Rich/RichFutureKernel/src/lib/RichHistoBase.icpp b/Rich/RichFutureKernel/src/lib/RichHistoBase.icpp
new file mode 100644
index 00000000000..d4bd4402b4b
--- /dev/null
+++ b/Rich/RichFutureKernel/src/lib/RichHistoBase.icpp
@@ -0,0 +1,61 @@
+/*****************************************************************************\
+* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration      *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+
+//-----------------------------------------------------------------------------
+/** @file RichHistoBase.icpp
+ *
+ *  Implementation file for RICH base class : Rich::HistoBase
+ *
+ *  @author Chris Jones   Christopher.Rob.Jones@cern.ch
+ *  @date   2009-07-27
+ */
+//-----------------------------------------------------------------------------
+
+#pragma once
+
+// local
+#include "RichFutureKernel/RichHistoBase.h"
+
+// Utils
+#include "RichUtils/RichException.h"
+
+// GaudiUtils
+#include "GaudiUtils/HistoLabels.h"
+using namespace Gaudi::Utils::Histos;
+
+// Base class methods
+#include "RichCommonBase.icpp"
+
+template <class PBASE>
+StatusCode Rich::Future::HistoBase<PBASE>::sysInitialize() {
+  // run base clase method
+  auto sc = CommonBase<PBASE>::sysInitialize();
+  if ( sc ) {
+    // as last thing book any histos (only once)
+    if ( !m_histosAreBooked ) {
+      try {
+        sc                = prebookHistograms();
+        m_histosAreBooked = true;
+      } catch ( const Rich::Exception& excp ) {
+        this->error() << "Problem prebooking histograms : Error = '" << excp.message() << "'" << endmsg;
+        sc = StatusCode::FAILURE;
+      }
+    }
+  }
+  // return
+  return sc;
+}
+
+template <class PBASE>
+StatusCode Rich::Future::HistoBase<PBASE>::prebookHistograms() {
+  // Default implementation does nothing
+  return StatusCode::SUCCESS;
+}
diff --git a/Rich/RichFutureKernel/src/RichHistoToolBase.cpp b/Rich/RichFutureKernel/src/lib/RichHistoToolBase.cpp
similarity index 100%
rename from Rich/RichFutureKernel/src/RichHistoToolBase.cpp
rename to Rich/RichFutureKernel/src/lib/RichHistoToolBase.cpp
diff --git a/Rich/RichFutureKernel/src/RichToolBase.cpp b/Rich/RichFutureKernel/src/lib/RichToolBase.cpp
similarity index 100%
rename from Rich/RichFutureKernel/src/RichToolBase.cpp
rename to Rich/RichFutureKernel/src/lib/RichToolBase.cpp
diff --git a/Rich/RichFutureKernel/src/RichTupleAlgBase.cpp b/Rich/RichFutureKernel/src/lib/RichTupleAlgBase.cpp
similarity index 100%
rename from Rich/RichFutureKernel/src/RichTupleAlgBase.cpp
rename to Rich/RichFutureKernel/src/lib/RichTupleAlgBase.cpp
diff --git a/Rich/RichFutureKernel/src/RichTupleToolBase.cpp b/Rich/RichFutureKernel/src/lib/RichTupleToolBase.cpp
similarity index 100%
rename from Rich/RichFutureKernel/src/RichTupleToolBase.cpp
rename to Rich/RichFutureKernel/src/lib/RichTupleToolBase.cpp
diff --git a/Rich/RichFutureKernel/tests/options/Histograms.py b/Rich/RichFutureKernel/tests/options/Histograms.py
new file mode 100644
index 00000000000..7ba7401402d
--- /dev/null
+++ b/Rich/RichFutureKernel/tests/options/Histograms.py
@@ -0,0 +1,62 @@
+#####################################################################################
+# (c) Copyright 1998-2019 CERN for the benefit of the LHCb and ATLAS collaborations #
+#                                                                                   #
+# This software is distributed under the terms of the Apache version 2 licence,     #
+# copied verbatim in the file "LICENSE".                                            #
+#                                                                                   #
+# In applying this licence, CERN does not waive the privileges and immunities       #
+# granted to it by virtue of its status as an Intergovernmental Organization        #
+# or submit itself to any jurisdiction.                                             #
+#####################################################################################
+
+from Gaudi.Configuration import *
+from Configurables import FPEAuditor
+from Configurables import Gaudi__Monitoring__MessageSvcSink as MessageSvcSink
+from Configurables import Gaudi__Histograming__Sink__Root as RootHistoSink
+from Configurables import RichTestH1DD, RichTestWH1DD, RichTestP1DD, RichTestWP1DD
+from Configurables import RichTestH2DD, RichTestWH2DD, RichTestP2DD, RichTestWP2DD
+from Configurables import RichTestH1DF, RichTestWH1DF, RichTestP1DF, RichTestWP1DF
+from Configurables import RichTestH2DF, RichTestWH2DF, RichTestP2DF, RichTestWP2DF
+from Configurables import RichTestH1DI, RichTestP1DI, RichTestH2DI, RichTestP2DI
+
+# Histo printout should be disabled if either of these is WARNING or above
+outLevel = INFO
+MessageSvc().OutputLevel = INFO
+
+algs = [
+    # Double
+    RichTestH1DD(OutputLevel=outLevel),
+    RichTestWH1DD(OutputLevel=outLevel),
+    RichTestP1DD(OutputLevel=outLevel),
+    RichTestWP1DD(OutputLevel=outLevel),
+    RichTestH2DD(OutputLevel=outLevel),
+    RichTestWH2DD(OutputLevel=outLevel),
+    RichTestP2DD(OutputLevel=outLevel),
+    RichTestWP2DD(OutputLevel=outLevel),
+    # Float
+    RichTestH1DF(OutputLevel=outLevel),
+    RichTestWH1DF(OutputLevel=outLevel),
+    RichTestP1DF(OutputLevel=outLevel),
+    RichTestWP1DF(OutputLevel=outLevel),
+    RichTestH2DF(OutputLevel=outLevel),
+    RichTestWH2DF(OutputLevel=outLevel),
+    RichTestP2DF(OutputLevel=outLevel),
+    RichTestWP2DF(OutputLevel=outLevel),
+    # Int
+    RichTestH1DI(OutputLevel=outLevel),
+    RichTestP1DI(OutputLevel=outLevel),
+    RichTestH2DI(OutputLevel=outLevel),
+    RichTestP2DI(OutputLevel=outLevel),
+]
+
+AuditorSvc().Auditors += ["FPEAuditor"]
+FPEAuditor().EnableGlobal = True
+
+app = ApplicationMgr(
+    EvtMax=1000,
+    EvtSel="NONE",
+    HistogramPersistency="ROOT",
+    TopAlg=algs,
+    ExtSvc=[AuditorSvc(), MessageSvcSink(),
+            RootHistoSink()],
+    AuditAlgorithms=True)
diff --git a/Rich/RichFutureKernel/tests/qmtest/histograms.qmt b/Rich/RichFutureKernel/tests/qmtest/histograms.qmt
new file mode 100644
index 00000000000..85d8650959c
--- /dev/null
+++ b/Rich/RichFutureKernel/tests/qmtest/histograms.qmt
@@ -0,0 +1,22 @@
+<?xml version="1.0" ?><!DOCTYPE extension  PUBLIC '-//QM/2.3/Extension//EN'  'http://www.codesourcery.com/qm/dtds/2.3/-//qm/2.3/extension//en.dtd'>
+<!--
+    (c) Copyright 1998-2019 CERN for the benefit of the LHCb and ATLAS collaborations
+
+    This software is distributed under the terms of the Apache version 2 licence,
+    copied verbatim in the file "LICENSE".
+
+    In applying this licence, CERN does not waive the privileges and immunities
+    granted to it by virtue of its status as an Intergovernmental Organization
+    or submit itself to any jurisdiction.
+-->
+<extension class="GaudiTest.GaudiExeTest" kind="test">
+<argument name="program"><text>gaudirun.py</text></argument>
+<argument name="args"><set><text>$RICHFUTUREKERNELROOT/tests/options/Histograms.py</text></set></argument>
+<argument name="use_temp_dir"><enumeral>true</enumeral></argument>
+<argument name="reference"><text>../refs/histograms.ref</text></argument>
+<argument name="error_reference"><text>../refs/empty.ref</text></argument>
+<argument name="validator"><text>
+from GaudiConf.QMTest.LHCbExclusions import preprocessor
+validateWithReference(preproc = preprocessor)
+</text></argument>
+</extension>
diff --git a/Rich/RichFutureKernel/tests/refs/empty.ref b/Rich/RichFutureKernel/tests/refs/empty.ref
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/Rich/RichFutureKernel/tests/refs/histograms.ref b/Rich/RichFutureKernel/tests/refs/histograms.ref
new file mode 100644
index 00000000000..46daadf5c27
--- /dev/null
+++ b/Rich/RichFutureKernel/tests/refs/histograms.ref
@@ -0,0 +1,113 @@
+ApplicationMgr    SUCCESS
+====================================================================================================================================
+====================================================================================================================================
+ApplicationMgr       INFO Application Manager Configured successfully
+RichTestH1DD         INFO 1D=1 2D=0 H=1 P=0 W=0 NW=1
+RichTestWH1DD        INFO 1D=1 2D=0 H=1 P=0 W=1 NW=0
+RichTestP1DD         INFO 1D=1 2D=0 H=0 P=1 W=0 NW=1
+RichTestWP1DD        INFO 1D=1 2D=0 H=0 P=1 W=1 NW=0
+RichTestH2DD         INFO 1D=0 2D=1 H=1 P=0 W=0 NW=1
+RichTestWH2DD        INFO 1D=0 2D=1 H=1 P=0 W=1 NW=0
+RichTestP2DD         INFO 1D=0 2D=1 H=0 P=1 W=0 NW=1
+RichTestWP2DD        INFO 1D=0 2D=1 H=0 P=1 W=1 NW=0
+RichTestH1DF         INFO 1D=1 2D=0 H=1 P=0 W=0 NW=1
+RichTestWH1DF        INFO 1D=1 2D=0 H=1 P=0 W=1 NW=0
+RichTestP1DF         INFO 1D=1 2D=0 H=0 P=1 W=0 NW=1
+RichTestWP1DF        INFO 1D=1 2D=0 H=0 P=1 W=1 NW=0
+RichTestH2DF         INFO 1D=0 2D=1 H=1 P=0 W=0 NW=1
+RichTestWH2DF        INFO 1D=0 2D=1 H=1 P=0 W=1 NW=0
+RichTestP2DF         INFO 1D=0 2D=1 H=0 P=1 W=0 NW=1
+RichTestWP2DF        INFO 1D=0 2D=1 H=0 P=1 W=1 NW=0
+RichTestH1DI         INFO 1D=1 2D=0 H=1 P=0 W=0 NW=1
+RichTestP1DI         INFO 1D=1 2D=0 H=0 P=1 W=0 NW=1
+RichTestH2DI         INFO 1D=0 2D=1 H=1 P=0 W=0 NW=1
+RichTestP2DI         INFO 1D=0 2D=1 H=0 P=1 W=0 NW=1
+EventLoopMgr      WARNING Unable to locate service "EventSelector"
+EventLoopMgr      WARNING No events will be processed from external input.
+HistogramPersis...   INFO Added successfully Conversion service RootHistSvc
+ApplicationMgr       INFO Application Manager Initialized successfully
+ApplicationMgr       INFO Application Manager Started successfully
+RichTestH1DD         INFO Booked 2 Histogram(s) : 1D=2 2D=0 3D=0 1DProf=0 2DProf=0 3DProf=0
+RichTestH1DD         INFO 1D histograms in directory "RichTestH1DD" : 2
+RichTestH1DF         INFO Booked 2 Histogram(s) : 1D=2 2D=0 3D=0 1DProf=0 2DProf=0 3DProf=0
+RichTestH1DF         INFO 1D histograms in directory "RichTestH1DF" : 2
+RichTestH1DI         INFO Booked 2 Histogram(s) : 1D=2 2D=0 3D=0 1DProf=0 2DProf=0 3DProf=0
+RichTestH1DI         INFO 1D histograms in directory "RichTestH1DI" : 2
+RichTestH2DD         INFO Booked 2 Histogram(s) : 1D=0 2D=2 3D=0 1DProf=0 2DProf=0 3DProf=0
+RichTestH2DD         INFO 2D histograms in directory "RichTestH2DD" : 2
+RichTestH2DF         INFO Booked 2 Histogram(s) : 1D=0 2D=2 3D=0 1DProf=0 2DProf=0 3DProf=0
+RichTestH2DF         INFO 2D histograms in directory "RichTestH2DF" : 2
+RichTestH2DI         INFO Booked 2 Histogram(s) : 1D=0 2D=2 3D=0 1DProf=0 2DProf=0 3DProf=0
+RichTestH2DI         INFO 2D histograms in directory "RichTestH2DI" : 2
+RichTestP1DD         INFO Booked 2 Histogram(s) : 1D=0 2D=0 3D=0 1DProf=2 2DProf=0 3DProf=0
+RichTestP1DD         INFO 1D profile histograms in directory "RichTestP1DD" : 2
+RichTestP1DF         INFO Booked 2 Histogram(s) : 1D=0 2D=0 3D=0 1DProf=2 2DProf=0 3DProf=0
+RichTestP1DF         INFO 1D profile histograms in directory "RichTestP1DF" : 2
+RichTestP1DI         INFO Booked 2 Histogram(s) : 1D=0 2D=0 3D=0 1DProf=2 2DProf=0 3DProf=0
+RichTestP1DI         INFO 1D profile histograms in directory "RichTestP1DI" : 2
+RichTestP2DD         INFO Booked 2 Histogram(s) : 1D=0 2D=0 3D=0 1DProf=0 2DProf=2 3DProf=0
+RichTestP2DD         INFO 2D profile histograms in directory "RichTestP2DD" : 2
+RichTestP2DF         INFO Booked 2 Histogram(s) : 1D=0 2D=0 3D=0 1DProf=0 2DProf=2 3DProf=0
+RichTestP2DF         INFO 2D profile histograms in directory "RichTestP2DF" : 2
+RichTestP2DI         INFO Booked 2 Histogram(s) : 1D=0 2D=0 3D=0 1DProf=0 2DProf=2 3DProf=0
+RichTestP2DI         INFO 2D profile histograms in directory "RichTestP2DI" : 2
+RichTestWH1DD        INFO Booked 2 Histogram(s) : 1D=2 2D=0 3D=0 1DProf=0 2DProf=0 3DProf=0
+RichTestWH1DD        INFO 1D histograms in directory "RichTestWH1DD" : 2
+RichTestWH1DF        INFO Booked 2 Histogram(s) : 1D=2 2D=0 3D=0 1DProf=0 2DProf=0 3DProf=0
+RichTestWH1DF        INFO 1D histograms in directory "RichTestWH1DF" : 2
+RichTestWH2DD        INFO Booked 2 Histogram(s) : 1D=0 2D=2 3D=0 1DProf=0 2DProf=0 3DProf=0
+RichTestWH2DD        INFO 2D histograms in directory "RichTestWH2DD" : 2
+RichTestWH2DF        INFO Booked 2 Histogram(s) : 1D=0 2D=2 3D=0 1DProf=0 2DProf=0 3DProf=0
+RichTestWH2DF        INFO 2D histograms in directory "RichTestWH2DF" : 2
+RichTestWP1DD        INFO Booked 2 Histogram(s) : 1D=0 2D=0 3D=0 1DProf=2 2DProf=0 3DProf=0
+RichTestWP1DD        INFO 1D profile histograms in directory "RichTestWP1DD" : 2
+RichTestWP1DF        INFO Booked 2 Histogram(s) : 1D=0 2D=0 3D=0 1DProf=2 2DProf=0 3DProf=0
+RichTestWP1DF        INFO 1D profile histograms in directory "RichTestWP1DF" : 2
+RichTestWP2DD        INFO Booked 2 Histogram(s) : 1D=0 2D=0 3D=0 1DProf=0 2DProf=2 3DProf=0
+RichTestWP2DD        INFO 2D profile histograms in directory "RichTestWP2DD" : 2
+RichTestWP2DF        INFO Booked 2 Histogram(s) : 1D=0 2D=0 3D=0 1DProf=0 2DProf=2 3DProf=0
+RichTestWP2DF        INFO 2D profile histograms in directory "RichTestWP2DF" : 2
+ApplicationMgr       INFO Application Manager Stopped successfully
+EventLoopMgr         INFO Histograms converted successfully according to request.
+ApplicationMgr       INFO Application Manager Finalized successfully
+ApplicationMgr       INFO Application Manager Terminated successfully
+RichTestH1DD         INFO 1D histograms in directory "RichTestH1DD" : 2
+ | ID                                            | Title                                         |      #     |     Mean   |    RMS     |  Skewness  |  Kurtosis  |
+ | /RICH/RichTestH1DD/testH1D0                   | "Test 1D Histogram 0;Rand Number;Entries"     |      50000 |      25.52 | 14.143     |  0.0091834 |    -1.1995 |
+ | /RICH/RichTestH1DD/testH1D1                   | "Test 1D Histogram 1;Rand Number;Entries"     |      50000 |         25 | 14.975     |          0 |    -1.2116 |
+RichTestH1DF         INFO 1D histograms in directory "RichTestH1DF" : 2
+ | ID                                            | Title                                         |      #     |     Mean   |    RMS     |  Skewness  |  Kurtosis  |
+ | /RICH/RichTestH1DF/testH1D0                   | "Test 1D Histogram 0;Rand Number;Entries"     |      50000 |      25.52 | 14.143     |  0.0091834 |    -1.1995 |
+ | /RICH/RichTestH1DF/testH1D1                   | "Test 1D Histogram 1;Rand Number;Entries"     |      50000 |         25 | 14.975     |          0 |    -1.2116 |
+RichTestH1DI         INFO 1D histograms in directory "RichTestH1DI" : 2
+ | ID                                            | Title                                         |      #     |     Mean   |    RMS     |  Skewness  |  Kurtosis  |
+ | /RICH/RichTestH1DI/testH1D0                   | "Test 1D Histogram 0;Rand Number;Entries"     |      50000 |         51 | 28.849     |          0 |    -1.2031 |
+ | /RICH/RichTestH1DI/testH1D1                   | "Test 1D Histogram 1;Rand Number;Entries"     |      50000 |         49 | 28.849     |          0 |    -1.2031 |
+RichTestWH1DD        INFO 1D histograms in directory "RichTestWH1DD" : 2
+ | ID                                            | Title                                         |      #     |     Mean   |    RMS     |  Skewness  |  Kurtosis  |
+ | /RICH/RichTestWH1DD/testH1D0                  | "Test 1D Histogram 0;Rand Number;Entries"     |      50000 |     34.167 | 11.528     |   -0.56675 |   -0.60602 |
+ | /RICH/RichTestWH1DD/testH1D1                  | "Test 1D Histogram 1;Rand Number;Entries"     |      50000 |     34.167 | 11.528     |   -0.56675 |   -0.60602 |
+RichTestWH1DF        INFO 1D histograms in directory "RichTestWH1DF" : 2
+ | ID                                            | Title                                         |      #     |     Mean   |    RMS     |  Skewness  |  Kurtosis  |
+ | /RICH/RichTestWH1DF/testH1D0                  | "Test 1D Histogram 0;Rand Number;Entries"     |      50000 |     34.167 | 11.528     |   -0.56675 |   -0.60602 |
+ | /RICH/RichTestWH1DF/testH1D1                  | "Test 1D Histogram 1;Rand Number;Entries"     |      50000 |     34.167 | 11.528     |   -0.56675 |   -0.60602 |
+RichTestP1DD         INFO 1D profile histograms in directory "RichTestP1DD" : 2
+ | ID                                            | Title                                         |      #     |     Mean   |    RMS     |  Skewness  |  Kurtosis  |
+ | /RICH/RichTestP1DD/testH1D0                   | "Test 1D Histogram 0;Rand Number;Entries"     |      25000 |       24.5 | 14.422     |          0 |    -1.2038 |
+ | /RICH/RichTestP1DD/testH1D1                   | "Test 1D Histogram 1;Rand Number;Entries"     |      25000 |       24.5 | 14.422     |          0 |    -1.2038 |
+RichTestP1DF         INFO 1D profile histograms in directory "RichTestP1DF" : 2
+ | ID                                            | Title                                         |      #     |     Mean   |    RMS     |  Skewness  |  Kurtosis  |
+ | /RICH/RichTestP1DF/testH1D0                   | "Test 1D Histogram 0;Rand Number;Entries"     |      25000 |       24.5 | 14.422     | 6.5108e-07 |    -1.2039 |
+ | /RICH/RichTestP1DF/testH1D1                   | "Test 1D Histogram 1;Rand Number;Entries"     |      25000 |       24.5 | 14.422     | 6.5108e-07 |    -1.2039 |
+RichTestP1DI         INFO 1D profile histograms in directory "RichTestP1DI" : 2
+ | ID                                            | Title                                         |      #     |     Mean   |    RMS     |  Skewness  |  Kurtosis  |
+ | /RICH/RichTestP1DI/testH1D0                   | "Test 1D Histogram 0;Rand Number;Entries"     |      50000 |       50.5 | 28.862     |          0 |     -1.201 |
+ | /RICH/RichTestP1DI/testH1D1                   | "Test 1D Histogram 1;Rand Number;Entries"     |      50000 |       50.5 | 28.862     |          0 |     -1.201 |
+RichTestWP1DD        INFO 1D profile histograms in directory "RichTestWP1DD" : 2
+ | ID                                            | Title                                         |      #     |     Mean   |    RMS     |  Skewness  |  Kurtosis  |
+ | /RICH/RichTestWP1DD/testH1D0                  | "Test 1D Histogram 0;Rand Number;Entries"     |      50000 |    0.50456 | 0.41173    |     96.152 |     9617.8 |
+ | /RICH/RichTestWP1DD/testH1D1                  | "Test 1D Histogram 1;Rand Number;Entries"     |      50000 |     34.539 | 11.674     |   -0.55601 |   -0.61011 |
+RichTestWP1DF        INFO 1D profile histograms in directory "RichTestWP1DF" : 2
+ | ID                                            | Title                                         |      #     |     Mean   |    RMS     |  Skewness  |  Kurtosis  |
+ | /RICH/RichTestWP1DF/testH1D0                  | "Test 1D Histogram 0;Rand Number;Entries"     |      50000 |    0.50456 | 0.41173    |     96.152 |     9617.8 |
+ | /RICH/RichTestWP1DF/testH1D1                  | "Test 1D Histogram 1;Rand Number;Entries"     |      50000 |     34.539 | 11.674     |   -0.55601 |   -0.61011 |
-- 
GitLab