yoda is hosted by Hepforge, IPPP Durham
YODA - Yet more Objects for Data Analysis 2.0.0
BinnedEstimate.h
Go to the documentation of this file.
1// -*- C++ -*-
2//
3// This file is part of YODA -- Yet more Objects for Data Analysis
4// Copyright (C) 2008-2023 The YODA collaboration (see AUTHORS for details)
5//
6#ifndef YODA_BinnedEstimate_h
7#define YODA_BinnedEstimate_h
8
10#include "YODA/BinnedStorage.h"
11#include "YODA/Estimate.h"
12#include "YODA/Scatter.h"
13#include "YODA/Transformation.h"
15
16namespace YODA {
17
19 namespace {
21 template<size_t axisN, typename BinT>
22 std::pair<double, double> nullifyIfDisc(const BinT& /* b */, const double /* val */, std::false_type, const double null = 0.0) {
23 return { null, null };
24 }
25
28 template<size_t axisN, typename BinT>
29 std::pair<double, double> nullifyIfDisc(const BinT& b, const double val, std::true_type, const double /* null */ = 0.0) {
30 return { val - b.template min<axisN>(), b.template max<axisN>() - val };
31 }
32
34 template<size_t axisN, typename BinT>
35 double unifyIfDisc(const BinT& /* b */, std::false_type, const double unity = 1.0) {
36 return unity;
37 }
38
40 template<size_t axisN, typename BinT>
41 double unifyIfDisc(const BinT& b, std::true_type, const double /* unity */ = 1.0) {
42 return b.template width<axisN>();
43 }
44
46 template<size_t axisN, typename BinT>
47 double coordPicker(const BinT& b, std::false_type, std::false_type) {
48 return b.index();
49 }
50
52 template<size_t axisN, typename BinT>
53 double coordPicker(const BinT& b, std::true_type, std::false_type) {
54 return b.template edge<axisN>();
55 }
57 template<size_t axisN, typename BinT>
58 double coordPicker(const BinT& b, std::true_type, std::true_type) {
59 return b.template mid<axisN>();
60 }
61 }
62
63
65 template <typename... AxisT>
66 class BinnedEstimate;
67
73 template<typename... AxisT>
75 : public BinnedStorage<Estimate, AxisT...>,
76 public AnalysisObject {
77 protected:
78
79 using BaseT = BinnedStorage<Estimate, AxisT...>;
80 using BinningT = typename BaseT::BinningT;
81 using BinT = typename BaseT::BinT;
82
83 public:
84
85 using BinType = BinT;
86 using AnalysisObject::operator =;
87
90
92 EstimateStorage(const std::string& path = "", const std::string& title = "")
93 : BaseT(), AnalysisObject(mkTypeString<AxisT...>(), path, title) { }
94
100 EstimateStorage(std::vector<AxisT>&&... binsEdges, const std::string& path = "", const std::string& title = "")
101 : BaseT(Axis<AxisT>(std::move(binsEdges))...), AnalysisObject(mkTypeString<AxisT...>(), path, title) { }
102
108 EstimateStorage(const std::vector<AxisT>&... binsEdges, const std::string& path = "", const std::string& title = "")
109 : BaseT(Axis<AxisT>(binsEdges)...), AnalysisObject(mkTypeString<AxisT...>(), path, title) { }
110
116 EstimateStorage(std::initializer_list<AxisT>&&... binsEdges, const std::string& path = "", const std::string& title = "")
117 : BaseT(Axis<AxisT>(std::move(binsEdges))...), AnalysisObject(mkTypeString<AxisT...>(), path, title) { }
118
120 template <typename EdgeT = double, typename = enable_if_all_CAxisT<EdgeT, AxisT...>>
121 EstimateStorage(const std::vector<size_t>& nBins,
122 const std::vector<std::pair<EdgeT, EdgeT>>& limitsLowUp,
123 const std::string& path = "", const std::string& title = "")
124 //: BaseT( BinningT(nBins, limitsLowUp, std::make_index_sequence<sizeof...(AxisT)>{}) ),
125 : BaseT( _mkBinning(nBins, limitsLowUp, std::make_index_sequence<sizeof...(AxisT)>{}) ),
126 AnalysisObject(mkTypeString<AxisT...>(), path, title) { }
127
129 EstimateStorage(const BinningT& binning, const std::string& path = "", const std::string& title = "")
130 : BaseT(binning), AnalysisObject(mkTypeString<AxisT...>(), path, title) { }
131
133 EstimateStorage(BinningT&& binning, const std::string& path = "", const std::string& title = "")
134 : BaseT(std::move(binning)), AnalysisObject(mkTypeString<AxisT...>(), path, title) { }
135
137 template <typename EdgeT = double, typename = enable_if_all_CAxisT<EdgeT, AxisT...>>
138 EstimateStorage(const ScatterND<sizeof...(AxisT)+1>& s, const std::string& path = "", const std::string& title = "")
139 : BaseT(_mkBinning(s, std::make_index_sequence<sizeof...(AxisT)>{})),
140 AnalysisObject(mkTypeString<AxisT...>(), path, title) { }
141
145 EstimateStorage(const EstimateStorage& other, const std::string& path = "") : BaseT(other),
146 AnalysisObject(mkTypeString<AxisT...>(), path!=""? path : other.path(), other, other.title()) { }
147
151 EstimateStorage(EstimateStorage&& other, const std::string& path = "") : BaseT(std::move(other)),
152 AnalysisObject(mkTypeString<AxisT...>(), path!=""? path : other.path(), other, other.title()) { }
153
155 EstimateStorage clone() const noexcept {
156 return EstimateStorage(*this);
157 }
158
160 EstimateStorage* newclone() const noexcept {
161 return new EstimateStorage(*this);
162 }
163
165
166
169
170 private:
171
172 // @brief Render information about this AO (private implementation)
173 template<size_t... Is>
174 void _renderYODA_aux(std::ostream& os, const int width, std::index_sequence<Is...>) const noexcept {
175
176 // print bin edges
177 BaseT::_binning._renderYODA(os);
178
179 // Assemble union of error sources, as it's not guaranteed
180 // that every bin has the same error breakdown
181 const std::vector<std::string> labels = this->sources();
182 if (labels.size()) {
183 os << "ErrorLabels: [";
184 for (size_t i = 0; i < labels.size(); ++i) {
185 const std::string& src = labels[i];
186 if (i) os << ", ";
187 os << std::quoted(src);
188 }
189 os << "]\n";
190 }
191
192 // column header: content types
193 os << std::setw(width) << std::left << "# value" << "\t";
194 const int errwidth = std::max(int(std::to_string(labels.size()).size()+7), width); // "errDn(" + src + ")"
195 for (size_t i = 0; i < labels.size(); ++i) {
196 const std::string& src = labels[i];
197 if (src.empty()) {
198 os << std::setw(errwidth) << std::left << "totalDn" << "\t"
199 << std::setw(errwidth) << std::left << "totalUp" << "\t";
200 }
201 else {
202 os << std::setw(errwidth) << std::left << ("errDn(" + std::to_string(i+1) + ")") << "\t"
203 << std::setw(errwidth) << std::left << ("errUp(" + std::to_string(i+1) + ")") << "\t";
204 }
205 }
206 os << "\n";
207
208 for (const auto& b : BaseT::bins(true, true)) {
209 os << std::setw(width) << std::left << b.val() << "\t"; // print value
210 // print systs if available
211 for (const std::string& src : labels) {
212 if (!b.hasSource(src)) {
213 os << std::setw(errwidth) << std::left << "---" << "\t"
214 << std::setw(errwidth) << std::left << "---" << "\t";
215 continue;
216 }
217 const auto& err = b.err(src);
218 os << std::setw(errwidth) << std::left << err.first << "\t"
219 << std::setw(errwidth) << std::left << err.second << "\t";
220 }
221 os << "\n";
222 }
223 }
224
225 public:
226
229
230 // @brief Render information about this AO
231 void _renderYODA(std::ostream& os, const int width = 13) const noexcept {
232 _renderYODA_aux(os, width, std::make_index_sequence<sizeof...(AxisT)>{});
233 }
234
235 // @brief Render scatter-like information about this AO
236 void _renderFLAT(std::ostream& os, const int width = 13) const noexcept {
237 const ScatterND<sizeof...(AxisT)+1> tmp = mkScatter();
238 tmp._renderYODA(os, width);
239 }
240
242
243
246
248 void scale(const double scalefactor) noexcept {
249 setAnnotation("ScaledBy", annotation<double>("ScaledBy", 1.0) * scalefactor);
250 for (auto& bin : BaseT::_bins) {
251 bin.scale(scalefactor);
252 }
253 }
254
255
264 template <size_t axisN>
265 void rebinBy(unsigned int n, size_t begin=1, size_t end=UINT_MAX) {
266 if (n < 1) throw UserError("Rebinning requested in groups of 0!");
267 if (!begin) throw UserError("Visible bins start with index 1!");
268 if (end > BaseT::numBinsAt(axisN)+1) end = BaseT::numBinsAt(axisN) + 1;
269 for (size_t m = begin; m < end; ++m) {
270 if (m > BaseT::numBinsAt(axisN)+1) break; // nothing to be done
271 const size_t myend = (m+n-1 < BaseT::numBinsAt(axisN)+1) ? m+n-1 : BaseT::numBinsAt(axisN);
272 if (myend > m) {
273 BaseT::template mergeBins<axisN>({m, myend});
274 end -= myend-m; //< reduce upper index by the number of removed bins
275 }
276 }
277 }
278
280 template <size_t axisN>
281 void rebin(unsigned int n, size_t begin=1, size_t end=UINT_MAX) {
282 rebinBy<axisN>(n, begin, end);
283 }
284
286 template <size_t axisN>
287 void rebinTo(const std::vector<typename BinningT::template getAxisT<axisN>::EdgeT>& newedges) {
288 if (newedges.size() < 2)
289 throw UserError("Requested rebinning to an edge list which defines no bins");
290 using thisAxisT = typename BinningT::template getAxisT<axisN>;
291 using thisEdgeT = typename thisAxisT::EdgeT;
292 // get list of shared edges
293 thisAxisT& oldAxis = BaseT::_binning.template axis<axisN>();
294 const thisAxisT newAxis(std::move(newedges));
295 const std::vector<thisEdgeT> eshared = oldAxis.sharedEdges(newAxis);
296 if (eshared.size() != newAxis.edges().size())
297 throw BinningError("Requested rebinning to incompatible edges");
298 // loop over new lower bin edges (= first bin index of merge range)
299 for (size_t begin = 0; begin < eshared.size() - 1; ++begin) {
300 // find index of upper edge along old axis
301 // (subtracting 1 gives index of last bin to be merged)
302 size_t end = oldAxis.index(eshared[begin+1]) - 1;
303 // if the current edge is the last visible edge before the overflow
304 // merge the remaining bins into the overflow
305 if (begin == newAxis.numBins(true)-1) end = oldAxis.numBins(true)-1;
306 // merge this range
307 if (end > begin) BaseT::template mergeBins<axisN>({begin, end});
308 if (eshared.size() == oldAxis.edges().size()) break; // we're done
309 }
310 }
311
313 template <size_t axisN>
314 void rebin(const std::vector<typename BinningT::template getAxisT<axisN>::EdgeT>& newedges) {
315 rebinTo<axisN>(std::move(newedges));
316 }
317
321 void reset() noexcept { BaseT::clearBins(); }
322
325 if (this != &est) {
328 }
329 return *this;
330 }
331
334 if (this != &est) {
336 BaseT::operator = (std::move(est));
337 }
338 return *this;
339 }
340
346 const std::string& pat_uncorr="^stat|^uncor" ) {
347 if (*this != est)
348 throw BinningError("Arithmetic operation requires compatible binning!");
349 if (AO::hasAnnotation("ScaledBy")) AO::rmAnnotation("ScaledBy");
350 for (size_t i = 0; i< BaseT::numBins(true, true); ++i) {
351 BaseT::bin(i).add(est.bin(i), pat_uncorr);
352 }
353 BaseT::maskBins(est.maskedBins(), true);
354 return *this;
355 }
356 //
358 return add(est);
359 }
360
366 const std::string& pat_uncorr="^stat|^uncor" ) {
367 if (*this != est)
368 throw BinningError("Arithmetic operation requires compatible binning!");
369 if (AO::hasAnnotation("ScaledBy")) AO::rmAnnotation("ScaledBy");
370 for (size_t i = 0; i< BaseT::numBins(true, true); ++i) {
371 BaseT::bin(i).add(std::move(est.bin(i)), pat_uncorr);
372 }
373 BaseT::maskBins(est.maskedBins(), true);
374 return *this;
375 }
376 //
378 return add(std::move(est));
379 }
380
381
387 const std::string& pat_uncorr="^stat|^uncor" ) {
388 if (*this != est)
389 throw BinningError("Arithmetic operation requires compatible binning!");
390 if (AO::hasAnnotation("ScaledBy")) AO::rmAnnotation("ScaledBy");
391 for (size_t i = 0; i< BaseT::numBins(true, true); ++i) {
392 BaseT::bin(i).subtract(est.bin(i), pat_uncorr);
393 }
394 BaseT::maskBins(est.maskedBins(), true);
395 return *this;
396 }
397 //
399 return subtract(est);
400 }
401
404 const std::string& pat_uncorr="^stat|^uncor" ) {
405 if (*this != est)
406 throw BinningError("Arithmetic operation requires compatible binning!");
407 if (AO::hasAnnotation("ScaledBy")) AO::rmAnnotation("ScaledBy");
408 for (size_t i = 0; i< BaseT::numBins(true, true); ++i) {
409 BaseT::bin(i) -= std::move(est.bin(i), pat_uncorr);
410 }
411 BaseT::maskBins(est.maskedBins(), true);
412 return *this;
413 }
414 //
416 return subtract(std::move(est));
417 }
418
420
421
424
426 size_t dim() const noexcept { return sizeof...(AxisT) + 1; }
427
429 std::string _config() const noexcept { return mkAxisConfig<AxisT...>(); }
430
435 template <size_t I, typename E = typename BinningT::template getEdgeT<I>>
436 std::vector<E> edges(const bool includeOverflows = false) const noexcept {
437 return BaseT::_binning.template edges<I>(includeOverflows);
438 }
439
446 template <size_t I, typename E = typename BinningT::template getEdgeT<I>>
447 std::enable_if_t<std::is_floating_point<E>::value, std::vector<E>>
448 widths(const bool includeOverflows = false) const noexcept {
449 return BaseT::_binning.template widths<I>(includeOverflows);
450 }
451
455 template <size_t I, typename E = typename BinningT::template getEdgeT<I>>
456 std::enable_if_t<std::is_floating_point<E>::value, E> min() const noexcept {
457 return BaseT::_binning.template min<I>();
458 }
459
463 template <size_t I, typename E = typename BinningT::template getEdgeT<I>>
464 std::enable_if_t<std::is_floating_point<E>::value, E> max() const noexcept {
465 return BaseT::_binning.template max<I>();
466 }
467
469
470
473
475 std::vector<double> vals(const bool includeOverflows=false,
476 const bool includeMaskedBins=false) const {
477 std::vector<double> rtn;
478 rtn.reserve(BaseT::numBins(includeOverflows, includeMaskedBins));
479 for (const auto& b : BaseT::bins(includeOverflows, includeMaskedBins)) {
480 rtn.push_back(b.val());
481 }
482 return rtn;
483 }
484
486 std::vector<std::string> sources() const {
487 // Assemble union of error sources, as it's not guaranteed
488 // that every bin has the same error breakdown
489 std::vector<std::string> rtn;
490
491 for (const auto& b : BaseT::bins(true)) {
492 std::vector<std::string> keys = b.sources();
493 rtn.insert(std::end(rtn),
494 std::make_move_iterator(std::begin(keys)),
495 std::make_move_iterator(std::end(keys)));
496 }
497 std::sort(rtn.begin(), rtn.end());
498 rtn.erase( std::unique(rtn.begin(), rtn.end()), rtn.end() );
499
500 return rtn;
501 }
502
506 double areaUnderCurve(const bool includeBinVol=true,
507 const bool includeOverflows=false,
508 const bool includeMaskedBins=false) const {
509 double ret = 0.;
510 for (const auto& b : BaseT::bins(includeOverflows, includeMaskedBins)) {
511 const double val = fabs(b.val());
512 const double vol = includeBinVol? b.dVol() : 1.0;
513 if (std::isfinite(vol)) ret += val*vol; // aggregate bin volume
514 }
515 return ret;
516 }
517
519 double auc(const bool includeBinVol=true,
520 const bool includeOverflows=false,
521 const bool includeMaskedBins=false) const {
522 return areaUnderCurve(includeBinVol, includeOverflows, includeMaskedBins);
523 }
524
525
526
528 std::vector<std::vector<double> > covarianceMatrix(const bool ignoreOffDiagonalTerms=false,
529 const bool includeOverflows=false,
530 const bool includeMaskedBins=false) const {
531 const size_t nBins = BaseT::numBins(includeOverflows,includeMaskedBins);
532 std::vector<std::vector<double> > covM(nBins);
533
534 // initialise cov matrix to be the right shape
535 for (size_t i = 0; i < nBins; ++i) {
536 covM[i] = std::vector<double>(nBins, 0.0);
537 }
538
539 const std::vector<std::string> error_sources = sources();
540
541 // nominal-only case, i.e. total uncertainty, labelled as empty string
542 if (error_sources.size() == 1 && error_sources[0] == "") {
543 size_t i = 0;
544 for (const auto& b : BaseT::bins(includeOverflows,includeMaskedBins)) {
545 covM[i][i] = b.hasSource("")? sqr(0.5*(b.err("").first+b.err("").second)) : 1.0;
546 ++i;
547 }
548 return covM;
549 }
550
551 // more interesting case where we actually have some uncertainty breakdown!
552 for (const std::string& sname : error_sources) {
553 if (sname == "") continue;
554 std::vector<double> systErrs(nBins, 0.0);
555 size_t i = 0;
556 for (const auto& b : BaseT::bins(includeOverflows,includeMaskedBins)) {
557 if (b.hasSource(sname)) {
558 const auto& errs = b.err(sname); // dn-up pair
559 systErrs[i] = 0.5 *( fabs(errs.first)+fabs(errs.second));
560 }
561 ++i;
562 }
563 const bool skipOffDiag = (ignoreOffDiagonalTerms
564 || sname.find("STAT") != std::string::npos
565 || sname.find("UNCOR") != std::string::npos);
566 for (size_t i = 0; i < nBins; ++i) {
567 for (size_t j = 0; j < nBins; ++j) {
568 if (skipOffDiag && i != j) continue;
569 covM[i][j] += systErrs[i]*systErrs[j];
570 }
571 }
572 }
573
574 return covM;
575 }
576
578
581
583 auto mkScatter(const std::string& path="", const bool includeOverflows=false,
584 const bool includeMaskedBins=false) const {
585
586 constexpr size_t N = sizeof...(AxisT);
587
588 ScatterND<N+1> rtn;
589 for (const std::string& a : annotations()) {
590 if (a != "Type") rtn.setAnnotation(a, annotation(a));
591 }
592 rtn.setAnnotation("Path", path);
593
594 const bool incOF = all_CAxes<AxisT...>::value && includeOverflows;
595 for (const auto& b : BaseT::bins(incOF, includeMaskedBins)) {
596
597 // Create the vector of coordinates
598 Utils::ndarray<double, N+1> vals;
599 // first fill bin centres, use bin index if axis non-arithmetic
600 auto indexIfDiscrete = [&vals, &b](auto I) {
601 using isContinuous = typename BinningT::template is_CAxis<I>;
602 using isArithmetic = typename BinningT::template is_Arithmetic<I>;
603 vals[I] = coordPicker<I>(b, std::integral_constant<bool, isArithmetic::value>{},
604 std::integral_constant<bool, isContinuous::value>{});
605 };
606 MetaUtils::staticFor<BinningT::Dimension::value>(indexIfDiscrete);
607 // then fill bin content
608 vals[N] = b.val();
609
610 // Create the vector of error pairs, use 0 if axis not continuous
611 Utils::ndarray<std::pair<double,double>, N+1> errs;
612 auto nullifyDiscrete = [&errs, &vals, &b](auto I) {
613 using isContinuous = typename BinningT::template is_CAxis<I>;
614 errs[I] = nullifyIfDisc<I>(b, vals[I], std::integral_constant<bool, isContinuous::value>{});
615 };
616 MetaUtils::staticFor<BinningT::Dimension::value>(nullifyDiscrete);
617 const double tot = b.quadSum().second; // use positive error component
618 errs[N] = { tot, tot };
619
620 // Add the PointND
621 rtn.addPoint( PointND<N+1>(vals, errs) );
622 }
623
624 // Decorate output scatter with the discrete edges
625 const BinningT& binning = BaseT::_binning;
626 auto decorateEdges = [&rtn, &binning](auto I) {
627 using isContinuous = typename BinningT::template is_CAxis<I>;
628 if constexpr( !isContinuous::value ) {
629 const auto& axis = binning.template axis<I>();
630 if (axis.numBins()) {
631 std::stringstream ss;
632 axis._renderYODA(ss);
633 rtn.setAnnotation("EdgesA" + std::to_string(I+1), ss.str());
634 }
635 }
636 };
637 MetaUtils::staticFor<BinningT::Dimension::value>(decorateEdges);
638
639 return rtn;
640 }
641
646 template<size_t axisN, typename = std::enable_if_t< (axisN < sizeof...(AxisT) && sizeof...(AxisT)>=2) >>
647 auto mkEstimates(const std::string& path="", const bool includeOverflows=false) const {
648
649 // Need to provide a prescription for how to add the two bin contents
650 auto how2add = [](auto& pivot, const BinType& toCopy) { pivot = toCopy; };
651 auto rtn = BaseT::template mkBinnedSlices<axisN, BinnedEstimate>(how2add, includeOverflows);
652 for (const std::string& a : annotations()) {
653 if (a == "Type") continue;
654 for (size_t i = 0; i < rtn.size(); ++i) {
655 rtn[i].setAnnotation(a, annotation(a));
656 }
657 }
658 for (size_t i = 0; i < rtn.size(); ++i) {
659 rtn[i].setAnnotation("Path", path);
660 }
661
662 return rtn;
663 }
664
665
667 AnalysisObject* mkInert(const std::string& path = "",
668 const std::string& source = "") const noexcept {
669 EstimateStorage* rtn = newclone();
670 rtn->setPath(path);
671 for (auto& b : rtn->bins(true, true)) {
672 if (b.numErrs() == 1) {
673 try {
674 b.renameSource("", source);
675 }
676 catch (YODA::UserError& e) { }
677 }
678 }
679 return rtn;
680 }
681
683
685
686
687 size_t lengthContent(bool fixed_length = false) const noexcept {
688 size_t rtn = 0;
689 for (const auto& bin : BaseT::bins(true, true)) {
690 rtn += bin._lengthContent(fixed_length);
691 }
692 return rtn;
693 }
694
695 std::vector<double> serializeContent(bool fixed_length = false) const noexcept {
696 std::vector<double> rtn;
697 const size_t nBins = BaseT::numBins(true, true);
698 rtn.reserve(nBins * 4);
699 for (size_t i = 0; i < nBins; ++i) {
700 const auto& b = BaseT::bin(i);
701 std::vector<double> bdata = b._serializeContent(fixed_length);
702 rtn.insert(std::end(rtn),
703 std::make_move_iterator(std::begin(bdata)),
704 std::make_move_iterator(std::end(bdata)));
705 }
706 return rtn;
707 }
708
709
710 void deserializeContent(const std::vector<double>& data) {
711
712 const size_t nBins = BaseT::numBins(true, true);
713 const size_t minLen = 2*nBins;
714 if (data.size() < minLen)
715 throw UserError("Length of serialized data should be at least " + std::to_string(minLen)+"!");
716
717 size_t i = 0;
718 auto itr = data.cbegin();
719 const auto itrEnd = data.cend();
720 const bool fixedLen = data.size() == 2*minLen;
721 while (itr != itrEnd) {
722 // for estimates, the first element represents the central,
723 // the subsequent value represents the number of error pairs
724 const size_t nErrs = fixedLen? 1 : (*(itr + 1) + 0.5); // add 0.5 to avoid rounding issues
725 auto last = itr + 2*(nErrs+1); // last element + 1
726 BaseT::bin(i)._deserializeContent(std::vector<double>{itr, last}, fixedLen);
727 // update for next iteration
728 itr = last;
729 ++i;
730 }
731 }
732
733 // @}
734
735 private:
736
739 template<size_t... Is>
740 BinningT _mkBinning(const std::vector<size_t>& nBins,
741 const std::vector<std::pair<double, double>>& limitsLowUp,
742 std::index_sequence<Is...>) const {
743 return BinningT({((void)Is, Axis<AxisT>(nBins[Is], limitsLowUp[Is].first, limitsLowUp[Is].second))...});
744 }
745
747 template<size_t... Is>
748 BinningT _mkBinning(const ScatterND<sizeof...(AxisT)+1>& s, std::index_sequence<Is...>) const {
749 return BinningT({((void)Is, Axis<AxisT>(s.edges(Is)))...});
750 }
751
752 };
753
754
755
757 template <typename... AxisT>
758 class BinnedEstimate : public EstimateStorage<AxisT...> {
759 public:
760 using EstimateT = BinnedEstimate<AxisT...>;
761 using BaseT = EstimateStorage<AxisT...>;
762 using BinType = typename BaseT::BinT;
763 using Ptr = std::shared_ptr<EstimateT>;
764
766 using BaseT::BaseT;
767
768 BinnedEstimate(const EstimateT&) = default;
772 using AnalysisObject::operator =;
773
777 BinnedEstimate(const BaseT& other) : BaseT(other) {}
778 //
779 BinnedEstimate(const EstimateT& other, const std::string& path) : BaseT(other, path) {}
780
782 BinnedEstimate(BaseT&& other) : BaseT(std::move(other)) {}
783 //
784 BinnedEstimate(EstimateT&& other, const std::string& path) : BaseT(std::move(other), path) {}
785
786 };
787
788
790 template <typename AxisT>
791 class BinnedEstimate<AxisT>
792 : public EstimateStorage<AxisT>,
793 public XAxisMixin<BinnedEstimate<AxisT>, AxisT> {
794 public:
797 using BinType = typename BaseT::BinT;
798 using Ptr = std::shared_ptr<EstimateT>;
799
801 using BaseT::BaseT;
802
803 BinnedEstimate(const EstimateT&) = default;
807 using AnalysisObject::operator =;
808
812 BinnedEstimate(const BaseT& other) : BaseT(other) {}
813 //
814 BinnedEstimate(const EstimateT& other, const std::string& path) : BaseT(other, path) {}
815
817 BinnedEstimate(BaseT&& other) : BaseT(std::move(other)) {}
818 //
819 BinnedEstimate(EstimateT&& other, const std::string& path) : BaseT(std::move(other), path) {}
820
821
822 BinnedEstimate(std::vector<AxisT>&& edges, const std::string& path="", const std::string& title="")
823 : BaseT(std::move(edges), path, title) {}
824
825 BinnedEstimate(const std::vector<AxisT>& edges, const std::string& path="", const std::string& title="")
826 : BaseT(edges, path, title) {}
827
834 template <typename EdgeT = double, typename = enable_if_all_CAxisT<EdgeT, AxisT>>
835 BinnedEstimate(size_t nbins, double lower, double upper, const std::string& path = "", const std::string& title = "")
836 : BaseT({nbins}, {{lower, upper}}, path, title) {}
837
839 EstimateT clone() const noexcept {
840 return EstimateT(*this);
841 }
842
844 EstimateT* newclone() const noexcept {
845 return new EstimateT(*this);
846 }
847
849 size_t indexAt(const AxisT xCoord) const noexcept {
850 return BaseT::binAt( {xCoord} ).index();
851 }
852
854 void maskBinAt(const AxisT xCoord, const bool status = true) noexcept {
855 return BaseT::maskBin({xCoord}, status);
856 }
857
858 };
859
860
861
863 template <typename AxisT1, typename AxisT2>
864 class BinnedEstimate<AxisT1, AxisT2>
865 : public EstimateStorage<AxisT1, AxisT2>,
866 public XAxisMixin<BinnedEstimate<AxisT1, AxisT2>, AxisT1>,
867 public YAxisMixin<BinnedEstimate<AxisT1, AxisT2>, AxisT2> {
868 public:
871 using BinType = typename BaseT::BinT;
872 using Ptr = std::shared_ptr<EstimateT>;
873
875 using BaseT::BaseT;
876
877 BinnedEstimate(const EstimateT&) = default;
881 using AnalysisObject::operator =;
882
886 BinnedEstimate(const BaseT& other) : BaseT(std::move(other)) {}
887 //
888 BinnedEstimate(const EstimateT& other, const std::string& path) : BaseT(other, path) {}
889
891 BinnedEstimate(BaseT&& other) : BaseT(std::move(other)) {}
892 //
893 BinnedEstimate(EstimateT&& other, const std::string& path) : BaseT(std::move(other), path) {}
894
895 BinnedEstimate(std::vector<AxisT1>&& xEdges, std::vector<AxisT2>&& yEdges,
896 const std::string& path="", const std::string& title="")
897 : BaseT(std::move(xEdges), std::move(yEdges), path, title) {}
898
899 BinnedEstimate(const std::vector<AxisT1>& xEdges, const std::vector<AxisT2>& yEdges,
900 const std::string& path="", const std::string& title="")
901 : BaseT(xEdges, yEdges, path, title) {}
902
909 template <typename EdgeT = double, typename = enable_if_all_CAxisT<EdgeT, AxisT1, AxisT2>>
910 BinnedEstimate(size_t nbinsX, double lowerX, double upperX,
911 size_t nbinsY, double lowerY, double upperY,
912 const std::string& path = "", const std::string& title = "")
913 : BaseT({nbinsX, nbinsY}, {{lowerX, upperX}, {lowerY, upperY}}, path, title) {}
914
916 EstimateT clone() const noexcept {
917 return EstimateT(*this);
918 }
919
921 EstimateT* newclone() const noexcept {
922 return new EstimateT(*this);
923 }
924
926 BinType& bin(const size_t index) noexcept {
927 return BaseT::bin(index);
928 }
929
931 const BinType& bin(const size_t index) const noexcept {
932 return BaseT::bin(index);
933 }
934
936 BinType& bin(const size_t localX, const size_t localY) noexcept {
937 return BaseT::bin( {localX, localY} );
938 }
939
941 const BinType& bin(const size_t localX, const size_t localY) const noexcept {
942 return BaseT::bin( {localX, localY} );
943 }
944
946 BinType& binAt(const AxisT1 xCoord, const AxisT2 yCoord) noexcept {
947 return BaseT::binAt( {xCoord, yCoord} );
948 }
949
951 const BinType& binAt(const AxisT1 xCoord, const AxisT2 yCoord) const noexcept {
952 return BaseT::binAt( {xCoord, yCoord} );
953 }
954
956 size_t indexAt(const AxisT1 xCoord, const AxisT2 yCoord) const noexcept {
957 return BaseT::binAt( {xCoord, yCoord} ).index();
958 }
959
961 void maskBinAt(const AxisT1 xCoord, const AxisT2 yCoord, const bool status = true) noexcept {
962 return BaseT::maskBin({xCoord, yCoord}, status);
963 }
964
965 };
966
967
969 template <typename AxisT1, typename AxisT2, typename AxisT3>
970 class BinnedEstimate<AxisT1, AxisT2, AxisT3>
971 : public EstimateStorage<AxisT1, AxisT2, AxisT3>,
972 public XAxisMixin<BinnedEstimate<AxisT1, AxisT2, AxisT3>, AxisT1>,
973 public YAxisMixin<BinnedEstimate<AxisT1, AxisT2, AxisT3>, AxisT2>,
974 public ZAxisMixin<BinnedEstimate<AxisT1, AxisT2, AxisT3>, AxisT3> {
975 public:
978 using BinType = typename BaseT::BinT;
979 using Ptr = std::shared_ptr<EstimateT>;
980
982 using BaseT::BaseT;
983
984 BinnedEstimate(const EstimateT&) = default;
988 using AnalysisObject::operator =;
989
993 BinnedEstimate(const BaseT& other) : BaseT(other) {}
994 //
995 BinnedEstimate(const EstimateT& other, const std::string& path) : BaseT(other, path) {}
996
998 BinnedEstimate(BaseT&& other) : BaseT(std::move(other)) {}
999 //
1000 BinnedEstimate(EstimateT&& other, const std::string& path) : BaseT(std::move(other), path) {}
1001
1008 template <typename EdgeT = double, typename = enable_if_all_CAxisT<EdgeT, AxisT1, AxisT2, AxisT3>>
1009 BinnedEstimate(size_t nbinsX, double lowerX, double upperX,
1010 size_t nbinsY, double lowerY, double upperY,
1011 size_t nbinsZ, double lowerZ, double upperZ,
1012 const std::string& path = "", const std::string& title = "")
1013 : BaseT({nbinsX, nbinsY, nbinsZ}, {{lowerX, upperX}, {lowerY, upperY},
1014 {lowerZ, upperZ}}, path, title) {}
1015
1017 EstimateT clone() const noexcept {
1018 return EstimateT(*this);
1019 }
1020
1022 EstimateT* newclone() const noexcept {
1023 return new EstimateT(*this);
1024 }
1025
1027 BinType& bin(const size_t index) noexcept {
1028 return BaseT::bin(index);
1029 }
1030
1032 const BinType& bin(const size_t index) const noexcept {
1033 return BaseT::bin(index);
1034 }
1035
1037 BinType& bin(const size_t localX, const size_t localY, const size_t localZ) noexcept {
1038 return BaseT::bin( {localX, localY, localZ} );
1039 }
1040
1042 const BinType& bin(const size_t localX, const size_t localY, const size_t localZ) const noexcept {
1043 return BaseT::bin( {localX, localY, localZ} );
1044 }
1045
1047 BinType& binAt(const AxisT1 xCoord, const AxisT2 yCoord, const AxisT3 zCoord) noexcept {
1048 return BaseT::binAt( {xCoord, yCoord, zCoord} );
1049 }
1050
1052 const BinType& binAt(const AxisT1 xCoord, const AxisT2 yCoord, const AxisT3 zCoord) const noexcept {
1053 return BaseT::binAt( {xCoord, yCoord, zCoord} );
1054 }
1055
1057 size_t indexAt(const AxisT1 xCoord, const AxisT2 yCoord, const AxisT3 zCoord) const noexcept {
1058 return BaseT::binAt( {xCoord, yCoord, zCoord} ).index();
1059 }
1060
1062 void maskBinAt(const AxisT1 xCoord, const AxisT2 yCoord, const AxisT3 zCoord, const bool status = true) noexcept {
1063 return BaseT::maskBin({xCoord, yCoord, zCoord}, status);
1064 }
1065
1066 };
1067
1070
1072 template <typename... AxisT>
1073 inline BinnedEstimate<AxisT...>
1075 first += second;
1076 return first;
1077 }
1078
1079
1081 template <typename... AxisT>
1082 inline BinnedEstimate<AxisT...>
1084 first += std::move(second);
1085 return first;
1086 }
1087
1088
1090 template <typename... AxisT>
1091 inline BinnedEstimate< AxisT...>
1093 first -= second;
1094 return first;
1095 }
1096
1098 template <typename... AxisT>
1099 inline BinnedEstimate< AxisT...>
1101 first -= std::move(second);
1102 return first;
1103 }
1104
1106 template <typename... AxisT>
1107 inline BinnedEstimate<AxisT...>
1109 const std::string& pat_uncorr="^stat|^uncor" ) {
1110 if (numer != denom) {
1111 throw BinningError("Arithmetic operation requires compatible binning!");
1112 }
1113
1114 BinnedEstimate<AxisT...> rtn(numer.binning());
1115 if (numer.path() == denom.path()) rtn.setPath(numer.path());
1116 if (rtn.hasAnnotation("ScaledBy")) rtn.rmAnnotation("ScaledBy");
1117
1118 for (const auto& b_num : numer.bins(true, true)) {
1119 const size_t idx = b_num.index();
1120 rtn.bin(idx) = divide(b_num, denom.bin(idx), pat_uncorr);
1121 }
1122 rtn.maskBins(denom.maskedBins(), true);
1123
1124 return rtn;
1125 }
1126
1128 template <typename... AxisT>
1129 inline BinnedEstimate<AxisT...>
1131 return divide(numer, denom);
1132 }
1133
1135 template <typename... AxisT>
1136 inline BinnedEstimate<AxisT...>
1138 return divide(std::move(numer), denom);
1139 }
1140
1142 template <typename... AxisT>
1143 inline BinnedEstimate<AxisT...>
1145 return divide(numer, std::move(denom));
1146 }
1147
1149 template <typename... AxisT>
1150 inline BinnedEstimate<AxisT...>
1152 return divide(std::move(numer), std::move(denom));
1153 }
1154
1155
1160 template <typename... AxisT>
1161 inline BinnedEstimate<AxisT...>
1163 const std::string& pat_uncorr="^stat|^uncor" ) {
1164
1165 if (accepted != total) {
1166 throw BinningError("Arithmetic operation requires compatible binning!");
1167 }
1168
1169 BinnedEstimate<AxisT...> rtn(accepted.binning());
1170
1171 for (const auto& b_acc : accepted.bins(true, true)) {
1172 Estimate est;
1173 const size_t idx = b_acc.index();
1174 try {
1175 est = efficiency(b_acc, total.bin(idx), pat_uncorr);
1176 } catch (const UserError& e) {
1177 //
1178 }
1179 rtn.bin(idx).set(est);
1180 }
1181 return rtn;
1182 }
1183
1184
1186 template <typename... AxisT>
1187 inline BinnedEstimate<AxisT...>
1189 const BinnedEstimate<AxisT...>& b,
1190 const std::string& pat_uncorr="^stat|^uncor" ) {
1191 return divde(subtract(a-b, pat_uncorr), add(a+b, pat_uncorr), pat_uncorr);
1192 }
1193
1194
1196
1197
1200
1201 template <typename... AxisT>
1202 inline void transform(BinnedEstimate<AxisT...>& est, const Trf<1>& fn) {
1203 for (auto& b : est.bins(true, true)) {
1204 b.transform(fn);
1205 }
1206 }
1207
1208 template <typename... AxisT, typename FN>
1209 inline void transform(BinnedEstimate<AxisT...>& est, const FN& fn) {
1210 transform(est, Trf<1>(fn));
1211 }
1212
1214
1215
1218
1220 template<typename A1>
1222
1223 template <typename A1, typename A2>
1225
1226 template <typename A1, typename A2, typename A3>
1228
1230 namespace {
1231 template <class T>
1232 struct EstimateMaker;
1233
1234 template<size_t... Is>
1235 struct EstimateMaker<std::index_sequence<Is...>> {
1237 };
1238 }
1239
1240 template<size_t N>
1241 using EstimateND = typename EstimateMaker<std::make_index_sequence<N>>::type;
1242
1243
1244 // User-friendly names (continuous axes only)
1248
1250
1251}
1252
1253#endif
AnalysisObject is the base class for histograms and scatters.
virtual AnalysisObject & operator=(const AnalysisObject &ao) noexcept
Default copy assignment operator.
void setAnnotation(const std::string &name, const T &value)
Add or set an annotation by name (templated for remaining types)
void setPath(const std::string &path)
const std::string title() const
Get the AO title.
std::vector< std::string > annotations() const
const std::string path() const
Get the AO path.
void rmAnnotation(const std::string &name)
Delete an annotation by name.
const std::string & annotation(const std::string &name) const
Get an annotation by name (as a string)
bool hasAnnotation(const std::string &name) const
Check if an annotation is defined.
AnalysisObject()
Default constructor.
Discrete axis with edges of non-floating-point-type.
Definition BinnedAxis.h:91
Specialisation of the BinnedEstimate for a 3D BinnedEstimate.
BinType & binAt(const AxisT1 xCoord, const AxisT2 yCoord, const AxisT3 zCoord) noexcept
Bin access using coordinates.
const BinType & bin(const size_t index) const noexcept
Bin access using global index (const version)
BinnedEstimate(const EstimateT &other, const std::string &path)
EstimateT clone() const noexcept
Make a copy on the stack.
BinType & bin(const size_t index) noexcept
Bin access using global index.
void maskBinAt(const AxisT1 xCoord, const AxisT2 yCoord, const AxisT3 zCoord, const bool status=true) noexcept
Mask/Unmask bin at given set of coordinates.
EstimateT * newclone() const noexcept
Make a copy on the heap.
BinnedEstimate(size_t nbinsX, double lowerX, double upperX, size_t nbinsY, double lowerY, double upperY, size_t nbinsZ, double lowerZ, double upperZ, const std::string &path="", const std::string &title="")
Constructor with auto-setup of evenly spaced axes.
const BinType & bin(const size_t localX, const size_t localY, const size_t localZ) const noexcept
Bin access using local indices.
BinnedEstimate(const BaseT &other)
Copy constructor (needed for clone functions).
const BinType & binAt(const AxisT1 xCoord, const AxisT2 yCoord, const AxisT3 zCoord) const noexcept
Bin access using coordinates (const version)
BinnedEstimate(EstimateT &&other, const std::string &path)
size_t indexAt(const AxisT1 xCoord, const AxisT2 yCoord, const AxisT3 zCoord) const noexcept
Find bin index for given coordinates.
BinType & bin(const size_t localX, const size_t localY, const size_t localZ) noexcept
Bin access using local indices.
BinnedEstimate(BaseT &&other)
Move constructor.
Specialisation of the BinnedEstimate for a 2D BinnedEstimate.
BinType & bin(const size_t index) noexcept
Bin access using global index.
BinType & bin(const size_t localX, const size_t localY) noexcept
Bin access using local indices.
BinnedEstimate(EstimateT &&other, const std::string &path)
const BinType & binAt(const AxisT1 xCoord, const AxisT2 yCoord) const noexcept
Bin access using coordinates (const version)
EstimateT clone() const noexcept
Make a copy on the stack.
BinnedEstimate(const EstimateT &other, const std::string &path)
BinnedEstimate(EstimateT &&)=default
BinnedEstimate(const BaseT &other)
Copy constructor (needed for clone functions).
const BinType & bin(const size_t index) const noexcept
Bin access using global index (const version)
BinnedEstimate(const std::vector< AxisT1 > &xEdges, const std::vector< AxisT2 > &yEdges, const std::string &path="", const std::string &title="")
std::shared_ptr< EstimateT > Ptr
BinType & binAt(const AxisT1 xCoord, const AxisT2 yCoord) noexcept
Bin access using coordinates.
BinnedEstimate(BaseT &&other)
Move constructor.
size_t indexAt(const AxisT1 xCoord, const AxisT2 yCoord) const noexcept
Find bin index for given coordinates.
BinnedEstimate(const EstimateT &)=default
BinnedEstimate(std::vector< AxisT1 > &&xEdges, std::vector< AxisT2 > &&yEdges, const std::string &path="", const std::string &title="")
const BinType & bin(const size_t localX, const size_t localY) const noexcept
Bin access using local indices (const version)
EstimateT * newclone() const noexcept
Make a copy on the heap.
void maskBinAt(const AxisT1 xCoord, const AxisT2 yCoord, const bool status=true) noexcept
Mask/Unmask bin at given set of coordinates.
BinnedEstimate(size_t nbinsX, double lowerX, double upperX, size_t nbinsY, double lowerY, double upperY, const std::string &path="", const std::string &title="")
Constructor with auto-setup of evenly spaced axes.
Specialisation of the BinnedEstimate for a 1D histogram.
typename BaseT::BinT BinType
BinnedEstimate(EstimateT &&)=default
EstimateT * newclone() const noexcept
Make a copy on the heap.
size_t indexAt(const AxisT xCoord) const noexcept
Find bin index for given coordinates.
BinnedEstimate(BaseT &&other)
Move constructor.
BinnedEstimate(const BaseT &other)
Copy constructor (needed for clone functions).
EstimateT clone() const noexcept
Make a copy on the stack.
BinnedEstimate(std::vector< AxisT > &&edges, const std::string &path="", const std::string &title="")
BinnedEstimate(const std::vector< AxisT > &edges, const std::string &path="", const std::string &title="")
void maskBinAt(const AxisT xCoord, const bool status=true) noexcept
Mask/Unmask bin at given set of coordinates.
BinnedEstimate(size_t nbins, double lower, double upper, const std::string &path="", const std::string &title="")
Constructor with auto-setup of evenly spaced axes.
BinnedEstimate(const EstimateT &)=default
BinnedEstimate(const EstimateT &other, const std::string &path)
BinnedEstimate(EstimateT &&other, const std::string &path)
std::shared_ptr< EstimateT > Ptr
Forward declaration.
typename BaseT::BinT BinType
BinnedEstimate(EstimateT &&)=default
BinnedEstimate(BaseT &&other)
Move constructor.
BinnedEstimate(const BaseT &other)
Copy constructor (needed for clone functions).
BinnedEstimate< AxisT... > EstimateT
BinnedEstimate & operator=(const EstimateT &)=default
BinnedEstimate(const EstimateT &)=default
BinnedEstimate(const EstimateT &other, const std::string &path)
BinnedEstimate(EstimateT &&other, const std::string &path)
std::shared_ptr< EstimateT > Ptr
BinnedStorage, stores the bins and coordinates access to them.
void maskBin(const size_t indexToMask, const bool status=true) noexcept
Mask a bin at a given index.
BinT & bin(size_t idx) noexcept
Returns reference to the bin at idx.
void maskBins(const std::vector< size_t > &indicesToMask, const bool status=true) noexcept
Mask a range of bins.
size_t numBinsAt(const size_t axisN, const bool includeOverflows=false) const noexcept
Number of bins in the BinnedStorage.
size_t numBins(const bool includeOverflows=false, const bool includeMaskedBins=false) const noexcept
Number of bins in the BinnedStorage.
Binning< std::decay_t< decltype(std::declval< Axis< AxisT > >())>... > BinningT
Convenience alias to be used in constructor.
BinnedStorage & operator=(const BinnedStorage &other) noexcept
Copy assignment.
Bin< sizeof...(AxisT), Estimate, BinningT > BinT
void clearBins() noexcept
Deletes all bins and creates empty new ones.
BinsVecWrapper< BinsVecT > bins(const bool includeOverflows=false, const bool includeMaskedBins=false) noexcept
Returns bins vector wrapper, which skips masked elements when iterated over.
const BinningT & binning() const noexcept
Returns dimension underlying binning object reference.
std::vector< size_t > maskedBins() const noexcept
BinT & binAt(typename BinningT::EdgeTypesTuple &&coords) noexcept
Returns reference to the bin at coordinates.
Error for general binning problems.
Definition Exceptions.h:27
EstimateStorage convenience class based on BinnedStorage.
void scale(const double scalefactor) noexcept
Rescale as if all fill weights had been different by factor scalefactor.
std::enable_if_t< std::is_floating_point< E >::value, E > min() const noexcept
Get the lowest non-overflow edge of the axis.
std::vector< double > vals(const bool includeOverflows=false, const bool includeMaskedBins=false) const
Get list of central values.
EstimateStorage & operator+=(const EstimateStorage &est)
typename BaseT::BinT BinT
std::vector< std::vector< double > > covarianceMatrix(const bool ignoreOffDiagonalTerms=false, const bool includeOverflows=false, const bool includeMaskedBins=false) const
Construct a covariance matrix from the error breakdown.
std::vector< double > serializeContent(bool fixed_length=false) const noexcept
Content serialisation for MPI reduce operations.
EstimateStorage(EstimateStorage &&other, const std::string &path="")
Move constructor.
EstimateStorage(const std::string &path="", const std::string &title="")
Nullary constructor for unique pointers etc.
void rebinTo(const std::vector< typename BinningT::template getAxisT< axisN >::EdgeT > &newedges)
Rebin to the given list of bin edges.
EstimateStorage(std::vector< AxisT > &&... binsEdges, const std::string &path="", const std::string &title="")
Constructor giving explicit bin edges as rvalue reference.
EstimateStorage & add(const EstimateStorage &est, const std::string &pat_uncorr="^stat|^uncor")
Add two EstimateStorages.
EstimateStorage & add(EstimateStorage &&est, const std::string &pat_uncorr="^stat|^uncor")
Add two (rvalue) EstimateStorages.
EstimateStorage & operator-=(const EstimateStorage &est)
double auc(const bool includeBinVol=true, const bool includeOverflows=false, const bool includeMaskedBins=false) const
Convenient alias for areaUnderCurve()
EstimateStorage * newclone() const noexcept
Make a copy on the heap.
EstimateStorage(std::initializer_list< AxisT > &&... binsEdges, const std::string &path="", const std::string &title="")
Constructor giving explicit bin edges as initializer list.
EstimateStorage(const std::vector< size_t > &nBins, const std::vector< std::pair< EdgeT, EdgeT > > &limitsLowUp, const std::string &path="", const std::string &title="")
Constructor giving range and number of bins.
void reset() noexcept
Reset the EstimateStorage.
EstimateStorage(const ScatterND< sizeof...(AxisT)+1 > &s, const std::string &path="", const std::string &title="")
Constructor given a scatter.
AnalysisObject * mkInert(const std::string &path="", const std::string &source="") const noexcept
Method returns clone of the estimate with streamlined error source.
void rebin(unsigned int n, size_t begin=1, size_t end=UINT_MAX)
Overloaded alias for rebinBy.
void rebinBy(unsigned int n, size_t begin=1, size_t end=UINT_MAX)
Merge every group of n bins, from start to end inclusive.
double areaUnderCurve(const bool includeBinVol=true, const bool includeOverflows=false, const bool includeMaskedBins=false) const
Calculate the volume underneath the EstimateStorage.
void rebin(const std::vector< typename BinningT::template getAxisT< axisN >::EdgeT > &newedges)
Overloaded alias for rebinTo.
EstimateStorage(const std::vector< AxisT > &... binsEdges, const std::string &path="", const std::string &title="")
Constructor giving explicit bin edges as lvalue reference.
EstimateStorage(const EstimateStorage &other, const std::string &path="")
Copy constructor.
EstimateStorage clone() const noexcept
Make a copy on the stack.
EstimateStorage & subtract(EstimateStorage &&est, const std::string &pat_uncorr="^stat|^uncor")
Subtract one (rvalue) EstimateStorages from another one.
auto mkScatter(const std::string &path="", const bool includeOverflows=false, const bool includeMaskedBins=false) const
Produce a ScatterND from a EstimateStorage.
std::enable_if_t< std::is_floating_point< E >::value, E > max() const noexcept
Get the highest non-overflow edge of the axis.
EstimateStorage(BinningT &&binning, const std::string &path="", const std::string &title="")
Constructor given an rvalue BinningT.
EstimateStorage & subtract(const EstimateStorage &est, const std::string &pat_uncorr="^stat|^uncor")
Subtract one EstimateStorages from another one.
EstimateStorage & operator=(const EstimateStorage &est) noexcept
Copy assignment.
size_t dim() const noexcept
Total dimension of the object (number of axes + estimate)
auto mkEstimates(const std::string &path="", const bool includeOverflows=false) const
Split into vector of BinnedEstimates along axisN.
std::vector< std::string > sources() const
Get list of error sources.
BinnedStorage< Estimate, AxisT... > BaseT
std::vector< E > edges(const bool includeOverflows=false) const noexcept
Templated version to get edges of axis N by value. +-inf edges are included.
size_t lengthContent(bool fixed_length=false) const noexcept
Length of serialized content vector for MPI reduce operations.
typename BaseT::BinningT BinningT
EstimateStorage(const BinningT &binning, const std::string &path="", const std::string &title="")
Constructor given a binning type.
std::enable_if_t< std::is_floating_point< E >::value, std::vector< E > > widths(const bool includeOverflows=false) const noexcept
Templated version to get bin widths of axis N by value.
void deserializeContent(const std::vector< double > &data)
Content deserialisation for MPI reduce operations.
A point estimate (base class for the Estimate)
Definition Estimate.h:29
A generic data type which is just a collection of n-dim data points with errors.
Definition Scatter.h:154
ScatterND< N > & addPoint(const PointND< N > &pt)
Insert a new point.
Definition Scatter.h:369
Error for problems introduced outside YODA, to put it nicely.
Definition Exceptions.h:100
Anonymous namespace to limit visibility.
std::string mkTypeString()
Helper function to construct the BinnedDbn and BinnedEstimate type names.
void transform(BinnedEstimate< AxisT... > &est, const Trf< 1 > &fn)
std::enable_if_t< all_CAxes< EdgeT... >::value > enable_if_all_CAxisT
Checks if all edge types are continuous.
std::string mkAxisConfig()
Helper function to construct the axis config.
typename std::conjunction< std::is_floating_point< EdgeT >... > all_CAxes
BinnedDbn< DbnN, AxisT... > operator+(BinnedDbn< DbnN, AxisT... > first, BinnedDbn< DbnN, AxisT... > &&second)
Add two BinnedDbn objects.
Definition BinnedDbn.h:1058
BinnedEstimate< AxisT... > operator/(const BinnedDbn< DbnN, AxisT... > &numer, const BinnedDbn< DbnN, AxisT... > &denom)
Definition BinnedDbn.h:1131
NUM sqr(NUM a)
Named number-type squaring operation.
Definition MathUtils.h:216
BinnedEstimate< AxisT... > efficiency(const BinnedDbn< DbnN, AxisT... > &accepted, const BinnedDbn< DbnN, AxisT... > &total)
Calculate a binned efficiency ratio of two BinnedDbn objects.
Definition BinnedDbn.h:1160
typename EstimateMaker< std::make_index_sequence< N > >::type EstimateND
BinnedEstimate< AxisT... > asymm(const BinnedDbn< DbnN, AxisT... > &a, const BinnedDbn< DbnN, AxisT... > &b)
Calculate the asymmetry (a-b)/(a+b) of two BinnedDbn objects.
Definition BinnedDbn.h:1199
BinnedEstimate< AxisT... > add(const BinnedDbn< DbnN, AxisT... > &dbn, const BinnedEstimate< AxisT... > &est)
Calculate the addition of a BinnedDbn with a BinnedEstimate.
Definition BinnedDbn.h:1268
BinnedEstimate< AxisT... > subtract(const BinnedDbn< DbnN, AxisT... > &dbn, const BinnedEstimate< AxisT... > &est)
Calculate the subtraction of a BinnedEstimate from a BinnedDbn.
Definition BinnedDbn.h:1300
BinnedDbn< DbnN, AxisT... > operator-(BinnedDbn< DbnN, AxisT... > first, BinnedDbn< DbnN, AxisT... > &&second)
Subtract one BinnedDbn object from another.
Definition BinnedDbn.h:1074
BinnedEstimate< AxisT... > divide(const BinnedDbn< DbnN, AxisT... > &numer, const BinnedDbn< DbnN, AxisT... > &denom)
Divide two BinnedDbn objects.
Definition BinnedDbn.h:1090
CRTP mixin introducing convenience aliases along X axis.
Definition BinnedUtils.h:18
CRTP mixin introducing convenience aliases along Y axis.
CRTP mixin introducing convenience aliases along Z axis.