File indexing completed on 2025-09-15 08:57:51
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #pragma once
0012
0013 #include <Gaudi/Accumulators.h>
0014 #include <Gaudi/MonitoringHub.h>
0015 #include <GaudiKernel/HistoDef.h>
0016
0017 #include <array>
0018 #include <cassert>
0019 #include <cmath>
0020 #include <fmt/format.h>
0021 #include <nlohmann/json.hpp>
0022 #include <string>
0023 #include <type_traits>
0024 #include <utility>
0025 #include <vector>
0026
0027 namespace {
0028
0029
0030 template <typename Tuple, typename Seq>
0031 struct SubTuple;
0032 template <typename Tuple, size_t... I>
0033 struct SubTuple<Tuple, std::index_sequence<I...>> {
0034 using type = decltype( std::make_tuple( std::get<I>( std::declval<Tuple>() )... ) );
0035 };
0036 template <typename Tuple, unsigned int N>
0037 using SubTuple_t = typename SubTuple<Tuple, std::make_index_sequence<N>>::type;
0038
0039
0040 template <typename T, unsigned int ND, typename = std::make_integer_sequence<unsigned int, ND>>
0041 struct make_tuple;
0042 template <typename T, unsigned int ND, unsigned int... S>
0043 struct make_tuple<T, ND, std::integer_sequence<unsigned int, S...>> {
0044 template <unsigned int>
0045 using typeMap = T;
0046 using type = std::tuple<typeMap<S>...>;
0047 };
0048 template <typename T, unsigned int ND>
0049 using make_tuple_t = typename make_tuple<T, ND>::type;
0050
0051
0052 template <typename AxisTupleType>
0053 struct AxisToArithmetic;
0054 template <typename... Axis>
0055 struct AxisToArithmetic<std::tuple<Axis...>> {
0056 using type = std::tuple<typename Axis::ArithmeticType...>;
0057 };
0058 template <typename AxisTupleType>
0059 using AxisToArithmetic_t = typename AxisToArithmetic<AxisTupleType>::type;
0060 template <typename ProfArithmetic, typename AxisTupleType>
0061 using ProfileAxisToArithmetic_t = decltype( std::tuple_cat( std::declval<AxisToArithmetic_t<AxisTupleType>>(),
0062 std::declval<std::tuple<ProfArithmetic>>() ) );
0063 }
0064
0065 namespace Gaudi::Accumulators {
0066
0067 namespace details {
0068 inline void requireValidTitle( std::string_view sv ) {
0069 if ( !sv.empty() && ( std::isspace( sv.back() ) || std::isspace( sv.front() ) ) ) {
0070 throw GaudiException(
0071 fmt::format( "Histogram title \'{}\' has whitespace at front or back -- please remove", sv ),
0072 "Gaudi::Accumulators", StatusCode::FAILURE );
0073 }
0074 }
0075 }
0076
0077
0078
0079
0080 struct ExtractWeight {
0081 template <typename Arithmetic>
0082 constexpr decltype( auto ) operator()( const std::pair<unsigned long, Arithmetic>& v ) const noexcept {
0083 return v.second;
0084 }
0085 };
0086
0087
0088
0089
0090 struct WeightedProduct {
0091 template <typename Arithmetic>
0092 constexpr decltype( auto ) operator()( const std::pair<Arithmetic, Arithmetic>& v ) const noexcept {
0093 return v.first * v.second;
0094 }
0095 };
0096
0097
0098
0099
0100 struct WeightedSquare {
0101 template <typename Arithmetic>
0102 constexpr decltype( auto ) operator()( const std::pair<Arithmetic, Arithmetic>& v ) const noexcept {
0103 return v.first * v.first * v.second;
0104 }
0105 };
0106
0107
0108
0109
0110 struct WeightedProfileTransform {
0111 template <typename Arithmetic>
0112 constexpr decltype( auto ) operator()( const std::pair<Arithmetic, Arithmetic>& v ) const noexcept {
0113 return std::pair<unsigned int, Arithmetic>{ 1ul, v.second };
0114 }
0115 };
0116
0117
0118
0119
0120
0121
0122 template <typename Arithmetic, atomicity Atomicity>
0123 struct WeightedAdder {
0124 using RegularType = std::pair<unsigned long, Arithmetic>;
0125 using AtomicType = std::pair<std::atomic<unsigned long>, std::atomic<Arithmetic>>;
0126 using OutputType = RegularType;
0127 static constexpr bool isAtomic = Atomicity == atomicity::full;
0128 using InternalType = std::conditional_t<isAtomic, AtomicType, OutputType>;
0129 static constexpr OutputType getValue( const InternalType& v ) noexcept {
0130 if constexpr ( isAtomic ) {
0131 return { v.first.load( std::memory_order_relaxed ), v.second.load( std::memory_order_relaxed ) };
0132 } else {
0133 return v;
0134 }
0135 }
0136 static RegularType exchange( InternalType& v, RegularType newv ) noexcept {
0137 if constexpr ( isAtomic ) {
0138 return { v.first.exchange( newv.first ), v.second.exchange( newv.second ) };
0139 } else {
0140 return { std::exchange( v.first, newv.first ), std::exchange( v.second, newv.second ) };
0141 }
0142 }
0143 static constexpr OutputType DefaultValue() { return { 0, Arithmetic{} }; }
0144 static void merge( InternalType& a, RegularType b ) noexcept {
0145 if constexpr ( isAtomic ) {
0146 fetch_add( a.first, b.first );
0147 fetch_add( a.second, b.second );
0148 } else {
0149 a.first += b.first;
0150 a.second += b.second;
0151 }
0152 }
0153 };
0154
0155
0156
0157
0158
0159
0160 template <atomicity Atomicity, typename Arithmetic>
0161 struct WeightedCountAccumulator
0162 : GenericAccumulator<std::pair<Arithmetic, Arithmetic>, std::pair<unsigned long, Arithmetic>, Atomicity,
0163 WeightedProfileTransform, ExtractWeight, WeightedAdder<Arithmetic, Atomicity>> {
0164 using Base = GenericAccumulator<std::pair<Arithmetic, Arithmetic>, std::pair<unsigned long, Arithmetic>, Atomicity,
0165 WeightedProfileTransform, ExtractWeight, WeightedAdder<Arithmetic, Atomicity>>;
0166 using Base::Base;
0167 using Base::operator+=;
0168
0169 WeightedCountAccumulator operator+=( const Arithmetic weight ) {
0170 *this += { 1ul, weight };
0171 return *this;
0172 }
0173 unsigned long nEntries() const { return this->rawValue().first; }
0174 Arithmetic sumOfWeights() const { return this->rawValue().second; }
0175 };
0176
0177
0178
0179
0180
0181
0182
0183 template <atomicity Atomicity, typename Arithmetic>
0184 struct WeightedSumAccumulator
0185 : GenericAccumulator<std::pair<Arithmetic, Arithmetic>, Arithmetic, Atomicity, WeightedProduct> {
0186 using GenericAccumulator<std::pair<Arithmetic, Arithmetic>, Arithmetic, Atomicity,
0187 WeightedProduct>::GenericAccumulator;
0188 Arithmetic sum() const { return this->value(); }
0189 };
0190
0191
0192
0193
0194
0195
0196 template <atomicity Atomicity, typename Arithmetic = double>
0197 struct WeightedSquareAccumulator
0198 : GenericAccumulator<std::pair<Arithmetic, Arithmetic>, Arithmetic, Atomicity, WeightedSquare> {
0199 using GenericAccumulator<std::pair<Arithmetic, Arithmetic>, Arithmetic, Atomicity,
0200 WeightedSquare>::GenericAccumulator;
0201 Arithmetic sum2() const { return this->value(); }
0202 };
0203
0204
0205
0206
0207
0208
0209 template <atomicity Atomicity, typename Arithmetic>
0210 using WeightedAveragingAccumulator =
0211 AveragingAccumulatorBase<Atomicity, Arithmetic, WeightedCountAccumulator, WeightedSumAccumulator>;
0212
0213
0214
0215
0216
0217
0218 template <atomicity Atomicity, typename Arithmetic>
0219 using WeightedSigmaAccumulator =
0220 SigmaAccumulatorBase<Atomicity, Arithmetic, WeightedAveragingAccumulator, WeightedSquareAccumulator>;
0221
0222
0223
0224
0225
0226
0227
0228 template <typename Arithmetic>
0229 class Axis {
0230 public:
0231 using ArithmeticType = Arithmetic;
0232 Axis( unsigned int nBins = 0, Arithmetic minValue = Arithmetic{}, Arithmetic maxValue = Arithmetic{},
0233 std::string title = {}, std::vector<std::string> labels = {} )
0234 : m_title( std::move( title ) )
0235 , nBins( nBins )
0236 , m_minValue( minValue )
0237 , m_maxValue( maxValue )
0238 , m_labels( std::move( labels ) ) {
0239 details::requireValidTitle( m_title );
0240 recomputeRatio();
0241 for ( const auto& s : m_labels ) details::requireValidTitle( s );
0242 }
0243 explicit Axis( Gaudi::Histo1DDef const& def )
0244 : Axis( (unsigned int)def.bins(), def.lowEdge(), def.highEdge(), def.title() ) {}
0245
0246
0247 unsigned int index( Arithmetic value ) const {
0248
0249
0250 int idx;
0251 if constexpr ( std::is_integral_v<Arithmetic> ) {
0252 idx = ( ( value - m_minValue ) * nBins / ( m_maxValue - m_minValue ) ) + 1;
0253 } else {
0254 idx = std::floor( ( value - m_minValue ) * m_ratio ) + 1;
0255 }
0256 return idx < 0 ? 0 : ( (unsigned int)idx > numBins() ? numBins() + 1 : (unsigned int)idx );
0257 }
0258
0259 friend std::ostream& operator<<( std::ostream& o, Axis const& axis ) {
0260
0261
0262 o << "(" << axis.numBins() << ", " << axis.minValue() << ", " << axis.maxValue() << ", "
0263 << "\"" << axis.m_title << "\", (";
0264 for ( auto const& label : axis.m_labels ) { o << "\"" << label << "\", "; }
0265 return o << "))";
0266 }
0267
0268
0269 bool inAcceptance( Arithmetic value ) const { return value >= m_minValue && value <= m_maxValue; }
0270
0271
0272 unsigned int numBins() const { return nBins; }
0273 void setNumBins( unsigned int n ) {
0274 nBins = n;
0275 recomputeRatio();
0276 }
0277 Arithmetic minValue() const { return m_minValue; }
0278 void setMinValue( Arithmetic v ) {
0279 m_minValue = v;
0280 recomputeRatio();
0281 }
0282 Arithmetic maxValue() const { return m_maxValue; }
0283 void setMaxValue( Arithmetic v ) {
0284 m_maxValue = v;
0285 recomputeRatio();
0286 }
0287 std::string const& title() const { return m_title; }
0288 void setTitle( std::string const& t ) { m_title = t; }
0289 std::vector<std::string> const labels() const { return m_labels; }
0290
0291 private:
0292
0293 std::string m_title;
0294
0295 public:
0296
0297
0298 unsigned int nBins;
0299
0300 private:
0301
0302 Arithmetic m_minValue, m_maxValue;
0303
0304
0305
0306
0307 Arithmetic m_ratio;
0308
0309 std::vector<std::string> m_labels;
0310
0311 void recomputeRatio() {
0312 m_ratio = ( m_maxValue == m_minValue ) ? Arithmetic{} : nBins / ( m_maxValue - m_minValue );
0313 }
0314 };
0315
0316
0317 template <typename Arithmetic>
0318 void to_json( nlohmann::json& j, const Axis<Arithmetic>& axis ) {
0319 j = nlohmann::json{ { "nBins", axis.numBins() },
0320 { "minValue", axis.minValue() },
0321 { "maxValue", axis.maxValue() },
0322 { "title", axis.title() } };
0323 if ( !axis.labels().empty() ) { j["labels"] = axis.labels(); }
0324 }
0325
0326
0327
0328
0329
0330
0331
0332
0333
0334
0335
0336
0337
0338
0339
0340
0341 template <typename Arithmetic, unsigned int NIndex>
0342 struct HistoInputType : HistoInputType<make_tuple_t<Arithmetic, NIndex>, NIndex> {
0343 using HistoInputType<make_tuple_t<Arithmetic, NIndex>, NIndex>::HistoInputType;
0344 };
0345 template <unsigned int NIndex, typename... Elements>
0346 struct HistoInputType<std::tuple<Elements...>, NIndex> : std::tuple<Elements...> {
0347 using InternalType = std::tuple<Elements...>;
0348 using ValueType = HistoInputType<SubTuple_t<InternalType, NIndex>, NIndex>;
0349 using std::tuple<Elements...>::tuple;
0350 template <class... AxisType>
0351 requires( sizeof...( AxisType ) == NIndex )
0352 unsigned int computeIndex( std::tuple<AxisType...> const& axis ) const {
0353 return computeIndexInternal<0, std::tuple<AxisType...>>( axis );
0354 }
0355 template <class... AxisType>
0356 requires( sizeof...( AxisType ) == NIndex )
0357 static unsigned int computeTotNBins( std::tuple<AxisType...> const& axis ) {
0358 return computeTotNBinsInternal<0, std::tuple<AxisType...>>( axis );
0359 }
0360 auto forInternalCounter() const { return 1ul; }
0361 template <class... AxisType>
0362 requires( sizeof...( AxisType ) == NIndex )
0363 bool inAcceptance( std::tuple<AxisType...> const& axis ) const {
0364 return inAcceptanceInternal<0, std::tuple<AxisType...>>( axis );
0365 }
0366
0367 private:
0368 template <int N, class Tuple>
0369 unsigned int computeIndexInternal( Tuple const& allAxis ) const {
0370
0371 auto const& axis = std::get<N>( allAxis );
0372 unsigned int localIndex = axis.index( std::get<N>( *this ) );
0373 if constexpr ( N + 1 == NIndex )
0374 return localIndex;
0375 else
0376 return localIndex + ( axis.numBins() + 2 ) * computeIndexInternal<N + 1, Tuple>( allAxis );
0377 }
0378 template <int N, class Tuple>
0379 static unsigned int computeTotNBinsInternal( Tuple const& allAxis ) {
0380 auto const& axis = std::get<N>( allAxis );
0381 unsigned int localNBins = axis.numBins() + 2;
0382 if constexpr ( N + 1 == NIndex )
0383 return localNBins;
0384 else
0385 return localNBins * computeTotNBinsInternal<N + 1, Tuple>( allAxis );
0386 }
0387 template <int N, class Tuple>
0388 bool inAcceptanceInternal( Tuple const& allAxis ) const {
0389 auto const& axis = std::get<N>( allAxis );
0390 bool localAnswer = axis.inAcceptance( std::get<N>( *this ) );
0391 if constexpr ( N + 1 == NIndex )
0392 return localAnswer;
0393 else
0394 return localAnswer || inAcceptanceInternal<N + 1, Tuple>( allAxis );
0395 }
0396 };
0397
0398
0399
0400
0401
0402
0403 template <typename ArithmeticTuple, unsigned int NIndex, typename WArithmetic>
0404 struct WeightedHistoInputType : std::pair<HistoInputType<ArithmeticTuple, NIndex>, WArithmetic> {
0405 using ValueType = typename HistoInputType<ArithmeticTuple, NIndex>::ValueType;
0406 using std::pair<HistoInputType<ArithmeticTuple, NIndex>, WArithmetic>::pair;
0407 template <class... AxisType>
0408 requires( sizeof...( AxisType ) == NIndex )
0409 unsigned int computeIndex( std::tuple<AxisType...> const& axis ) const {
0410 return this->first.computeIndex( axis );
0411 }
0412 template <class... AxisType>
0413 requires( sizeof...( AxisType ) == NIndex )
0414 static unsigned int computeTotNBins( std::tuple<AxisType...> const& axis ) {
0415 return HistoInputType<ArithmeticTuple, NIndex>::computeTotNBins( axis );
0416 }
0417 auto forInternalCounter() const { return std::pair( this->first.forInternalCounter(), this->second ); }
0418 template <class... AxisType>
0419 requires( sizeof...( AxisType ) == NIndex )
0420 bool inAcceptance( std::tuple<AxisType...> const& axis ) const {
0421 return this->first.inAcceptance( axis );
0422 }
0423 };
0424
0425
0426
0427
0428
0429
0430
0431
0432
0433
0434
0435
0436
0437
0438
0439
0440
0441
0442
0443
0444
0445
0446
0447
0448
0449
0450
0451
0452
0453
0454
0455
0456
0457
0458
0459
0460
0461
0462
0463
0464
0465
0466
0467
0468
0469
0470 template <atomicity Atomicity, typename InputType, typename Arithmetic,
0471 template <atomicity Ato, typename Arith> typename BaseAccumulatorT, typename AxisTupleType>
0472 class HistogramingAccumulatorInternal {
0473 template <atomicity, typename, typename, template <atomicity, typename> typename, typename>
0474 friend class HistogramingAccumulatorInternal;
0475
0476 public:
0477 using ND = std::integral_constant<unsigned int, std::tuple_size_v<AxisTupleType>>;
0478 using BaseAccumulator = BaseAccumulatorT<Atomicity, Arithmetic>;
0479 using AxisTupleArithmeticType = typename InputType::ValueType;
0480 HistogramingAccumulatorInternal( AxisTupleType axis )
0481 : m_axis{ axis }
0482 , m_totNBins{ InputType::computeTotNBins( m_axis ) }
0483 , m_value( new BaseAccumulator[m_totNBins] ) {
0484 reset();
0485 }
0486 template <atomicity ato>
0487 HistogramingAccumulatorInternal(
0488 construct_empty_t,
0489 const HistogramingAccumulatorInternal<ato, InputType, Arithmetic, BaseAccumulatorT, AxisTupleType>& other )
0490 : m_axis( other.m_axis ), m_totNBins{ other.m_totNBins }, m_value( new BaseAccumulator[m_totNBins] ) {
0491 reset();
0492 }
0493 [[deprecated( "Use `++h1[x]`, `++h2[{x,y}]`, etc. instead." )]] HistogramingAccumulatorInternal&
0494 operator+=( InputType v ) {
0495 accumulator( v.computeIndex( m_axis ) ) += v.forInternalCounter();
0496 return *this;
0497 }
0498 void reset() {
0499 for ( unsigned int index = 0; index < m_totNBins; index++ ) { accumulator( index ).reset(); }
0500 }
0501 template <atomicity ato>
0502 void mergeAndReset(
0503 HistogramingAccumulatorInternal<ato, InputType, Arithmetic, BaseAccumulatorT, AxisTupleType>& other ) {
0504 assert( m_totNBins == other.m_totNBins );
0505 for ( unsigned int index = 0; index < m_totNBins; index++ ) {
0506 accumulator( index ).mergeAndReset( other.accumulator( index ) );
0507 }
0508 }
0509 [[nodiscard]] auto operator[]( typename InputType::ValueType v ) {
0510 return Buffer<BaseAccumulatorT, Atomicity, Arithmetic>{ accumulator( v.computeIndex( m_axis ) ) };
0511 }
0512
0513 template <unsigned int N>
0514 auto& axis() const {
0515 return std::get<N>( m_axis );
0516 }
0517 auto& axis() const { return m_axis; }
0518 auto binValue( unsigned int i ) const { return accumulator( i ).value(); }
0519 auto nEntries( unsigned int i ) const { return accumulator( i ).nEntries(); }
0520 auto totNBins() const { return m_totNBins; }
0521
0522
0523
0524
0525 auto nBins( unsigned int i ) const { return _getAxis( i, std::integral_constant<size_t, 0>() ).numBins(); }
0526 auto minValue( unsigned int i ) const { return _getAxis( i, std::integral_constant<size_t, 0>() ).minValue(); }
0527 auto maxValue( unsigned int i ) const { return _getAxis( i, std::integral_constant<size_t, 0>() ).maxValue(); }
0528
0529 private:
0530 BaseAccumulator& accumulator( unsigned int index ) const {
0531 assert( index < m_totNBins );
0532 assert( m_value.get() );
0533 return m_value[index];
0534 }
0535
0536
0537
0538 std::tuple_element_t<0, AxisTupleType> const& _getAxis( size_t i,
0539 typename std::tuple_size<AxisTupleType>::type ) const {
0540 throw std::logic_error(
0541 fmt::format( "Retrieving axis {} in Histogram of dimension {}", i, std::tuple_size_v<AxisTupleType> ) );
0542 }
0543 template <size_t N>
0544 requires( std::tuple_size_v<AxisTupleType> != N )
0545 auto& _getAxis( size_t i, std::integral_constant<size_t, N> ) const {
0546 if ( i == N ) return std::get<N>( m_axis );
0547 return _getAxis( i, std::integral_constant<size_t, N + 1>() );
0548 }
0549
0550
0551 AxisTupleType m_axis;
0552
0553 unsigned int m_totNBins{};
0554
0555 std::unique_ptr<BaseAccumulator[]> m_value;
0556 };
0557
0558
0559
0560
0561
0562
0563 template <atomicity Atomicity, typename Arithmetic, typename ND, typename AxisTupleType>
0564 using HistogramingAccumulator =
0565 HistogramingAccumulatorInternal<Atomicity, HistoInputType<AxisToArithmetic_t<AxisTupleType>, ND::value>,
0566 unsigned long, IntegralAccumulator, AxisTupleType>;
0567
0568
0569
0570
0571
0572
0573 template <atomicity Atomicity, typename Arithmetic, typename ND, typename AxisTupleType>
0574 using WeightedHistogramingAccumulator =
0575 HistogramingAccumulatorInternal<Atomicity,
0576 WeightedHistoInputType<AxisToArithmetic_t<AxisTupleType>, ND::value, Arithmetic>,
0577 Arithmetic, WeightedCountAccumulator, AxisTupleType>;
0578
0579
0580
0581
0582
0583
0584 template <atomicity Atomicity, typename Arithmetic, typename ND, typename AxisTupleType>
0585 using ProfileHistogramingAccumulator =
0586 HistogramingAccumulatorInternal<Atomicity,
0587 HistoInputType<ProfileAxisToArithmetic_t<Arithmetic, AxisTupleType>, ND::value>,
0588 Arithmetic, SigmaAccumulator, AxisTupleType>;
0589
0590
0591
0592
0593
0594
0595 template <atomicity Atomicity, typename Arithmetic, typename ND, typename AxisTupleType>
0596 using WeightedProfileHistogramingAccumulator = HistogramingAccumulatorInternal<
0597 Atomicity, WeightedHistoInputType<ProfileAxisToArithmetic_t<Arithmetic, AxisTupleType>, ND::value, Arithmetic>,
0598 Arithmetic, WeightedSigmaAccumulator, AxisTupleType>;
0599
0600
0601
0602
0603
0604
0605
0606
0607
0608
0609
0610
0611
0612
0613
0614
0615
0616
0617
0618
0619
0620
0621
0622
0623
0624
0625
0626
0627
0628
0629
0630
0631
0632
0633
0634
0635
0636
0637
0638
0639
0640
0641
0642
0643
0644
0645
0646
0647
0648
0649
0650
0651
0652
0653
0654
0655
0656
0657
0658 template <unsigned int ND, atomicity Atomicity, typename Arithmetic, const char* Type,
0659 template <atomicity, typename, typename, typename> typename Accumulator, typename AxisTupleType>
0660 class HistogramingCounterBase;
0661 template <unsigned int ND, atomicity Atomicity, typename Arithmetic, const char* Type,
0662 template <atomicity, typename, typename, typename> typename Accumulator, typename... AxisTypes>
0663 class HistogramingCounterBase<ND, Atomicity, Arithmetic, Type, Accumulator, std::tuple<AxisTypes...>>
0664 : public BufferableCounter<Atomicity, Accumulator, Arithmetic, std::integral_constant<unsigned int, ND>,
0665 std::tuple<AxisTypes...>> {
0666 public:
0667 using AxisTupleType = std::tuple<AxisTypes...>;
0668 using NumberDimensions = std::integral_constant<unsigned int, ND>;
0669 using Parent = BufferableCounter<Atomicity, Accumulator, Arithmetic, NumberDimensions, AxisTupleType>;
0670 using AccumulatorType = Accumulator<Atomicity, Arithmetic, NumberDimensions, AxisTupleType>;
0671 using AxisTupleArithmeticType = typename AccumulatorType::AxisTupleArithmeticType;
0672
0673 using AxisArithmeticType = typename std::tuple_element<0, AxisTupleType>::type::ArithmeticType;
0674 inline static const std::string typeString{ std::string{ Type } + ':' + typeid( Arithmetic ).name() };
0675
0676 template <typename OWNER>
0677 HistogramingCounterBase( OWNER* owner, std::string const& name, std::string const& title, AxisTupleType axis )
0678 : Parent( owner, name, *this, axis ), m_title( title ) {
0679 details::requireValidTitle( m_title );
0680 }
0681
0682 template <typename OWNER>
0683 HistogramingCounterBase( OWNER* owner, std::string const& name, std::string const& title, AxisTypes... allAxis )
0684 : HistogramingCounterBase( owner, name, title, std::make_tuple( allAxis... ) ) {}
0685 using Parent::print;
0686 template <typename stream>
0687 stream& printImpl( stream& o, bool ) const {
0688 o << ND << "D Histogram with config ";
0689 std::apply( [&o]( auto&&... args ) { ( ( o << args << "\n" ), ... ); }, this->axis() );
0690 return o;
0691 }
0692 std::ostream& print( std::ostream& o, bool tableFormat = false ) const override {
0693 return printImpl( o, tableFormat );
0694 }
0695 MsgStream& print( MsgStream& o, bool tableFormat = false ) const override { return printImpl( o, tableFormat ); }
0696 friend void reset( HistogramingCounterBase& c ) { c.reset(); }
0697 friend void mergeAndReset( HistogramingCounterBase& h, HistogramingCounterBase& o ) { h.mergeAndReset( o ); }
0698 friend void to_json( nlohmann::json& j, HistogramingCounterBase const& h ) { h.to_json( j ); }
0699 virtual void to_json( nlohmann::json& j ) const {
0700
0701 std::vector<typename AccumulatorType::BaseAccumulator::OutputType> bins;
0702 bins.reserve( this->totNBins() );
0703 unsigned long totNEntries{ 0 };
0704 for ( unsigned int i = 0; i < this->totNBins(); i++ ) {
0705 bins.push_back( this->binValue( i ) );
0706 totNEntries += this->nEntries( i );
0707 }
0708
0709 j = { { "type", std::string( Type ) + ":" + typeid( Arithmetic ).name() },
0710 { "title", m_title },
0711 { "dimension", ND },
0712 { "empty", totNEntries == 0 },
0713 { "nEntries", totNEntries },
0714 { "axis", this->axis() },
0715 { "bins", bins } };
0716 }
0717 std::string const& title() const { return m_title; }
0718
0719 protected:
0720 std::string const m_title;
0721 };
0722
0723 namespace naming {
0724 inline constexpr char histogramString[] = "histogram:Histogram";
0725 inline constexpr char weightedHistogramString[] = "histogram:WeightedHistogram";
0726 inline constexpr char profilehistogramString[] = "histogram:ProfileHistogram";
0727 inline constexpr char weightedProfilehistogramString[] = "histogram:WeightedProfileHistogram";
0728 }
0729
0730
0731 template <unsigned int ND, atomicity Atomicity = atomicity::full, typename Arithmetic = double,
0732 typename AxisTupleType = make_tuple_t<Axis<Arithmetic>, ND>>
0733 using StaticHistogram = HistogramingCounterBase<ND, Atomicity, Arithmetic, naming::histogramString,
0734 HistogramingAccumulator, AxisTupleType>;
0735
0736
0737 template <unsigned int ND, atomicity Atomicity = atomicity::full, typename Arithmetic = double,
0738 typename AxisTupleType = make_tuple_t<Axis<Arithmetic>, ND>>
0739 using StaticWeightedHistogram = HistogramingCounterBase<ND, Atomicity, Arithmetic, naming::weightedHistogramString,
0740 WeightedHistogramingAccumulator, AxisTupleType>;
0741
0742
0743 template <unsigned int ND, atomicity Atomicity = atomicity::full, typename Arithmetic = double,
0744 typename AxisTupleType = make_tuple_t<Axis<Arithmetic>, ND>>
0745 using StaticProfileHistogram = HistogramingCounterBase<ND, Atomicity, Arithmetic, naming::profilehistogramString,
0746 ProfileHistogramingAccumulator, AxisTupleType>;
0747
0748
0749 template <unsigned int ND, atomicity Atomicity = atomicity::full, typename Arithmetic = double,
0750 typename AxisTupleType = make_tuple_t<Axis<Arithmetic>, ND>>
0751 using StaticWeightedProfileHistogram =
0752 HistogramingCounterBase<ND, Atomicity, Arithmetic, naming::weightedProfilehistogramString,
0753 WeightedProfileHistogramingAccumulator, AxisTupleType>;
0754
0755 }