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 if ( !std::isfinite( floatIdx ) ) {
return floatIdx > 0 ?
numBins() + 1 : 0; }
257 idx =
static_cast<int>( floatIdx );
259 return idx < 0 ? 0 : ( (
unsigned int)idx >
numBins() ?
numBins() + 1 : (
unsigned int)idx );
266 <<
"\"" << axis.
m_title <<
"\", (";
267 for (
auto const& label : axis.
m_labels ) { o <<
"\"" << label <<
"\", "; }
320 template <
typename Arithmetic>
322 j = nlohmann::json{ {
"nBins", axis.
numBins() },
325 {
"title", axis.
title() } };
326 if ( !axis.
labels().empty() ) { j[
"labels"] = axis.
labels(); }
344 template <
typename Arithmetic,
unsigned int NIndex>
348 template <
unsigned int NIndex,
typename... Elements>
352 using std::tuple<Elements...>::tuple;
353 template <
class... AxisType>
354 requires(
sizeof...( AxisType ) == NIndex )
355 unsigned int computeIndex( std::tuple<AxisType...>
const& axis )
const {
358 template <
class... AxisType>
359 requires(
sizeof...( AxisType ) == NIndex )
364 template <
class... AxisType>
365 requires(
sizeof...( AxisType ) == NIndex )
371 template <
int N,
class Tuple>
374 auto const& axis = std::get<N>( allAxis );
375 unsigned int localIndex = axis.index( std::get<N>( *
this ) );
376 if constexpr ( N + 1 == NIndex )
381 template <
int N,
class Tuple>
383 auto const& axis = std::get<N>( allAxis );
384 unsigned int localNBins = axis.numBins() + 2;
385 if constexpr ( N + 1 == NIndex )
390 template <
int N,
class Tuple>
392 auto const& axis = std::get<N>( allAxis );
393 bool localAnswer = axis.inAcceptance( std::get<N>( *
this ) );
394 if constexpr ( N + 1 == NIndex )
406 template <
typename ArithmeticTuple,
unsigned int NIndex,
typename WArithmetic>
410 template <
class... AxisType>
411 requires(
sizeof...( AxisType ) == NIndex )
412 unsigned int computeIndex( std::tuple<AxisType...>
const& axis )
const {
413 return this->first.computeIndex( axis );
415 template <
class... AxisType>
416 requires(
sizeof...( AxisType ) == NIndex )
420 auto forInternalCounter()
const {
return std::pair( this->first.forInternalCounter(), this->second ); }
421 template <
class... AxisType>
422 requires(
sizeof...( AxisType ) == NIndex )
424 return this->first.inAcceptance( axis );
473 template <
atomicity Atomicity,
typename InputType,
typename Arithmetic,
474 template <atomicity Ato,
typename Arith>
typename BaseAccumulatorT,
typename AxisTupleType>
476 template <atomicity,
typename,
typename,
template <atomicity,
typename>
typename,
typename>
480 using ND = std::integral_constant<unsigned int, std::tuple_size_v<AxisTupleType>>;
489 template <atomicity ato>
504 template <atomicity ato>
508 for (
unsigned int index = 0; index <
m_totNBins; index++ ) {
512 [[nodiscard]]
auto operator[](
typename InputType::ValueType v ) {
516 template <
unsigned int N>
518 return std::get<N>(
m_axis );
528 auto nBins(
unsigned int i )
const {
return _getAxis( i, std::integral_constant<size_t, 0>() ).numBins(); }
529 auto minValue(
unsigned int i )
const {
return _getAxis( i, std::integral_constant<size_t, 0>() ).minValue(); }
530 auto maxValue(
unsigned int i )
const {
return _getAxis( i, std::integral_constant<size_t, 0>() ).maxValue(); }
541 std::tuple_element_t<0, AxisTupleType>
const&
_getAxis(
size_t i,
542 typename std::tuple_size<AxisTupleType>::type )
const {
543 throw std::logic_error(
544 std::format(
"Retrieving axis {} in Histogram of dimension {}", i, std::tuple_size_v<AxisTupleType> ) );
547 requires( std::tuple_size_v<AxisTupleType> != N )
548 auto&
_getAxis(
size_t i, std::integral_constant<size_t, N> )
const {
549 if ( i == N )
return std::get<N>(
m_axis );
550 return _getAxis( i, std::integral_constant<size_t, N + 1>() );
566 template <atomicity Atomicity,
typename Arithmetic,
typename ND,
typename AxisTupleType>
576 template <atomicity Atomicity,
typename Arithmetic,
typename ND,
typename AxisTupleType>
587 template <atomicity Atomicity,
typename Arithmetic,
typename ND,
typename AxisTupleType>
598 template <atomicity Atomicity,
typename Arithmetic,
typename ND,
typename AxisTupleType>
661 template <
unsigned int ND,
atomicity Atomicity,
typename Arithmetic,
const char* Type,
662 template <atomicity,
typename,
typename,
typename>
typename Accumulator,
typename AxisTupleType>
664 template <
unsigned int ND,
atomicity Atomicity,
typename Arithmetic,
const char* Type,
665 template <atomicity,
typename,
typename,
typename>
typename Accumulator,
typename... AxisTypes>
667 :
public BufferableCounter<Atomicity, Accumulator, Arithmetic, std::integral_constant<unsigned int, ND>,
668 std::tuple<AxisTypes...>> {
673 using AccumulatorType = Accumulator<Atomicity, Arithmetic, NumberDimensions, AxisTupleType>;
677 inline static const std::string
typeString{ std::string{ Type } +
':' +
typeid( Arithmetic ).name() };
679 template <
typename OWNER>
685 template <
typename OWNER>
689 template <
typename stream>
691 o << ND <<
"D Histogram with config ";
692 std::apply( [&o](
auto&&... args ) { ( ( o << args <<
"\n" ), ... ); }, this->axis() );
695 std::ostream&
print( std::ostream& o,
bool tableFormat =
false )
const override {
702 virtual void to_json( nlohmann::json& j )
const {
704 std::vector<typename AccumulatorType::BaseAccumulator::OutputType> bins;
705 bins.reserve( this->totNBins() );
706 unsigned long totNEntries{ 0 };
707 for (
unsigned int i = 0; i < this->totNBins(); i++ ) {
708 bins.push_back( this->binValue( i ) );
709 totNEntries += this->nEntries( i );
712 j = { {
"type", std::string( Type ) +
":" +
typeid( Arithmetic ).name() },
715 {
"empty", totNEntries == 0 },
716 {
"nEntries", totNEntries },
717 {
"axis", this->axis() },
735 typename AxisTupleType = make_tuple_t<Axis<Arithmetic>, ND>>
741 typename AxisTupleType = make_tuple_t<Axis<Arithmetic>, ND>>
747 typename AxisTupleType = make_tuple_t<Axis<Arithmetic>, ND>>
753 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.