|
YODA - Yet more Objects for Data Analysis 2.0.2
|
Go to the documentation of this file.
25 template < size_t ... Is>
26 constexpr bool has_match( const size_t i, std::integer_sequence<size_t, Is...>) {
27 return ((i == Is) || ...);
31 template< typename INT>
32 constexpr std::integer_sequence<INT>
33 concat_sequences(std::integer_sequence<INT>){
38 template< typename INT, INT... s, INT... t>
39 constexpr std::integer_sequence<INT,s...,t...>
40 concat_sequences(std::integer_sequence<INT, s...>, std::integer_sequence<INT, t...>){
45 template< typename INT, INT... s, INT... t, class... R>
47 concat_sequences(std::integer_sequence<INT, s...>, std::integer_sequence<INT, t...>, R...) {
48 return concat_sequences(std::integer_sequence<INT,s...,t...>{}, R{}...);
53 template< class INT, INT a, class CHECK>
54 constexpr auto AxisFilterSingle(std::integer_sequence<INT, a>, CHECK pass) {
55 if constexpr (pass(a))
56 return std::integer_sequence<INT, a>{};
58 return std::integer_sequence<INT>{};
64 template< class INT, INT... b, class CHECK>
65 constexpr auto AxisFilter(std::integer_sequence<INT, b...>, [[maybe_unused]] CHECK pass) {
66 if constexpr ( sizeof...(b) > 0)
67 return concat_sequences(AxisFilterSingle(std::integer_sequence<INT, b>{}, pass)...);
69 return std::integer_sequence<INT>{};
90 using FillDim = std::integral_constant<size_t, N>;
91 using DataSize = std::integral_constant<size_t, 1 + 2*(N+1) + (N*(N-1)/2)>;
104 template< size_t dim = N, typename = std::enable_if_t<(dim < 2)>>
105 DbnBase(const double numEntries, const std::array< double,N+1>& sumW, const std::array< double,N+1>& sumW2)
106 : _numEntries(numEntries), _sumW(sumW), _sumW2(sumW2) { }
112 template< size_t dim = N, typename = std::enable_if_t<(dim >= 2)>>
114 const std::array< double,N*(N-1)/2>& sumWcross)
152 void fill( const std::array<double, N> vals, const double weight = 1.0, const double fraction = 1.0) {
153 fill(vals, weight, fraction, std::make_index_sequence<N>{});
161 template < typename... Args>
164 static_assert( sizeof...(args) <= N + 2,
165 "Value's dimension doesn't match distribution's dimension.");
166 std::array<double, sizeof...(args)> vals = {{args...}};
168 double fraction = 1.0;
169 if (vals.size() > N) {
171 if (vals.size() > N + 1) fraction = vals[N + 1];
173 const double sf = fraction * weight;
174 _numEntries += fraction;
176 _sumW2.at(0) += fraction* sqr(weight);
177 for ( unsigned int i = 0; i < N; ++i) {
178 _sumW.at(i + 1) += sf * vals.at(i);
179 _sumW2.at(i + 1) += sf * sqr(vals.at(i));
182 if constexpr(N >= 2) {
184 for ( size_t i = 0; i < (N-1); ++i) {
185 for ( size_t j = i+1; j < N; ++j) {
186 _sumWcross.at(idx++) += sf * vals.at(i) * vals.at(j);
198 const std::array<double,N+1>& sumW2,
199 const std::array< double,N*(N-1)/2>& sumWcross) {
203 _sumWcross = sumWcross;
210 const std::vector<double>& sumW2,
211 const std::vector<double>& sumWcross = {}) {
212 if (!( sumW.size() <= (N + 1) || sumW2.size() <= (N + 1) || sumWcross.size() <= (N*(N-1)/2)))
213 throw UserError( "Value's dimension doesn't match distribution's dimension.");
215 std::copy_n(std::make_move_iterator( sumW.begin()), sumW.size(), _sumW.begin());
216 std::copy_n(std::make_move_iterator( sumW2.begin()), sumW2.size(), _sumW2.begin());
217 std::copy_n(std::make_move_iterator(sumWcross.begin()), sumWcross.size(), _sumWcross.begin());
223 if ( this != &other) * this = other;
228 if ( this != &other) * this = std::move(other);
242 _sumW.at(0) *= scalefactor;
243 _sumW2.at(0) *= sqr(scalefactor);
244 for ( size_t i = 0; i< N; ++i) {
246 _sumW.at(i+1) *= scalefactor;
247 _sumW2.at(i+1) *= scalefactor;
249 for ( size_t i = 0; i < _sumWcross.size(); ++i) {
250 _sumWcross.at(i) *= scalefactor;
254 void scale( const size_t dim, const double factor) {
256 throw RangeError( "Dimension index should be less than "+std::to_string(N));
257 _sumW.at( dim+1) *= factor;
258 _sumW2.at( dim+1) *= sqr(factor);
260 for ( size_t i = 0; i < (N-1); ++i) {
261 for ( size_t j = i+1; j < N; ++j) {
262 if (i == dim || j == dim) {
263 _sumWcross.at(idx++) *= factor;
285 double mean( const size_t i) const;
300 double RMS( const size_t i) const;
315 if (_sumW2.at(0) == 0) return 0;
316 return _sumW.at(0)*_sumW.at(0) / _sumW2.at(0);
330 double sumW( const size_t i) const {
335 double sumW2( const size_t i) const {
340 template< size_t dim = N, typename = std::enable_if_t<(dim >= 2)>>
341 double crossTerm( const size_t A1, const size_t A2) const {
342 if (A1 >= N || A2 >= N) throw RangeError( "Invalid axis int, must be in range 0..dim-1");
343 if (A1 >= A2) throw RangeError( "Indices need to be different for cross term");
346 for ( size_t i = 0; i < (N-1); ++i) {
347 for ( size_t j = i+1; j < N; ++j) {
348 if (i == A1 && j == A2) break;
354 return _sumWcross.at(idx);
357 size_t dim() const { return N; }
367 res += ( "numEntries="+ std::to_string(_numEntries)) ;
369 res += ( ", Mean="+ std::to_string( mean(0))) ;
370 res += ( ", RMS="+ std::to_string( RMS(0))) ;
382 template< typename... size_t>
384 if constexpr (N == sizeof...(axes)) { return * this; }
387 std::array<double, sizeof...(axes)+1> newSumW = { _sumW[0], _sumW[axes+1]... };
388 std::array<double, sizeof...(axes)+1> newSumW2 = { _sumW2[0], _sumW2[axes+1]... };
389 if constexpr ( sizeof...(axes) < 2) {
390 return DbnBase< sizeof...(axes)>(_numEntries, newSumW, newSumW2);
393 constexpr auto newDim = sizeof...(axes);
394 std::array<double, newDim*(newDim-1)/2> newSumWcross;
395 unsigned int idx = 0;
396 for ( unsigned int i : {axes...}) {
397 for ( unsigned int j : {axes...}) {
398 if (i < j) { newSumWcross.at(idx) = crossTerm(i, j); ++idx; }
401 return DbnBase< sizeof...(axes)>(_numEntries, newSumW, newSumW2, newSumWcross);
407 template< size_t... Is>
414 template< size_t... axes>
416 constexpr auto new_axes = AxisFilter(std::make_index_sequence<N>{},
417 []( size_t i) { return !has_match(i, std::integer_sequence<size_t, axes...>{}); }
427 size_t _lengthContent() const noexcept {
428 return DataSize::value;
431 std::vector<double> _serializeContent() const noexcept {
432 std::vector<double> rtn;
433 rtn.reserve(DataSize::value);
434 rtn.insert(rtn.end(), _sumW.begin(), _sumW.end());
435 rtn.insert(rtn.end(), _sumW2.begin(), _sumW2.end());
436 rtn.insert(rtn.end(), _sumWcross.begin(), _sumWcross.end());
437 rtn.push_back(_numEntries);
441 void _deserializeContent( const std::vector<double>& data) {
443 if (data.size() != DataSize::value)
444 throw UserError( "Length of serialized data should be "+std::to_string(DataSize::value)+ "!");
446 auto itr = data.cbegin();
447 std::copy_n(itr, _sumW.size(), _sumW.begin());
448 std::copy_n(itr+N+1, _sumW2.size(), _sumW2.begin());
449 std::copy_n(itr+2*(N+1), _sumWcross.size(), _sumWcross.begin());
450 _numEntries = *(itr + 2*(N+1) + (N*(N-1)/2));
481 std::array<double, N+1> _sumW;
484 std::array<double, N+1> _sumW2;
487 std::array<double, N*(N-1)/2> _sumWcross;
495 template < size_t... I>
496 void fill( const std::array<double, N> vals, const double weight, const double fraction,
497 std::index_sequence<I...>) {
498 fill(vals[I]..., weight, fraction);
507 return sqrt(sumW2(0));
513 return std::numeric_limits<double>::quiet_NaN();
515 return errW()/sumW(0);
532 return YODA::stdErr(sumW(i), sumW(0), sumW2(i), sumW2(0));
539 return std::numeric_limits<double>::quiet_NaN();
547 return YODA::RMS(sumW2(i), sumW(0), sumW2());
552 _numEntries += d._numEntries;
553 for ( size_t i = 0; i <= N; ++i) {
554 _sumW.at(i) += d._sumW.at(i);
555 _sumW2.at(i) += d._sumW2.at(i);
557 for ( size_t i = 0; i < _sumWcross.size(); ++i) {
558 _sumWcross.at(i) += d._sumWcross.at(i);
566 _numEntries += std::move(d._numEntries);
567 for ( size_t i = 0; i <= N; ++i) {
568 _sumW.at(i) += std::move(d._sumW.at(i));
569 _sumW2.at(i) += std::move(d._sumW2.at(i));
571 for ( size_t i = 0; i < _sumWcross.size(); ++i) {
572 _sumWcross.at(i) += std::move(d._sumWcross.at(i));
580 _numEntries -= d._numEntries;
581 for ( unsigned int i =0; i<= N ; ++i) {
582 _sumW.at(i) -= d._sumW.at(i);
583 _sumW2.at(i) += d._sumW2.at(i);
585 for ( size_t i = 0; i < _sumWcross.size(); ++i) {
586 _sumWcross.at(i) -= d._sumWcross.at(i);
594 _numEntries -= std::move(d._numEntries);
595 for ( unsigned int i =0; i<= N ; ++i) {
596 _sumW.at(i) -= std::move(d._sumW.at(i));
597 _sumW2.at(i) += std::move(d._sumW2.at(i));
599 for ( size_t i = 0; i < _sumWcross.size(); ++i) {
600 _sumWcross.at(i) -= std::move(d._sumWcross.at(i));
616 first += std::move(second);
630 first -= std::move(second);
641 using BaseT::operator=;
652 using BaseT::operator=;
663 void fill( const std::array<double, 0>& vals, const double weight = 1.0, const double fraction = 1.0) {
667 void fill( const double weight=1.0, const double fraction=1.0) { BaseT::fill({}, weight, fraction); }
684 using BaseT::operator=;
695 void fill( const std::array<double, 1>& vals, const double weight = 1.0, const double fraction = 1.0) {
699 void fill( const double val, const double weight=1.0, const double fraction=1.0) {
715 using BaseT::operator=;
720 const double sumWY, const double sumWY2, const double sumWXY)
727 void fill( const std::array<double, 2>& vals, const double weight = 1.0, const double fraction = 1.0) {
731 void fill( const double valX, const double valY, const double weight=1.0, const double fraction=1.0) {
749 using BaseT::operator=;
754 const double sumWX, const double sumWX2,
755 const double sumWY, const double sumWY2,
756 const double sumWZ, const double sumWZ2,
757 const double sumWXY, const double sumWXZ, const double sumWYZ)
758 : BaseT( numEntries, { sumW, sumWX, sumWY, sumWZ} , { sumW2, sumWX2, sumWY2, sumWZ2}, {sumWXY, sumWXZ, sumWYZ}) { }
764 void fill( const std::array<double, 3>& vals, const double weight = 1.0, const double fraction = 1.0) {
768 void fill( const double valX, const double valY, const double valZ, const double weight=1.0, const double fraction=1.0) {
DbnBase(DbnBase &&)=default
DbnBase & operator+=(const DbnBase &d) Add two DbnBases.
double RMS(const size_t i) const Weighted RMS, , of distribution.
DbnBase & operator=(const DbnBase &)=default
DbnBase< sizeof...(size_t)> reduceTo(size_t... axes) const Reduce operation that produces a lower-dimensional DbnBase keeping only the specified axes in the new...
DbnBase & operator-=(const DbnBase &d) Subtract one DbnBase from another.
DbnBase() Default constructor of a new distribution.
void set(DbnBase< N > &&other) Set a sample with other.
DbnBase(const DbnBase &)=default
void reset() Reset the internal counters.
void set(const double numEntries, const std::vector< double > &sumW, const std::vector< double > &sumW2, const std::vector< double > &sumWcross={}) Set a sample with vector-based number of entries numEntries, sum of weights sumW (and corresponding m...
void set(const double numEntries, const std::array< double, N+1 > &sumW, const std::array< double, N+1 > &sumW2, const std::array< double, N *(N-1)/2 > &sumWcross) Set a sample with array-based number of entries numEntries, sum of weights sumW (and corresponding mo...
double stdDev(const size_t i) const Weighted standard deviation, , of distribution.
auto reduce() const Reduce operation that produces a lower-dimensional DbnBase removing the specified axes for the new Db...
std::string toString() const String representation of the DbnBase for debugging.
std::integral_constant< size_t, 1+2 *(N+1)+(N *(N-1)/2)> DataSize
void fill(const std::array< double, N > vals, const double weight=1.0, const double fraction=1.0) Contribute a sample at val (from an array) with weight weight.
double errW() const The absolute error on sumW.
double mean(const size_t i) const Weighted mean, , of distribution.
DbnBase< sizeof...(Is)> reduceTo(std::index_sequence< Is... >) const Same as above but using an std::integer_sequence.
double relErrW() const The relative error on sumW.
DbnBase(const double numEntries, const std::array< double, N+1 > &sumW, const std::array< double, N+1 > &sumW2, const std::array< double, N *(N-1)/2 > &sumWcross) Constructor to set a distribution with a pre-filled state.
double effNumEntries() const Effective number of entries .
void set(const DbnBase< N > &other) Set a sample with other.
void fill(Args &&... args) Templated convenience overload of fill method.
double variance(const size_t i) const Weighted variance, , of distribution.
double sumW(const size_t i) const The sum of x*weight.
double sumW() const The sum of weights.
void scaleW(const double scalefactor) Rescale as if all fill weights had been different by factor scalefactor.
void scale(const size_t dim, const double factor)
double sumW2(const size_t i) const The sum of x^2*weight.
double stdErr(const size_t i) const Weighted standard error on the mean, , of distribution.
std::integral_constant< size_t, N > FillDim
double numEntries() const Number of entries (number of times fill was called, ignoring weights)
double crossTerm(const size_t A1, const size_t A2) const The second-order cross term between axes k and l.
double sumW2() const The sum of weights squared.
double relStdErr(const size_t i) const Relative weighted standard error on the mean, , of distribution.
Partial template specialisation for Dbn0D.
void set(const double numEntries, const double sumW, const double sumW2)
void fill(const double weight=1.0, const double fraction=1.0)
void fill(const std::array< double, 0 > &vals, const double weight=1.0, const double fraction=1.0)
Dbn(const double numEntries, const double sumW, const double sumW2)
Partial template specialisation with CRTP for x-methods.
void fill(const double val, const double weight=1.0, const double fraction=1.0)
void fill(const std::array< double, 1 > &vals, const double weight=1.0, const double fraction=1.0)
Dbn(const double numEntries, const double sumW, const double sumW2, const double sumWX, const double sumWX2)
Partial template specialisation with CRTP for x- and y-methods.
void fill(const std::array< double, 2 > &vals, const double weight=1.0, const double fraction=1.0)
void fill(const double valX, const double valY, const double weight=1.0, const double fraction=1.0)
Dbn(const double numEntries, const double sumW, const double sumW2, const double sumWX, const double sumWX2, const double sumWY, const double sumWY2, const double sumWXY)
Partial template specialisation with CRTP for x-, y- and z-methods.
void fill(const std::array< double, 3 > &vals, const double weight=1.0, const double fraction=1.0)
Dbn(const double numEntries, const double sumW, const double sumW2, const double sumWX, const double sumWX2, const double sumWY, const double sumWY2, const double sumWZ, const double sumWZ2, const double sumWXY, const double sumWXZ, const double sumWYZ)
void fill(const double valX, const double valY, const double valZ, const double weight=1.0, const double fraction=1.0)
User-facing Dbn class inheriting from DbnBase.
Error for e.g. use of invalid bin ranges.
Error for problems introduced outside YODA, to put it nicely.
Anonymous namespace to limit visibility.
double stdErr(const double sumWX, const double sumW, const double sumWX2, const double sumW2) Calculate the weighted standard error of a sample.
double RMS(const double sumWX2, const double sumW, const double sumW2) Calculate the weighted RMS of a sample.
BinnedDbn< DbnN, AxisT... > operator+(BinnedDbn< DbnN, AxisT... > first, BinnedDbn< DbnN, AxisT... > &&second) Add two BinnedDbn objects.
NUM sqr(NUM a) Named number-type squaring operation.
BinnedDbn< DbnN, AxisT... > operator-(BinnedDbn< DbnN, AxisT... > first, BinnedDbn< DbnN, AxisT... > &&second) Subtract one BinnedDbn object from another.
double variance(const double sumWX, const double sumW, const double sumWX2, const double sumW2) Calculate the weighted variance of a sample.
double mean(const std::vector< int > &sample) Calculate the mean of a sample.
double effNumEntries(const double sumW, const double sumW2) Calculate the effective number of entries of a sample.
CRTP mixin introducing convenience aliases along X axis.
CRTP mixin introducing convenience aliases along Y axis.
CRTP mixin introducing convenience aliases along Z axis.
|