yoda is hosted by Hepforge, IPPP Durham
YODA - Yet more Objects for Data Analysis 2.1.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-2025 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#include <regex>
16
17#ifdef HAVE_HDF5
18#include "YODA/Utils/H5Utils.h"
19#endif
20
21
22namespace YODA {
23
25 namespace {
27 template<size_t axisN, typename BinT>
28 std::pair<double, double> nullifyIfDisc(const BinT& /* b */, const double /* val */, std::false_type, const double null = 0.0) {
29 return { null, null };
30 }
31
34 template<size_t axisN, typename BinT>
35 std::pair<double, double> nullifyIfDisc(const BinT& b, const double val, std::true_type, const double /* null */ = 0.0) {
36 return { val - b.template min<axisN>(), b.template max<axisN>() - val };
37 }
38
40 template<size_t axisN, typename BinT>
41 double unifyIfDisc(const BinT& /* b */, std::false_type, const double unity = 1.0) {
42 return unity;
43 }
44
46 template<size_t axisN, typename BinT>
47 double unifyIfDisc(const BinT& b, std::true_type, const double /* unity */ = 1.0) {
48 return b.template width<axisN>();
49 }
50
52 template<size_t axisN, typename BinT>
53 double coordPicker(const BinT& b, std::false_type, std::false_type) {
54 return b.index();
55 }
56
58 template<size_t axisN, typename BinT>
59 double coordPicker(const BinT& b, std::true_type, std::false_type) {
60 return b.template edge<axisN>();
61 }
63 template<size_t axisN, typename BinT>
64 double coordPicker(const BinT& b, std::true_type, std::true_type) {
65 return b.template mid<axisN>();
66 }
67 }
68
69
71 template <typename... AxisT>
72 class BinnedEstimate;
73
79 template<typename... AxisT>
81 : public BinnedStorage<Estimate, AxisT...>,
82 public AnalysisObject {
83 public:
84
85 using BaseT = BinnedStorage<Estimate, AxisT...>;
86 using BinningT = typename BaseT::BinningT;
87 using BinT = typename BaseT::BinT;
88 using BinType = BinT;
89 using AnalysisObject::operator =;
90
93
95 EstimateStorage(const std::string& path = "", const std::string& title = "")
96 : BaseT(), AnalysisObject(mkTypeString<AxisT...>(), path, title) { }
97
103 EstimateStorage(std::vector<AxisT>&&... binsEdges, const std::string& path = "", const std::string& title = "")
104 : BaseT(Axis<AxisT>(std::move(binsEdges))...), AnalysisObject(mkTypeString<AxisT...>(), path, title) { }
105
111 EstimateStorage(const std::vector<AxisT>&... binsEdges, const std::string& path = "", const std::string& title = "")
112 : BaseT(Axis<AxisT>(binsEdges)...), AnalysisObject(mkTypeString<AxisT...>(), path, title) { }
113
119 EstimateStorage(std::initializer_list<AxisT>&&... binsEdges, const std::string& path = "", const std::string& title = "")
120 : BaseT(Axis<AxisT>(std::move(binsEdges))...), AnalysisObject(mkTypeString<AxisT...>(), path, title) { }
121
123 template <typename EdgeT = double, typename = enable_if_all_CAxisT<EdgeT, AxisT...>>
124 EstimateStorage(const std::vector<size_t>& nBins,
125 const std::vector<std::pair<EdgeT, EdgeT>>& limitsLowUp,
126 const std::string& path = "", const std::string& title = "")
127 //: BaseT( BinningT(nBins, limitsLowUp, std::make_index_sequence<sizeof...(AxisT)>{}) ),
128 : BaseT( _mkBinning(nBins, limitsLowUp, std::make_index_sequence<sizeof...(AxisT)>{}) ),
129 AnalysisObject(mkTypeString<AxisT...>(), path, title) { }
130
132 EstimateStorage(const BinningT& binning, const std::string& path = "", const std::string& title = "")
133 : BaseT(binning), AnalysisObject(mkTypeString<AxisT...>(), path, title) { }
134
136 EstimateStorage(BinningT&& binning, const std::string& path = "", const std::string& title = "")
137 : BaseT(std::move(binning)), AnalysisObject(mkTypeString<AxisT...>(), path, title) { }
138
140 template <typename EdgeT = double, typename = enable_if_all_CAxisT<EdgeT, AxisT...>>
141 EstimateStorage(const ScatterND<sizeof...(AxisT)+1>& s, const std::string& path = "", const std::string& title = "")
142 : BaseT(_mkBinning(s, std::make_index_sequence<sizeof...(AxisT)>{})),
143 AnalysisObject(mkTypeString<AxisT...>(), path, title) { }
144
148 EstimateStorage(const EstimateStorage& other, const std::string& path = "") : BaseT(other),
149 AnalysisObject(mkTypeString<AxisT...>(), path!=""? path : other.path(), other, other.title()) { }
150
154 EstimateStorage(EstimateStorage&& other, const std::string& path = "") : BaseT(std::move(other)),
155 AnalysisObject(mkTypeString<AxisT...>(), path!=""? path : other.path(), other, other.title()) { }
156
158 EstimateStorage clone() const noexcept {
159 return EstimateStorage(*this);
160 }
161
163 EstimateStorage* newclone() const noexcept {
164 return new EstimateStorage(*this);
165 }
166
168
169
172
173 private:
174
175 // @brief Render information about this AO (private implementation)
176 template<size_t... Is>
177 void _renderYODA_aux(std::ostream& os, const int width, std::index_sequence<Is...>) const noexcept {
178
179 // print bin edges
180 BaseT::_binning._renderYODA(os);
181
182 // Assemble union of error sources, as it's not guaranteed
183 // that every bin has the same error breakdown
184 const std::vector<std::string> labels = this->sources();
185 if (labels.size()) {
186 os << "ErrorLabels: [";
187 for (size_t i = 0; i < labels.size(); ++i) {
188 const std::string& src = labels[i];
189 if (i) os << ", ";
190 os << std::quoted(src);
191 }
192 os << "]\n";
193 }
194
195 // column header: content types
196 os << std::setw(width) << std::left << "# value" << "\t";
197 const int errwidth = std::max(int(std::to_string(labels.size()).size()+7), width); // "errDn(" + src + ")"
198 for (size_t i = 0; i < labels.size(); ++i) {
199 const std::string& src = labels[i];
200 if (src.empty()) {
201 os << std::setw(errwidth) << std::left << "totalDn" << "\t"
202 << std::setw(errwidth) << std::left << "totalUp" << "\t";
203 }
204 else {
205 os << std::setw(errwidth) << std::left << ("errDn(" + std::to_string(i+1) + ")") << "\t"
206 << std::setw(errwidth) << std::left << ("errUp(" + std::to_string(i+1) + ")") << "\t";
207 }
208 }
209 os << "\n";
210
211 for (const auto& b : BaseT::bins(true, true)) {
212 os << std::setw(width) << std::left << b.val() << "\t"; // print value
213 // print systs if available
214 for (const std::string& src : labels) {
215 if (!b.hasSource(src)) {
216 os << std::setw(errwidth) << std::left << "---" << "\t"
217 << std::setw(errwidth) << std::left << "---" << "\t";
218 continue;
219 }
220 const auto& err = b.err(src);
221 os << std::setw(errwidth) << std::left << err.first << "\t"
222 << std::setw(errwidth) << std::left << err.second << "\t";
223 }
224 os << "\n";
225 }
226 }
227
228 public:
229
232
233 // @brief Render information about this AO
234 void _renderYODA(std::ostream& os, const int width = 13) const noexcept {
235 _renderYODA_aux(os, width, std::make_index_sequence<sizeof...(AxisT)>{});
236 }
237
238 // @brief Render scatter-like information about this AO
239 void _renderFLAT(std::ostream& os, const int width = 13) const noexcept {
240 const ScatterND<sizeof...(AxisT)+1> tmp = mkScatter();
241 tmp._renderYODA(os, width);
242 }
243
244 #ifdef HAVE_HDF5
245
246 // @brief Extract error labels of this AO
247 void _extractLabels(std::vector<std::string>& labels,
248 std::vector<size_t>& labelsizes) const noexcept {
249 size_t nlabels = 0;
250 for (const auto& b : BaseT::bins(true, true)) {
251 std::vector<std::string> keys = b.sources();
252 nlabels += keys.size()+1; //< +1 for length info itself
253 labels.insert(std::end(labels),
254 std::make_move_iterator(std::begin(keys)),
255 std::make_move_iterator(std::end(keys)));
256 }
257 std::sort(labels.begin(), labels.end());
258 labels.erase( std::unique(labels.begin(), labels.end()), labels.end() );
259 labelsizes.emplace_back(std::move(nlabels));
260 };
261
262 // @brief Extract axes edges of this AO into map of @a edges
263 void _extractEdges(std::map<std::string, EdgeHandlerBasePtr>& edges,
264 const std::vector<std::string>& labels) const noexcept {
265
266 using lenT = EdgeHandler<size_t>;
267 using lenPtr = EdgeHandlerPtr<size_t>;
268 const std::string lengthID("sizeinfo");
269 lenPtr nedges = std::static_pointer_cast<lenT>(edges.find(lengthID)->second);
270
271 auto extractEdges = [&edges, &binning = BaseT::_binning, &nedges](auto I) {
272
273 using thisEdgeT = typename BinningT::template getEdgeT<I>;
274 using thisHandlerT = EdgeHandler<thisEdgeT>;
275 using thisHandlerPtr = EdgeHandlerPtr<thisEdgeT>;
276
277 const std::string edgeID = std::string("edges_") + TypeID<thisEdgeT>::name();
278 std::vector<thisEdgeT> tmp = binning.template edges<I>();
279 nedges->extend({ tmp.size() });
280
281 auto itr = edges.find(edgeID);
282 if (itr != edges.cend()) {
283 thisHandlerPtr edgeset = std::static_pointer_cast<thisHandlerT>(itr->second);
284 edgeset->extend(std::move(tmp));
285 }
286 else {
287 edges[edgeID] = std::make_shared<thisHandlerT>(std::move(tmp));
288 }
289 };
290 MetaUtils::staticFor<sizeof...(AxisT)>(extractEdges);
291
292 std::vector<size_t> masks = BaseT::_binning.maskedBins();
293 nedges->extend({ masks.size() });
294 nedges->extend(std::move(masks));
295
296 const auto& itr = labels.cbegin();
297 const auto& itrEnd = labels.cend();
298 for (const auto& b : BaseT::bins(true, true)) {
299 vector<string> keys = b.sources();
300 nedges->extend({ keys.size() });
301 for (const string& k : keys) {
302 size_t dist = std::find(itr, itrEnd, k) - itr;
303 nedges->extend({ dist });
304 }
305 }
306 }
307
308 #endif
309
311
312
315
317 void scale(const double scalefactor) noexcept {
318 setAnnotation("ScaledBy", annotation<double>("ScaledBy", 1.0) * scalefactor);
319 for (auto& bin : BaseT::_bins) {
320 bin.scale(scalefactor);
321 }
322 }
323
324
333 template <size_t axisN>
334 void rebinBy(unsigned int n, size_t begin=1, size_t end=UINT_MAX) {
335 if (n < 1) throw UserError("Rebinning requested in groups of 0!");
336 if (!begin) throw UserError("Visible bins start with index 1!");
337 if (end > BaseT::numBinsAt(axisN)+1) end = BaseT::numBinsAt(axisN) + 1;
338 for (size_t m = begin; m < end; ++m) {
339 if (m > BaseT::numBinsAt(axisN)+1) break; // nothing to be done
340 const size_t myend = (m+n-1 < BaseT::numBinsAt(axisN)+1) ? m+n-1 : BaseT::numBinsAt(axisN);
341 if (myend > m) {
342 BaseT::template mergeBins<axisN>({m, myend});
343 end -= myend-m; //< reduce upper index by the number of removed bins
344 }
345 }
346 }
347
349 template <size_t axisN>
350 void rebin(unsigned int n, size_t begin=1, size_t end=UINT_MAX) {
351 rebinBy<axisN>(n, begin, end);
352 }
353
355 template <size_t axisN>
356 void rebinTo(const std::vector<typename BinningT::template getAxisT<axisN>::EdgeT>& newedges) {
357 if (newedges.size() < 2)
358 throw UserError("Requested rebinning to an edge list which defines no bins");
359 using thisAxisT = typename BinningT::template getAxisT<axisN>;
360 using thisEdgeT = typename thisAxisT::EdgeT;
361 // get list of shared edges
362 thisAxisT& oldAxis = BaseT::_binning.template axis<axisN>();
363 const thisAxisT newAxis(std::move(newedges));
364 const std::vector<thisEdgeT> eshared = oldAxis.sharedEdges(newAxis);
365 if (eshared.size() != newAxis.edges().size())
366 throw BinningError("Requested rebinning to incompatible edges");
367 // loop over new lower bin edges (= first bin index of merge range)
368 for (size_t begin = 0; begin < eshared.size() - 1; ++begin) {
369 // find index of upper edge along old axis
370 // (subtracting 1 gives index of last bin to be merged)
371 size_t end = oldAxis.index(eshared[begin+1]) - 1;
372 // if the current edge is the last visible edge before the overflow
373 // merge the remaining bins into the overflow
374 if (begin == newAxis.numBins(true)-1) end = oldAxis.numBins(true)-1;
375 // merge this range
376 if (end > begin) BaseT::template mergeBins<axisN>({begin, end});
377 if (eshared.size() == oldAxis.edges().size()) break; // we're done
378 }
379 }
380
382 template <size_t axisN>
383 void rebin(const std::vector<typename BinningT::template getAxisT<axisN>::EdgeT>& newedges) {
384 rebinTo<axisN>(std::move(newedges));
385 }
386
390 void reset() noexcept { BaseT::clearBins(); }
391
394 if (this != &est) {
397 }
398 return *this;
399 }
400
403 if (this != &est) {
405 BaseT::operator = (std::move(est));
406 }
407 return *this;
408 }
409
415 const std::string& pat_uncorr="^stat|^uncor" ) {
416 if (*this != est)
417 throw BinningError("Arithmetic operation requires compatible binning!");
418 if (AO::hasAnnotation("ScaledBy")) AO::rmAnnotation("ScaledBy");
419 for (size_t i = 0; i< BaseT::numBins(true, true); ++i) {
420 BaseT::bin(i).add(est.bin(i), pat_uncorr);
421 }
422 BaseT::maskBins(est.maskedBins(), true);
423 return *this;
424 }
425 //
427 return add(est);
428 }
429
435 const std::string& pat_uncorr="^stat|^uncor" ) {
436 if (*this != est)
437 throw BinningError("Arithmetic operation requires compatible binning!");
438 if (AO::hasAnnotation("ScaledBy")) AO::rmAnnotation("ScaledBy");
439 for (size_t i = 0; i< BaseT::numBins(true, true); ++i) {
440 BaseT::bin(i).add(std::move(est.bin(i)), pat_uncorr);
441 }
442 BaseT::maskBins(est.maskedBins(), true);
443 return *this;
444 }
445 //
447 return add(std::move(est));
448 }
449
450
456 const std::string& pat_uncorr="^stat|^uncor" ) {
457 if (*this != est)
458 throw BinningError("Arithmetic operation requires compatible binning!");
459 if (AO::hasAnnotation("ScaledBy")) AO::rmAnnotation("ScaledBy");
460 for (size_t i = 0; i< BaseT::numBins(true, true); ++i) {
461 BaseT::bin(i).subtract(est.bin(i), pat_uncorr);
462 }
463 BaseT::maskBins(est.maskedBins(), true);
464 return *this;
465 }
466 //
468 return subtract(est);
469 }
470
473 const std::string& pat_uncorr="^stat|^uncor" ) {
474 if (*this != est)
475 throw BinningError("Arithmetic operation requires compatible binning!");
476 if (AO::hasAnnotation("ScaledBy")) AO::rmAnnotation("ScaledBy");
477 for (size_t i = 0; i< BaseT::numBins(true, true); ++i) {
478 BaseT::bin(i) -= std::move(est.bin(i), pat_uncorr);
479 }
480 BaseT::maskBins(est.maskedBins(), true);
481 return *this;
482 }
483 //
485 return subtract(std::move(est));
486 }
487
489
490
493
495 size_t dim() const noexcept { return sizeof...(AxisT) + 1; }
496
498 std::string _config() const noexcept { return mkAxisConfig<AxisT...>(); }
499
504 template <size_t I, typename E = typename BinningT::template getEdgeT<I>>
505 std::vector<E> edges(const bool includeOverflows = false) const noexcept {
506 return BaseT::_binning.template edges<I>(includeOverflows);
507 }
508
515 template <size_t I, typename E = typename BinningT::template getEdgeT<I>>
516 std::enable_if_t<std::is_floating_point<E>::value, std::vector<E>>
517 widths(const bool includeOverflows = false) const noexcept {
518 return BaseT::_binning.template widths<I>(includeOverflows);
519 }
520
524 template <size_t I, typename E = typename BinningT::template getEdgeT<I>>
525 std::enable_if_t<std::is_floating_point<E>::value, E> min() const noexcept {
526 return BaseT::_binning.template min<I>();
527 }
528
532 template <size_t I, typename E = typename BinningT::template getEdgeT<I>>
533 std::enable_if_t<std::is_floating_point<E>::value, E> max() const noexcept {
534 return BaseT::_binning.template max<I>();
535 }
536
538
539
542
544 std::vector<double> vals(const bool includeOverflows=false,
545 const bool includeMaskedBins=false) const {
546 std::vector<double> rtn;
547 rtn.reserve(BaseT::numBins(includeOverflows, includeMaskedBins));
548 for (const auto& b : BaseT::bins(includeOverflows, includeMaskedBins)) {
549 rtn.push_back(b.val());
550 }
551 return rtn;
552 }
553
555 std::vector<std::string> sources() const {
556 // Assemble union of error sources, as it's not guaranteed
557 // that every bin has the same error breakdown
558 std::vector<std::string> rtn;
559
560 for (const auto& b : BaseT::bins(true)) {
561 std::vector<std::string> keys = b.sources();
562 rtn.insert(std::end(rtn),
563 std::make_move_iterator(std::begin(keys)),
564 std::make_move_iterator(std::end(keys)));
565 }
566 std::sort(rtn.begin(), rtn.end());
567 rtn.erase( std::unique(rtn.begin(), rtn.end()), rtn.end() );
568
569 return rtn;
570 }
571
575 double areaUnderCurve(const bool includeBinVol=true,
576 const bool includeOverflows=false,
577 const bool includeMaskedBins=false) const {
578 double ret = 0.;
579 for (const auto& b : BaseT::bins(includeOverflows, includeMaskedBins)) {
580 const double val = fabs(b.val());
581 const double vol = includeBinVol? b.dVol() : 1.0;
582 if (std::isfinite(vol)) ret += val*vol; // aggregate bin volume
583 }
584 return ret;
585 }
586
588 double auc(const bool includeBinVol=true,
589 const bool includeOverflows=false,
590 const bool includeMaskedBins=false) const {
591 return areaUnderCurve(includeBinVol, includeOverflows, includeMaskedBins);
592 }
593
594
595
597 std::vector<std::vector<double> > covarianceMatrix(const bool ignoreOffDiagonalTerms=false,
598 const bool includeOverflows=false,
599 const bool includeMaskedBins=false,
600 const std::string& pat_uncorr="^stat|^uncor") const {
601 const size_t nBins = BaseT::numBins(includeOverflows,includeMaskedBins);
602 std::vector<std::vector<double> > covM(nBins);
603
604 // initialise cov matrix to be the right shape
605 for (size_t i = 0; i < nBins; ++i) {
606 covM[i] = std::vector<double>(nBins, 0.0);
607 }
608
609 const std::vector<std::string> error_sources = sources();
610
611 // nominal-only case, i.e. total uncertainty, labelled as empty string
612 if (error_sources.size() == 1 && error_sources[0] == "") {
613 size_t i = 0;
614 for (const auto& b : BaseT::bins(includeOverflows,includeMaskedBins)) {
615 covM[i][i] = b.hasSource("")? sqr(0.5*(b.err("").first+b.err("").second)) : 1.0;
616 ++i;
617 }
618 return covM;
619 }
620
621 // more interesting case where we actually have some uncertainty breakdown!
622 std::smatch match;
623 const std::regex re(pat_uncorr, std::regex_constants::icase);
624 for (const std::string& sname : error_sources) {
625 if (sname == "") continue;
626 std::vector<double> systErrs(nBins, 0.0);
627 size_t k = 0;
628 for (const auto& b : BaseT::bins(includeOverflows,includeMaskedBins)) {
629 if (b.hasSource(sname)) {
630 const auto& errs = b.err(sname); // dn-up pair
631 systErrs[k] = 0.5 *( fabs(errs.first)+fabs(errs.second));
632 }
633 ++k;
634 }
635 const bool skipOffDiag = (ignoreOffDiagonalTerms
636 || std::regex_search(sname, match, re));
637 for (size_t i = 0; i < nBins; ++i) {
638 for (size_t j = 0; j < nBins; ++j) {
639 if (skipOffDiag && i != j) continue;
640 covM[i][j] += systErrs[i]*systErrs[j];
641 }
642 }
643 }
644
645 return covM;
646 }
647
649
652
654 auto mkScatter(const std::string& path="", const std::string& pat_match = "",
655 const bool includeOverflows=false,
656 const bool includeMaskedBins=false) const {
657
658 constexpr size_t N = sizeof...(AxisT);
659
660 ScatterND<N+1> rtn;
661 for (const std::string& a : annotations()) {
662 if (a != "Type") rtn.setAnnotation(a, annotation(a));
663 }
664 rtn.setAnnotation("Path", path);
665
666 const bool incOF = all_CAxes<AxisT...>::value && includeOverflows;
667 for (const auto& b : BaseT::bins(incOF, includeMaskedBins)) {
668
669 // Create the vector of coordinates
670 Utils::ndarray<double, N+1> vals;
671 // first fill bin centres, use bin index if axis non-arithmetic
672 auto indexIfDiscrete = [&vals, &b](auto I) {
673 using isContinuous = typename BinningT::template is_CAxis<I>;
674 using isArithmetic = typename BinningT::template is_Arithmetic<I>;
675 vals[I] = coordPicker<I>(b, std::integral_constant<bool, isArithmetic::value>{},
676 std::integral_constant<bool, isContinuous::value>{});
677 };
678 MetaUtils::staticFor<BinningT::Dimension::value>(indexIfDiscrete);
679 // then fill bin content
680 vals[N] = b.val();
681
682 // Create the vector of error pairs, use 0 if axis not continuous
683 Utils::ndarray<std::pair<double,double>, N+1> errs;
684 auto nullifyDiscrete = [&errs, &vals, &b](auto I) {
685 using isContinuous = typename BinningT::template is_CAxis<I>;
686 errs[I] = nullifyIfDisc<I>(b, vals[I], std::integral_constant<bool, isContinuous::value>{});
687 };
688 MetaUtils::staticFor<BinningT::Dimension::value>(nullifyDiscrete);
689 const double tot = fabs(b.totalErrPos(pat_match)); // use positive error component
690 errs[N] = { tot, tot };
691
692 // Add the PointND
693 rtn.addPoint( PointND<N+1>(vals, errs) );
694 }
695
696 // Decorate output scatter with the discrete edges
697 const BinningT& binning = BaseT::_binning;
698 auto decorateEdges = [&rtn, &binning](auto I) {
699 using isContinuous = typename BinningT::template is_CAxis<I>;
700 if constexpr( !isContinuous::value ) {
701 const auto& axis = binning.template axis<I>();
702 if (axis.numBins()) {
703 std::stringstream ss;
704 axis._renderYODA(ss);
705 rtn.setAnnotation("EdgesA" + std::to_string(I+1), ss.str());
706 }
707 }
708 };
709 MetaUtils::staticFor<BinningT::Dimension::value>(decorateEdges);
710
711 return rtn;
712 }
713
718 template<size_t axisN, typename = std::enable_if_t< (axisN < sizeof...(AxisT) && sizeof...(AxisT)>=2) >>
719 auto mkEstimates(const std::string& path="", const bool includeOverflows=false) const {
720
721 // Need to provide a prescription for how to add the two bin contents
722 auto how2add = [](auto& pivot, const BinType& toCopy) { pivot = toCopy; };
723 auto rtn = BaseT::template mkBinnedSlices<axisN, BinnedEstimate>(how2add, includeOverflows);
724 for (const std::string& a : annotations()) {
725 if (a == "Type") continue;
726 for (size_t i = 0; i < rtn.size(); ++i) {
727 rtn[i].setAnnotation(a, annotation(a));
728 }
729 }
730 for (size_t i = 0; i < rtn.size(); ++i) {
731 rtn[i].setAnnotation("Path", path);
732 }
733
734 return rtn;
735 }
736
737
739 AnalysisObject* mkInert(const std::string& path = "",
740 const std::string& source = "") const noexcept {
741 EstimateStorage* rtn = newclone();
742 rtn->setPath(path);
743 for (auto& b : rtn->bins(true, true)) {
744 if (b.numErrs() == 1) {
745 try {
746 b.renameSource("", source);
747 }
748 catch (YODA::UserError& e) { }
749 }
750 }
751 return rtn;
752 }
753
755
757
758
759 size_t lengthContent(bool fixed_length = false) const noexcept {
760 size_t rtn = 0;
761 for (const auto& bin : BaseT::bins(true, true)) {
762 rtn += bin._lengthContent(fixed_length);
763 }
764 return rtn;
765 }
766
767 std::vector<double> serializeContent(bool fixed_length = false) const noexcept {
768 std::vector<double> rtn;
769 const size_t nBins = BaseT::numBins(true, true);
770 rtn.reserve(nBins * 4);
771 for (size_t i = 0; i < nBins; ++i) {
772 const auto& b = BaseT::bin(i);
773 std::vector<double> bdata = b._serializeContent(fixed_length);
774 rtn.insert(std::end(rtn),
775 std::make_move_iterator(std::begin(bdata)),
776 std::make_move_iterator(std::end(bdata)));
777 }
778 return rtn;
779 }
780
781
782 void deserializeContent(const std::vector<double>& data) {
783
784 const size_t nBins = BaseT::numBins(true, true);
785 const size_t minLen = 2*nBins;
786 if (data.size() < minLen)
787 throw UserError("Length of serialized data should be at least " + std::to_string(minLen)+"!");
788
789 size_t i = 0;
790 auto itr = data.cbegin();
791 const auto itrEnd = data.cend();
792 const bool fixedLen = data.size() == 2*minLen;
793 while (itr != itrEnd) {
794 // for estimates, the first element represents the central,
795 // the subsequent value represents the number of error pairs
796 const size_t nErrs = fixedLen? 1 : (*(itr + 1) + 0.5); // add 0.5 to avoid rounding issues
797 auto last = itr + 2*(nErrs+1); // last element + 1
798 BaseT::bin(i)._deserializeContent(std::vector<double>{itr, last}, fixedLen);
799 // update for next iteration
800 itr = last;
801 ++i;
802 }
803 }
804
805 // @}
806
807 private:
808
811 template<size_t... Is>
812 BinningT _mkBinning(const std::vector<size_t>& nBins,
813 const std::vector<std::pair<double, double>>& limitsLowUp,
814 std::index_sequence<Is...>) const {
815 return BinningT({((void)Is, Axis<AxisT>(nBins[Is], limitsLowUp[Is].first, limitsLowUp[Is].second))...});
816 }
817
819 template<size_t... Is>
820 BinningT _mkBinning(const ScatterND<sizeof...(AxisT)+1>& s, std::index_sequence<Is...>) const {
821 return BinningT({((void)Is, Axis<AxisT>(s.edges(Is)))...});
822 }
823
824 };
825
826
827
829 template <typename... AxisT>
830 class BinnedEstimate : public EstimateStorage<AxisT...> {
831 public:
832 using EstimateT = BinnedEstimate<AxisT...>;
833 using BaseT = EstimateStorage<AxisT...>;
834 using BinType = typename BaseT::BinT;
835 using Ptr = std::shared_ptr<EstimateT>;
836
838 using BaseT::BaseT;
839
840 BinnedEstimate(const EstimateT&) = default;
844 using AnalysisObject::operator =;
845
849 BinnedEstimate(const BaseT& other) : BaseT(other) {}
850 //
851 BinnedEstimate(const EstimateT& other, const std::string& path) : BaseT(other, path) {}
852
854 BinnedEstimate(BaseT&& other) : BaseT(std::move(other)) {}
855 //
856 BinnedEstimate(EstimateT&& other, const std::string& path) : BaseT(std::move(other), path) {}
857
858 };
859
860
862 template <typename AxisT>
863 class BinnedEstimate<AxisT>
864 : public EstimateStorage<AxisT>,
865 public XAxisMixin<BinnedEstimate<AxisT>, AxisT> {
866 public:
869 using BinType = typename BaseT::BinT;
870 using Ptr = std::shared_ptr<EstimateT>;
871
873 using BaseT::BaseT;
874
875 BinnedEstimate(const EstimateT&) = default;
879 using AnalysisObject::operator =;
880
884 BinnedEstimate(const BaseT& other) : BaseT(other) {}
885 //
886 BinnedEstimate(const EstimateT& other, const std::string& path) : BaseT(other, path) {}
887
889 BinnedEstimate(BaseT&& other) : BaseT(std::move(other)) {}
890 //
891 BinnedEstimate(EstimateT&& other, const std::string& path) : BaseT(std::move(other), path) {}
892
893
894 BinnedEstimate(std::vector<AxisT>&& edges, const std::string& path="", const std::string& title="")
895 : BaseT(std::move(edges), path, title) {}
896
897 BinnedEstimate(const std::vector<AxisT>& edges, const std::string& path="", const std::string& title="")
898 : BaseT(edges, path, title) {}
899
906 template <typename EdgeT = double, typename = enable_if_all_CAxisT<EdgeT, AxisT>>
907 BinnedEstimate(size_t nbins, double lower, double upper, const std::string& path = "", const std::string& title = "")
908 : BaseT({nbins}, {{lower, upper}}, path, title) {}
909
911 EstimateT clone() const noexcept {
912 return EstimateT(*this);
913 }
914
916 EstimateT* newclone() const noexcept {
917 return new EstimateT(*this);
918 }
919
921 size_t indexAt(const AxisT xCoord) const noexcept {
922 return BaseT::binAt( {xCoord} ).index();
923 }
924
926 void maskBinAt(const AxisT xCoord, const bool status = true) noexcept {
927 return BaseT::maskBin({xCoord}, status);
928 }
929
930 };
931
932
933
935 template <typename AxisT1, typename AxisT2>
936 class BinnedEstimate<AxisT1, AxisT2>
937 : public EstimateStorage<AxisT1, AxisT2>,
938 public XAxisMixin<BinnedEstimate<AxisT1, AxisT2>, AxisT1>,
939 public YAxisMixin<BinnedEstimate<AxisT1, AxisT2>, AxisT2> {
940 public:
943 using BinType = typename BaseT::BinT;
944 using Ptr = std::shared_ptr<EstimateT>;
945
947 using BaseT::BaseT;
948
949 BinnedEstimate(const EstimateT&) = default;
953 using AnalysisObject::operator =;
954
958 BinnedEstimate(const BaseT& other) : BaseT(std::move(other)) {}
959 //
960 BinnedEstimate(const EstimateT& other, const std::string& path) : BaseT(other, path) {}
961
963 BinnedEstimate(BaseT&& other) : BaseT(std::move(other)) {}
964 //
965 BinnedEstimate(EstimateT&& other, const std::string& path) : BaseT(std::move(other), path) {}
966
967 BinnedEstimate(std::vector<AxisT1>&& xEdges, std::vector<AxisT2>&& yEdges,
968 const std::string& path="", const std::string& title="")
969 : BaseT(std::move(xEdges), std::move(yEdges), path, title) {}
970
971 BinnedEstimate(const std::vector<AxisT1>& xEdges, const std::vector<AxisT2>& yEdges,
972 const std::string& path="", const std::string& title="")
973 : BaseT(xEdges, yEdges, path, title) {}
974
981 template <typename EdgeT = double, typename = enable_if_all_CAxisT<EdgeT, AxisT1, AxisT2>>
982 BinnedEstimate(size_t nbinsX, double lowerX, double upperX,
983 size_t nbinsY, double lowerY, double upperY,
984 const std::string& path = "", const std::string& title = "")
985 : BaseT({nbinsX, nbinsY}, {{lowerX, upperX}, {lowerY, upperY}}, path, title) {}
986
988 EstimateT clone() const noexcept {
989 return EstimateT(*this);
990 }
991
993 EstimateT* newclone() const noexcept {
994 return new EstimateT(*this);
995 }
996
998 BinType& bin(const size_t index) noexcept {
999 return BaseT::bin(index);
1000 }
1001
1003 const BinType& bin(const size_t index) const noexcept {
1004 return BaseT::bin(index);
1005 }
1006
1008 BinType& bin(const size_t localX, const size_t localY) noexcept {
1009 return BaseT::bin( {localX, localY} );
1010 }
1011
1013 const BinType& bin(const size_t localX, const size_t localY) const noexcept {
1014 return BaseT::bin( {localX, localY} );
1015 }
1016
1018 BinType& binAt(const AxisT1 xCoord, const AxisT2 yCoord) noexcept {
1019 return BaseT::binAt( {xCoord, yCoord} );
1020 }
1021
1023 const BinType& binAt(const AxisT1 xCoord, const AxisT2 yCoord) const noexcept {
1024 return BaseT::binAt( {xCoord, yCoord} );
1025 }
1026
1028 size_t indexAt(const AxisT1 xCoord, const AxisT2 yCoord) const noexcept {
1029 return BaseT::binAt( {xCoord, yCoord} ).index();
1030 }
1031
1033 void maskBinAt(const AxisT1 xCoord, const AxisT2 yCoord, const bool status = true) noexcept {
1034 return BaseT::maskBin({xCoord, yCoord}, status);
1035 }
1036
1037 };
1038
1039
1041 template <typename AxisT1, typename AxisT2, typename AxisT3>
1042 class BinnedEstimate<AxisT1, AxisT2, AxisT3>
1043 : public EstimateStorage<AxisT1, AxisT2, AxisT3>,
1044 public XAxisMixin<BinnedEstimate<AxisT1, AxisT2, AxisT3>, AxisT1>,
1045 public YAxisMixin<BinnedEstimate<AxisT1, AxisT2, AxisT3>, AxisT2>,
1046 public ZAxisMixin<BinnedEstimate<AxisT1, AxisT2, AxisT3>, AxisT3> {
1047 public:
1050 using BinType = typename BaseT::BinT;
1051 using Ptr = std::shared_ptr<EstimateT>;
1052
1054 using BaseT::BaseT;
1055
1056 BinnedEstimate(const EstimateT&) = default;
1060 using AnalysisObject::operator =;
1061
1065 BinnedEstimate(const BaseT& other) : BaseT(other) {}
1066 //
1067 BinnedEstimate(const EstimateT& other, const std::string& path) : BaseT(other, path) {}
1068
1070 BinnedEstimate(BaseT&& other) : BaseT(std::move(other)) {}
1071 //
1072 BinnedEstimate(EstimateT&& other, const std::string& path) : BaseT(std::move(other), path) {}
1073
1080 template <typename EdgeT = double, typename = enable_if_all_CAxisT<EdgeT, AxisT1, AxisT2, AxisT3>>
1081 BinnedEstimate(size_t nbinsX, double lowerX, double upperX,
1082 size_t nbinsY, double lowerY, double upperY,
1083 size_t nbinsZ, double lowerZ, double upperZ,
1084 const std::string& path = "", const std::string& title = "")
1085 : BaseT({nbinsX, nbinsY, nbinsZ}, {{lowerX, upperX}, {lowerY, upperY},
1086 {lowerZ, upperZ}}, path, title) {}
1087
1089 EstimateT clone() const noexcept {
1090 return EstimateT(*this);
1091 }
1092
1094 EstimateT* newclone() const noexcept {
1095 return new EstimateT(*this);
1096 }
1097
1099 BinType& bin(const size_t index) noexcept {
1100 return BaseT::bin(index);
1101 }
1102
1104 const BinType& bin(const size_t index) const noexcept {
1105 return BaseT::bin(index);
1106 }
1107
1109 BinType& bin(const size_t localX, const size_t localY, const size_t localZ) noexcept {
1110 return BaseT::bin( {localX, localY, localZ} );
1111 }
1112
1114 const BinType& bin(const size_t localX, const size_t localY, const size_t localZ) const noexcept {
1115 return BaseT::bin( {localX, localY, localZ} );
1116 }
1117
1119 BinType& binAt(const AxisT1 xCoord, const AxisT2 yCoord, const AxisT3 zCoord) noexcept {
1120 return BaseT::binAt( {xCoord, yCoord, zCoord} );
1121 }
1122
1124 const BinType& binAt(const AxisT1 xCoord, const AxisT2 yCoord, const AxisT3 zCoord) const noexcept {
1125 return BaseT::binAt( {xCoord, yCoord, zCoord} );
1126 }
1127
1129 size_t indexAt(const AxisT1 xCoord, const AxisT2 yCoord, const AxisT3 zCoord) const noexcept {
1130 return BaseT::binAt( {xCoord, yCoord, zCoord} ).index();
1131 }
1132
1134 void maskBinAt(const AxisT1 xCoord, const AxisT2 yCoord, const AxisT3 zCoord, const bool status = true) noexcept {
1135 return BaseT::maskBin({xCoord, yCoord, zCoord}, status);
1136 }
1137
1138 };
1139
1142
1144 template <typename... AxisT>
1145 inline BinnedEstimate<AxisT...>
1147 first += second;
1148 return first;
1149 }
1150
1151
1153 template <typename... AxisT>
1154 inline BinnedEstimate<AxisT...>
1156 first += std::move(second);
1157 return first;
1158 }
1159
1160
1162 template <typename... AxisT>
1163 inline BinnedEstimate< AxisT...>
1165 first -= second;
1166 return first;
1167 }
1168
1170 template <typename... AxisT>
1171 inline BinnedEstimate< AxisT...>
1173 first -= std::move(second);
1174 return first;
1175 }
1176
1178 template <typename... AxisT>
1179 inline BinnedEstimate<AxisT...>
1181 const std::string& pat_uncorr="^stat|^uncor" ) {
1182 if (numer != denom) {
1183 throw BinningError("Arithmetic operation requires compatible binning!");
1184 }
1185
1186 BinnedEstimate<AxisT...> rtn(numer.binning());
1187 if (numer.path() == denom.path()) rtn.setPath(numer.path());
1188 if (rtn.hasAnnotation("ScaledBy")) rtn.rmAnnotation("ScaledBy");
1189
1190 for (const auto& b_num : numer.bins(true, true)) {
1191 const size_t idx = b_num.index();
1192 rtn.bin(idx) = divide(b_num, denom.bin(idx), pat_uncorr);
1193 }
1194 rtn.maskBins(denom.maskedBins(), true);
1195
1196 return rtn;
1197 }
1198
1200 template <typename... AxisT>
1201 inline BinnedEstimate<AxisT...>
1203 return divide(numer, denom);
1204 }
1205
1207 template <typename... AxisT>
1208 inline BinnedEstimate<AxisT...>
1210 return divide(std::move(numer), denom);
1211 }
1212
1214 template <typename... AxisT>
1215 inline BinnedEstimate<AxisT...>
1217 return divide(numer, std::move(denom));
1218 }
1219
1221 template <typename... AxisT>
1222 inline BinnedEstimate<AxisT...>
1224 return divide(std::move(numer), std::move(denom));
1225 }
1226
1227
1232 template <typename... AxisT>
1233 inline BinnedEstimate<AxisT...>
1235 const std::string& pat_uncorr="^stat|^uncor" ) {
1236
1237 if (accepted != total) {
1238 throw BinningError("Arithmetic operation requires compatible binning!");
1239 }
1240
1241 BinnedEstimate<AxisT...> rtn(accepted.binning());
1242
1243 for (const auto& b_acc : accepted.bins(true, true)) {
1244 Estimate est;
1245 const size_t idx = b_acc.index();
1246 try {
1247 est = efficiency(b_acc, total.bin(idx), pat_uncorr);
1248 } catch (const UserError& e) {
1249 //
1250 }
1251 rtn.bin(idx).set(est);
1252 }
1253 return rtn;
1254 }
1255
1256
1258 template <typename... AxisT>
1259 inline BinnedEstimate<AxisT...>
1261 const BinnedEstimate<AxisT...>& b,
1262 const std::string& pat_uncorr="^stat|^uncor" ) {
1263 return divde(subtract(a-b, pat_uncorr), add(a+b, pat_uncorr), pat_uncorr);
1264 }
1265
1266
1268
1269
1272
1273 template <typename... AxisT>
1274 inline void transform(BinnedEstimate<AxisT...>& est, const Trf<1>& fn) {
1275 for (auto& b : est.bins(true, true)) {
1276 b.transform(fn);
1277 }
1278 }
1279
1280 template <typename... AxisT, typename FN>
1281 inline void transform(BinnedEstimate<AxisT...>& est, const FN& fn) {
1282 transform(est, Trf<1>(fn));
1283 }
1284
1286
1287
1290
1292 template<typename A1>
1294
1295 template <typename A1, typename A2>
1297
1298 template <typename A1, typename A2, typename A3>
1300
1302 namespace {
1303 template <class T>
1304 struct EstimateMaker;
1305
1306 template<size_t... Is>
1307 struct EstimateMaker<std::index_sequence<Is...>> {
1309 };
1310 }
1311
1312 template<size_t N>
1313 using EstimateND = typename EstimateMaker<std::make_index_sequence<N>>::type;
1314
1315
1316 // User-friendly names (continuous axes only)
1320
1322
1323}
1324
1325#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< 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.
auto mkScatter(const std::string &path="", const std::string &pat_match="", const bool includeOverflows=false, const bool includeMaskedBins=false) const
Produce a ScatterND from a EstimateStorage.
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.
std::vector< std::vector< double > > covarianceMatrix(const bool ignoreOffDiagonalTerms=false, const bool includeOverflows=false, const bool includeMaskedBins=false, const std::string &pat_uncorr="^stat|^uncor") const
Construct a covariance matrix from the error breakdown.
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.
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:153
ScatterND< N > & addPoint(const PointND< N > &pt)
Insert a new point.
Definition Scatter.h:378
Error for problems introduced outside YODA, to put it nicely.
Definition Exceptions.h:86
constexpr void staticFor(Func &&f)
Used to apply functor on tuple. Calls lambda with integral constant, which can be used to query tuple...
Definition MetaUtils.h:35
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:1142
BinnedEstimate< AxisT... > operator/(const BinnedDbn< DbnN, AxisT... > &numer, const BinnedDbn< DbnN, AxisT... > &denom)
Definition BinnedDbn.h:1215
BinnedEstimate< double, double, double > Estimate3D
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:1244
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:1278
BinnedEstimate< AxisT... > add(const BinnedDbn< DbnN, AxisT... > &dbn, const BinnedEstimate< AxisT... > &est)
Calculate the addition of a BinnedDbn with a BinnedEstimate.
Definition BinnedDbn.h:1347
BinnedEstimate< AxisT... > subtract(const BinnedDbn< DbnN, AxisT... > &dbn, const BinnedEstimate< AxisT... > &est)
Calculate the subtraction of a BinnedEstimate from a BinnedDbn.
Definition BinnedDbn.h:1379
BinnedDbn< DbnN, AxisT... > operator-(BinnedDbn< DbnN, AxisT... > first, BinnedDbn< DbnN, AxisT... > &&second)
Subtract one BinnedDbn object from another.
Definition BinnedDbn.h:1158
BinnedEstimate< AxisT... > divide(const BinnedDbn< DbnN, AxisT... > &numer, const BinnedDbn< DbnN, AxisT... > &denom)
Divide two BinnedDbn objects.
Definition BinnedDbn.h:1174
BinnedEstimate< double, double > Estimate2D
BinnedEstimate< A1, A2 > BinnedEstimate2D
BinnedEstimate< A1 > BinnedEstimate1D
Define dimension-specific short-hands (Cython sugar)
BinnedEstimate< A1, A2, A3 > BinnedEstimate3D
BinnedEstimate< double > Estimate1D
static const char * name()
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.