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.