20 #include <fmt/format.h>
21 #include <nlohmann/json.hpp>
23 #include <type_traits>
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>
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>
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 fmt::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>
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>
352 unsigned int computeIndex( std::tuple<AxisType...>
const& axis )
const {
353 return computeIndexInternal<0, std::tuple<AxisType...>>( axis );
355 template <
class... AxisType>
356 requires(
sizeof...( AxisType ) == NIndex )
357 static unsigned int computeTotNBins( std::tuple<AxisType...>
const& axis ) {
358 return computeTotNBinsInternal<0, std::tuple<AxisType...>>( axis );
361 template <
class... AxisType>
363 bool inAcceptance( std::tuple<AxisType...>
const& axis )
const {
364 return inAcceptanceInternal<0, std::tuple<AxisType...>>( axis );
368 template <
int N,
class Tuple>
369 unsigned int computeIndexInternal( Tuple
const& allAxis )
const {
371 auto const& axis = std::get<N>( allAxis );
372 unsigned int localIndex = axis.index( std::get<N>( *
this ) );
373 if constexpr (
N + 1 == NIndex )
376 return localIndex + ( axis.numBins() + 2 ) * computeIndexInternal<N + 1, Tuple>( allAxis );
378 template <
int N,
class Tuple>
379 static unsigned int computeTotNBinsInternal( Tuple
const& allAxis ) {
380 auto const& axis = std::get<N>( allAxis );
381 unsigned int localNBins = axis.numBins() + 2;
382 if constexpr (
N + 1 == NIndex )
385 return localNBins * computeTotNBinsInternal<N + 1, Tuple>( allAxis );
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 )
394 return localAnswer || inAcceptanceInternal<N + 1, Tuple>( allAxis );
403 template <
typename ArithmeticTuple,
unsigned int NIndex,
typename WArithmetic>
406 using std::pair<HistoInputType<ArithmeticTuple, NIndex>, WArithmetic>::pair;
407 template <
class... AxisType>
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 )
414 static unsigned int computeTotNBins( std::tuple<AxisType...>
const& axis ) {
417 auto forInternalCounter()
const {
return std::pair( this->first.forInternalCounter(), this->second ); }
418 template <
class... AxisType>
419 requires(
sizeof...( AxisType ) == NIndex )
420 bool inAcceptance( std::tuple<AxisType...>
const& axis )
const {
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>
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,
540 throw std::logic_error(
541 fmt::format(
"Retrieving axis {} in Histogram of dimension {}", i, std::tuple_size_v<AxisTupleType> ) );
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>
678 :
Parent( owner,
name, *this, axis ), m_title( title ) {
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 {
693 return printImpl( o, tableFormat );
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() },
710 {
"title", m_title },
712 {
"empty", totNEntries == 0 },
713 {
"nEntries", totNEntries },
714 {
"axis", this->axis() },
717 std::string
const&
title()
const {
return m_title; }
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>>