21#include <nlohmann/json.hpp> 
   30  template <
typename Tuple, 
typename Seq>
 
   32  template <
typename Tuple, 
size_t... I>
 
   33  struct SubTuple<Tuple, 
std::index_sequence<I...>> {
 
   34    using type = 
decltype( std::make_tuple( std::get<I>( std::declval<Tuple>() )... ) );
 
   36  template <
typename Tuple, 
unsigned int N>
 
   37  using SubTuple_t = 
typename SubTuple<Tuple, std::make_index_sequence<N>>::type;
 
   40  template <
typename T, 
unsigned int ND, 
typename = std::make_
integer_sequence<
unsigned int, ND>>
 
   42  template <
typename T, 
unsigned int ND, 
unsigned int... S>
 
   43  struct make_tuple<T, ND, 
std::integer_sequence<unsigned int, S...>> {
 
   44    template <
unsigned int>
 
   46    using type    = std::tuple<typeMap<S>...>;
 
   48  template <
typename T, 
unsigned int ND>
 
   49  using make_tuple_t = 
typename make_tuple<T, ND>::type;
 
   52  template <
typename AxisTupleType>
 
   53  struct AxisToArithmetic;
 
   54  template <
typename... Axis>
 
   55  struct AxisToArithmetic<
std::tuple<Axis...>> {
 
   56    using type = std::tuple<
typename Axis::ArithmeticType...>;
 
   58  template <
typename AxisTupleType>
 
   59  using AxisToArithmetic_t = 
typename AxisToArithmetic<AxisTupleType>::type;
 
   60  template <
typename ProfArithmetic, 
typename AxisTupleType>
 
   61  using ProfileAxisToArithmetic_t = 
decltype( std::tuple_cat( std::declval<AxisToArithmetic_t<AxisTupleType>>(),
 
   62                                                              std::declval<std::tuple<ProfArithmetic>>() ) );
 
   69      if ( !sv.empty() && ( std::isspace( sv.back() ) || std::isspace( sv.front() ) ) ) {
 
   71            std::format( 
"Histogram title \'{}\' has whitespace at front or back -- please remove", sv ),
 
 
   81    template <
typename Arithmetic>
 
   82    constexpr decltype( auto ) 
operator()( 
const std::pair<unsigned long, Arithmetic>& v ) 
const noexcept {
 
 
 
   91    template <
typename Arithmetic>
 
   92    constexpr decltype( auto ) 
operator()( 
const std::pair<Arithmetic, Arithmetic>& v ) 
const noexcept {
 
   93      return v.first * v.second;
 
 
 
  101    template <
typename Arithmetic>
 
  102    constexpr decltype( auto ) 
operator()( 
const std::pair<Arithmetic, Arithmetic>& v ) 
const noexcept {
 
  103      return v.first * v.first * v.second;
 
 
 
  111    template <
typename Arithmetic>
 
  112    constexpr decltype( auto ) 
operator()( 
const std::pair<Arithmetic, Arithmetic>& v ) 
const noexcept {
 
  113      return std::pair<unsigned int, Arithmetic>{ 1ul, v.second };
 
 
 
  122  template <
typename Arithmetic, atomicity Atomicity>
 
  125    using AtomicType               = std::pair<std::atomic<unsigned long>, std::atomic<Arithmetic>>;
 
  128    using InternalType             = std::conditional_t<isAtomic, AtomicType, OutputType>;
 
  131        return { v.first.load( std::memory_order_relaxed ), v.second.load( std::memory_order_relaxed ) };
 
 
  138        return { v.first.exchange( newv.first ), v.second.exchange( newv.second ) };
 
  140        return { std::exchange( v.first, newv.first ), std::exchange( v.second, newv.second ) };
 
 
  150        a.second += b.second;
 
 
 
  160  template <atomicity Atomicity, 
typename Arithmetic>
 
  162      : 
GenericAccumulator<std::pair<Arithmetic, Arithmetic>, std::pair<unsigned long, Arithmetic>, Atomicity,
 
  163                           WeightedProfileTransform, ExtractWeight, WeightedAdder<Arithmetic, Atomicity>> {
 
  167    using Base::operator+=;
 
  170      *
this += { 1ul, weight };
 
 
 
  183  template <atomicity Atomicity, 
typename Arithmetic>
 
  185      : 
GenericAccumulator<std::pair<Arithmetic, Arithmetic>, Arithmetic, Atomicity, WeightedProduct> {
 
 
  196  template <atomicity Atomicity, 
typename Arithmetic = 
double>
 
  198      : 
GenericAccumulator<std::pair<Arithmetic, Arithmetic>, Arithmetic, Atomicity, WeightedSquare> {
 
 
  209  template <atomicity Atomicity, 
typename Arithmetic>
 
  218  template <atomicity Atomicity, 
typename Arithmetic>
 
  228  template <
typename Arithmetic>
 
  233          std::string 
title = {}, std::vector<std::string> 
labels = {} )
 
 
  244        : 
Axis( (unsigned int)def.bins(), def.lowEdge(), def.highEdge(), def.
title() ) {}
 
 
  247    unsigned int index( Arithmetic value )
 const {
 
  251      if constexpr ( std::is_integral_v<Arithmetic> ) {
 
  256      return idx < 0 ? 0 : ( (
unsigned int)idx > 
numBins() ? 
numBins() + 1 : (
unsigned int)idx );
 
 
  263        << 
"\"" << axis.
m_title << 
"\", (";
 
  264      for ( 
auto const& label : axis.
m_labels ) { o << 
"\"" << label << 
"\", "; }
 
 
 
  317  template <
typename Arithmetic>
 
  319    j = nlohmann::json{ { 
"nBins", axis.
numBins() },
 
  322                        { 
"title", axis.
title() } };
 
  323    if ( !axis.
labels().empty() ) { j[
"labels"] = axis.
labels(); }
 
 
  341  template <
typename Arithmetic, 
unsigned int NIndex>
 
  345  template <
unsigned int NIndex, 
typename... Elements>
 
  349    using std::tuple<Elements...>::tuple;
 
  350    template <
class... AxisType>
 
  351      requires( 
sizeof...( AxisType ) == NIndex )
 
  352    unsigned int computeIndex( std::tuple<AxisType...> 
const& axis ) 
const {
 
 
  355    template <
class... AxisType>
 
  356      requires( 
sizeof...( AxisType ) == NIndex )
 
  361    template <
class... AxisType>
 
  362      requires( 
sizeof...( AxisType ) == NIndex )
 
  368    template <
int N, 
class Tuple>
 
  371      auto const&  axis       = std::get<N>( allAxis );
 
  372      unsigned int localIndex = axis.index( std::get<N>( *
this ) );
 
  373      if constexpr ( N + 1 == NIndex )
 
 
  378    template <
int N, 
class Tuple>
 
  380      auto const&  axis       = std::get<N>( allAxis );
 
  381      unsigned int localNBins = axis.numBins() + 2;
 
  382      if constexpr ( N + 1 == NIndex )
 
 
  387    template <
int N, 
class Tuple>
 
  389      auto const& axis        = std::get<N>( allAxis );
 
  390      bool        localAnswer = axis.inAcceptance( std::get<N>( *
this ) );
 
  391      if constexpr ( N + 1 == NIndex )
 
 
 
  403  template <
typename ArithmeticTuple, 
unsigned int NIndex, 
typename WArithmetic>
 
  407    template <
class... AxisType>
 
  408      requires( 
sizeof...( AxisType ) == NIndex )
 
  409    unsigned int computeIndex( std::tuple<AxisType...> 
const& axis ) 
const {
 
  410      return this->first.computeIndex( axis );
 
 
  412    template <
class... AxisType>
 
  413      requires( 
sizeof...( AxisType ) == NIndex )
 
  417    auto forInternalCounter()
 const { 
return std::pair( this->first.forInternalCounter(), this->second ); }
 
  418    template <
class... AxisType>
 
  419      requires( 
sizeof...( AxisType ) == NIndex )
 
  421      return this->first.inAcceptance( axis );
 
 
 
  470  template <
atomicity Atomicity, 
typename InputType, 
typename Arithmetic,
 
  471            template <atomicity Ato, 
typename Arith> 
typename BaseAccumulatorT, 
typename AxisTupleType>
 
  473    template <atomicity, 
typename, 
typename, 
template <atomicity, 
typename> 
typename, 
typename>
 
  477    using ND                      = std::integral_constant<unsigned int, std::tuple_size_v<AxisTupleType>>;
 
  486    template <atomicity ato>
 
  501    template <atomicity ato>
 
  505      for ( 
unsigned int index = 0; index < 
m_totNBins; index++ ) {
 
 
  509    [[nodiscard]] 
auto operator[]( 
typename InputType::ValueType v ) {
 
 
  513    template <
unsigned int N>
 
  515      return std::get<N>( 
m_axis );
 
 
  525    auto nBins( 
unsigned int i )
 const { 
return _getAxis( i, std::integral_constant<size_t, 0>() ).numBins(); }
 
  526    auto minValue( 
unsigned int i )
 const { 
return _getAxis( i, std::integral_constant<size_t, 0>() ).minValue(); }
 
  527    auto maxValue( 
unsigned int i )
 const { 
return _getAxis( i, std::integral_constant<size_t, 0>() ).maxValue(); }
 
  538    std::tuple_element_t<0, AxisTupleType> 
const& 
_getAxis( 
size_t i,
 
  539                                                            typename std::tuple_size<AxisTupleType>::type )
 const {
 
  540      throw std::logic_error(
 
  541          std::format( 
"Retrieving axis {} in Histogram of dimension {}", i, std::tuple_size_v<AxisTupleType> ) );
 
 
  544      requires( std::tuple_size_v<AxisTupleType> != N )
 
  545    auto& 
_getAxis( 
size_t i, std::integral_constant<size_t, N> ) 
const {
 
  546      if ( i == N ) 
return std::get<N>( 
m_axis );
 
  547      return _getAxis( i, std::integral_constant<size_t, N + 1>() );
 
 
 
  563  template <atomicity Atomicity, 
typename Arithmetic, 
typename ND, 
typename AxisTupleType>
 
  573  template <atomicity Atomicity, 
typename Arithmetic, 
typename ND, 
typename AxisTupleType>
 
  584  template <atomicity Atomicity, 
typename Arithmetic, 
typename ND, 
typename AxisTupleType>
 
  595  template <atomicity Atomicity, 
typename Arithmetic, 
typename ND, 
typename AxisTupleType>
 
  658  template <
unsigned int ND, 
atomicity Atomicity, 
typename Arithmetic, 
const char* Type,
 
  659            template <atomicity, 
typename, 
typename, 
typename> 
typename Accumulator, 
typename AxisTupleType>
 
  661  template <
unsigned int ND, 
atomicity Atomicity, 
typename Arithmetic, 
const char* Type,
 
  662            template <atomicity, 
typename, 
typename, 
typename> 
typename Accumulator, 
typename... AxisTypes>
 
  664      : 
public BufferableCounter<Atomicity, Accumulator, Arithmetic, std::integral_constant<unsigned int, ND>,
 
  665                                 std::tuple<AxisTypes...>> {
 
  670    using AccumulatorType  = Accumulator<Atomicity, Arithmetic, NumberDimensions, AxisTupleType>;
 
  674    inline static const std::string 
typeString{ std::string{ Type } + 
':' + 
typeid( Arithmetic ).name() };
 
  676    template <
typename OWNER>
 
  682    template <
typename OWNER>
 
  686    template <
typename stream>
 
  688      o << ND << 
"D Histogram with config ";
 
  689      std::apply( [&o]( 
auto&&... args ) { ( ( o << args << 
"\n" ), ... ); }, this->axis() );
 
 
  692    std::ostream& 
print( std::ostream& o, 
bool tableFormat = 
false )
 const override {
 
 
  699    virtual void to_json( nlohmann::json& j )
 const {
 
  701      std::vector<typename AccumulatorType::BaseAccumulator::OutputType> bins;
 
  702      bins.reserve( this->totNBins() );
 
  703      unsigned long totNEntries{ 0 };
 
  704      for ( 
unsigned int i = 0; i < this->totNBins(); i++ ) {
 
  705        bins.push_back( this->binValue( i ) );
 
  706        totNEntries += this->nEntries( i );
 
  709      j = { { 
"type", std::string( Type ) + 
":" + 
typeid( Arithmetic ).name() },
 
  712            { 
"empty", totNEntries == 0 },
 
  713            { 
"nEntries", totNEntries },
 
  714            { 
"axis", this->axis() },
 
 
 
  732            typename AxisTupleType = make_tuple_t<Axis<Arithmetic>, ND>>
 
  738            typename AxisTupleType = make_tuple_t<Axis<Arithmetic>, ND>>
 
  744            typename AxisTupleType = make_tuple_t<Axis<Arithmetic>, ND>>
 
  750            typename AxisTupleType = make_tuple_t<Axis<Arithmetic>, ND>>
 
Definition of a default type of Histogram Axis It contains number of bins, min and max value plus a t...
std::string const & title() const
void setMinValue(Arithmetic v)
Arithmetic minValue() const
unsigned int numBins() const
void setMaxValue(Arithmetic v)
Arithmetic m_minValue
min and max values on this axis
std::vector< std::string > m_labels
labels for the bins
Axis(unsigned int nBins=0, Arithmetic minValue=Arithmetic{}, Arithmetic maxValue=Arithmetic{}, std::string title={}, std::vector< std::string > labels={})
std::vector< std::string > const & labels() const
bool inAcceptance(Arithmetic value) const
says whether the given value is within the range of the axis
void setNumBins(unsigned int n)
Arithmetic ArithmeticType
Arithmetic maxValue() const
friend std::ostream & operator<<(std::ostream &o, Axis const &axis)
Axis(Gaudi::Histo1DDef const &def)
void setTitle(std::string const &t)
std::string m_title
title of this axis
unsigned int nBins
number of bins for this Axis FIXME : should be private and called m_nBins but will break backward com...
unsigned int index(Arithmetic value) const
returns the bin number for a given value, ranging from 0 (underflow) to nBins+1 (overflow)
Arithmetic m_ratio
precomputed ratio to convert a value into bin number equal to nBins/(maxValue-minValue).
Buffer is a non atomic Accumulator which, when it goes out-of-scope, updates the underlying thread-sa...
BufferableCounter()=default
friend class GenericAccumulator
Internal Accumulator class dealing with Histograming.
auto maxValue(unsigned int i) const
HistogramingAccumulatorInternal(AxisTupleType axis)
auto operator[](typename InputType::ValueType v)
std::integral_constant< unsigned int, std::tuple_size_v< AxisTupleType > > ND
friend class HistogramingAccumulatorInternal
void mergeAndReset(HistogramingAccumulatorInternal< ato, InputType, Arithmetic, BaseAccumulatorT, AxisTupleType > &other)
auto & _getAxis(size_t i, std::integral_constant< size_t, N >) const
auto binValue(unsigned int i) const
BaseAccumulator & accumulator(unsigned int index) const
std::tuple_element_t< 0, AxisTupleType > const & _getAxis(size_t i, typename std::tuple_size< AxisTupleType >::type) const
HistogramingAccumulatorInternal & operator+=(InputType v)
BaseAccumulatorT< Atomicity, Arithmetic > BaseAccumulator
auto nBins(unsigned int i) const
HistogramingAccumulatorInternal(construct_empty_t, const HistogramingAccumulatorInternal< ato, InputType, Arithmetic, BaseAccumulatorT, AxisTupleType > &other)
typename InputType::ValueType AxisTupleArithmeticType
std::unique_ptr< BaseAccumulator[]> m_value
auto minValue(unsigned int i) const
auto nEntries(unsigned int i) const
A base counter dealing with Histograms.
friend void reset(HistogramingCounterBase &c)
std::ostream & print(std::ostream &o, bool tableFormat=false) const override
prints the counter to a stream
MsgStream & print(MsgStream &o, bool tableFormat=false) const override
std::tuple< AxisTypes... > AxisTupleType
std::string const & title() const
typename AccumulatorType::AxisTupleArithmeticType AxisTupleArithmeticType
friend void mergeAndReset(HistogramingCounterBase &h, HistogramingCounterBase &o)
std::string const m_title
friend void to_json(nlohmann::json &j, HistogramingCounterBase const &h)
Accumulator< Atomicity, Arithmetic, NumberDimensions, AxisTupleType > AccumulatorType
HistogramingCounterBase(OWNER *owner, std::string const &name, std::string const &title, AxisTypes... allAxis)
This constructor takes the axis one by one, when ND >= 2. If ND = 1, the other one can be used.
stream & printImpl(stream &o, bool) const
typename std::tuple_element< 0, AxisTupleType >::type::ArithmeticType AxisArithmeticType
for backward compatibility with previous implementation, should not be used FIXME
std::integral_constant< unsigned int, ND > NumberDimensions
static const std::string typeString
HistogramingCounterBase(OWNER *owner, std::string const &name, std::string const &title, AxisTupleType axis)
This constructor takes the axis as a tuple.
virtual void to_json(nlohmann::json &j) const
BufferableCounter< Atomicity, Accumulator, Arithmetic, NumberDimensions, AxisTupleType > Parent
Simple helper class for description of 1D-histogram The class is targeted to act as the primary "hist...
Define general base for Gaudi exception.
Definition of the MsgStream class used to transmit messages.
constexpr static const auto FAILURE
void requireValidTitle(std::string_view sv)
constexpr char profilehistogramString[]
constexpr char histogramString[]
constexpr char weightedProfilehistogramString[]
constexpr char weightedHistogramString[]
Efficient counter implementations for Gaudi.
HistogramingAccumulatorInternal< Atomicity, HistoInputType< ProfileAxisToArithmetic_t< Arithmetic, AxisTupleType >, ND::value >, Arithmetic, SigmaAccumulator, AxisTupleType > ProfileHistogramingAccumulator
Class implementing a profile histogram accumulator.
HistogramingAccumulatorInternal< Atomicity, HistoInputType< AxisToArithmetic_t< AxisTupleType >, ND::value >, unsigned long, IntegralAccumulator, AxisTupleType > HistogramingAccumulator
Class implementing a regular histogram accumulator.
void to_json(nlohmann::json &j, const Axis< Arithmetic > &axis)
automatic conversion of the Axis type to json
SigmaAccumulatorBase< Atomicity, Arithmetic, WeightedAveragingAccumulator, WeightedSquareAccumulator > WeightedSigmaAccumulator
WeightedSigmaAccumulator.
HistogramingAccumulatorInternal< Atomicity, WeightedHistoInputType< ProfileAxisToArithmetic_t< Arithmetic, AxisTupleType >, ND::value, Arithmetic >, Arithmetic, WeightedSigmaAccumulator, AxisTupleType > WeightedProfileHistogramingAccumulator
Class implementing a weighted profile histogram accumulator.
HistogramingCounterBase< ND, Atomicity, Arithmetic, naming::profilehistogramString, ProfileHistogramingAccumulator, AxisTupleType > StaticProfileHistogram
profile static histograming counter. See HistogramingCounterBase for details
AveragingAccumulatorBase< Atomicity, Arithmetic, WeightedCountAccumulator, WeightedSumAccumulator > WeightedAveragingAccumulator
WeightedAveragingAccumulator.
HistogramingCounterBase< ND, Atomicity, Arithmetic, naming::histogramString, HistogramingAccumulator, AxisTupleType > StaticHistogram
standard static histograming counter. See HistogramingCounterBase for details
HistogramingCounterBase< ND, Atomicity, Arithmetic, naming::weightedProfilehistogramString, WeightedProfileHistogramingAccumulator, AxisTupleType > StaticWeightedProfileHistogram
weighted static profile histograming counter. See HistogramingCounterBase for details
atomicity
Defines atomicity of the accumulators.
void fetch_add(AtomicType &atVar, Arithmetic value)
generic fetch_add, also dealing with atomic types with no fetch_add member method
SigmaAccumulatorBase< Atomicity, Arithmetic, AveragingAccumulator, SquareAccumulator > SigmaAccumulator
SigmaAccumulator.
HistogramingAccumulatorInternal< Atomicity, WeightedHistoInputType< AxisToArithmetic_t< AxisTupleType >, ND::value, Arithmetic >, Arithmetic, WeightedCountAccumulator, AxisTupleType > WeightedHistogramingAccumulator
Class implementing a weighted histogram accumulator.
HistogramingCounterBase< ND, Atomicity, Arithmetic, naming::weightedHistogramString, WeightedHistogramingAccumulator, AxisTupleType > StaticWeightedHistogram
standard static histograming counter with weight. See HistogramingCounterBase for details
AveragingAccumulatorBase.
An Adder ValueHandler, taking weight into account and computing a count plus the sum of the weights I...
static constexpr bool isAtomic
std::conditional_t< isAtomic, AtomicType, OutputType > InternalType
static RegularType exchange(InternalType &v, RegularType newv) noexcept
std::pair< std::atomic< unsigned long >, std::atomic< Arithmetic > > AtomicType
static constexpr OutputType DefaultValue()
static constexpr OutputType getValue(const InternalType &v) noexcept
static void merge(InternalType &a, RegularType b) noexcept
std::pair< unsigned long, Arithmetic > RegularType
WeightedCountAccumulator.
GenericAccumulator< std::pair< Arithmetic, Arithmetic >, std::pair< unsigned long, Arithmetic >, Atomicity, WeightedProfileTransform, ExtractWeight, WeightedAdder< Arithmetic, Atomicity > > Base
Arithmetic sumOfWeights() const
unsigned long nEntries() const
WeightedCountAccumulator operator+=(const Arithmetic weight)
overload of operator+= to be able to only give weight and no value
A Product functor, take a pair (value, weight) as input.
WeightedSquareAccumulator.
A WeightedSquare functor, take a pair (value, weight) as input.
constant used to disambiguate construction of an empty Accumulator versus the copy constructor.