yoda is hosted by Hepforge, IPPP Durham
YODA - Yet more Objects for Data Analysis 2.0.2
BinnedDbn.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-2024 The YODA collaboration (see AUTHORS for details)
5//
6#ifndef YODA_BinnedDbn_h
7#define YODA_BinnedDbn_h
8
10#include "YODA/Fillable.h"
12#include "YODA/Dbn.h"
13#include "YODA/BinnedEstimate.h"
14#include "YODA/Scatter.h"
15
16#include <memory>
17#include <utility>
18#include <iostream>
19#include <iomanip>
20
21namespace YODA {
22
24 /*
39 */
43
44
45 template <size_t DbnN, typename... AxisT>
46 class DbnStorage;
47
49 template <size_t DbnN, typename... AxisT>
50 class BinnedDbn : public DbnStorage<DbnN, AxisT...> {
51 public:
52 using HistoT = BinnedDbn<DbnN, AxisT...>;
53 using BaseT = DbnStorage<DbnN, AxisT...>;
54 using FillType = typename BaseT::FillType;
55 using BinType = typename BaseT::BinT;
56 using Ptr = std::shared_ptr<HistoT>;
57
59 using BaseT::BaseT;
60
61 BinnedDbn() = default;
62 BinnedDbn(const HistoT&) = default;
63 BinnedDbn(HistoT&&) = default;
64 BinnedDbn& operator =(const HistoT&) = default;
66 using AnalysisObject::operator =;
67
71 BinnedDbn(const BaseT& other) : BaseT(other) {}
72 //
73 BinnedDbn(const HistoT& other, const std::string& path) : BaseT(other, path) {}
74
76 BinnedDbn(BaseT&& other) : BaseT(std::move(other)) {}
77 //
78 BinnedDbn(HistoT&& other, const std::string& path) : BaseT(std::move(other), path) {}
79
81 HistoT clone() const noexcept {
82 return HistoT(*this);
83 }
84
86 HistoT* newclone() const noexcept {
87 return new HistoT(*this);
88 }
89
90 };
91
92
95
96 template <typename... AxisTypes>
97 using BinnedHisto = BinnedDbn<sizeof...(AxisTypes), AxisTypes...>;
98
99 template <typename... AxisTypes>
100 using BinnedProfile = BinnedDbn<sizeof...(AxisTypes)+1, AxisTypes...>;
101
103
104
114 template <size_t DbnN, typename... AxisT>
115 class DbnStorage : public FillableStorage<DbnN, Dbn<DbnN>, AxisT...>,
116 public AnalysisObject, public Fillable {
117 public:
118
120 using BinningT = typename BaseT::BinningT;
121 using BinT = typename BaseT::BinT;
122 using BinType = typename BaseT::BinT;
123 using FillType = typename BaseT::FillType;
124 using AnalysisObject::operator =;
125
128
133 DbnStorage() : BaseT(), AnalysisObject(mkTypeString<DbnN, AxisT...>(), "") { }
134
140 DbnStorage(std::vector<AxisT>&&... binsEdges,
141 const std::string& path = "", const std::string& title = "")
142 : BaseT(Axis<AxisT>(std::move(binsEdges))...),
143 AnalysisObject(mkTypeString<DbnN, AxisT...>(), path, title) { }
144
150 DbnStorage(const std::vector<AxisT>&... binsEdges,
151 const std::string& path = "", const std::string& title = "")
152 : BaseT(Axis<AxisT>(binsEdges)...),
153 AnalysisObject(mkTypeString<DbnN, AxisT...>(), path, title) { }
154
160 DbnStorage(std::initializer_list<AxisT>&&... binsEdges,
161 const std::string& path = "", const std::string& title = "")
162 : BaseT(Axis<AxisT>(std::move(binsEdges))...),
163 AnalysisObject(mkTypeString<DbnN, AxisT...>(), path, title) { }
164
169 template <typename EdgeT = double, typename = enable_if_all_CAxisT<EdgeT, AxisT...>>
170 DbnStorage(const std::vector<size_t>& nBins, const std::vector<std::pair<EdgeT, EdgeT>>& limitsLowUp,
171 const std::string& path = "", const std::string& title = "")
172 : BaseT( _mkBinning(nBins, limitsLowUp, std::make_index_sequence<sizeof...(AxisT)>{}) ),
173 AnalysisObject(mkTypeString<DbnN, AxisT...>(), path, title) { }
174
176 DbnStorage(const Axis<AxisT>&... axes, const std::string& path = "", const std::string& title = "")
177 : BaseT(axes...), AnalysisObject(mkTypeString<DbnN, AxisT...>(), path, title) { }
178
180 DbnStorage(Axis<AxisT>&&... axes, const std::string& path = "", const std::string& title = "")
181 : BaseT(std::move(axes)...), AnalysisObject(mkTypeString<DbnN, AxisT...>(), path, title) { }
182
184 DbnStorage(const BinningT& binning, const std::string& path = "", const std::string& title = "")
185 : BaseT(binning), AnalysisObject(mkTypeString<DbnN, AxisT...>(), path, title) { }
186
188 DbnStorage(BinningT&& binning, const std::string& path = "", const std::string& title = "")
189 : BaseT(std::move(binning)), AnalysisObject(mkTypeString<DbnN, AxisT...>(), path, title) { }
190
192 template <typename EdgeT = double, typename = enable_if_all_CAxisT<EdgeT, AxisT...>>
193 DbnStorage(const ScatterND<sizeof...(AxisT)+1>& s, const std::string& path = "", const std::string& title = "")
194 : BaseT(_mkBinning(s, std::make_index_sequence<sizeof...(AxisT)>{})),
195 AnalysisObject(mkTypeString<DbnN, AxisT...>(), path, title) { }
196
200 DbnStorage(const DbnStorage& other, const std::string& path = "") : BaseT(other),
201 AnalysisObject(mkTypeString<DbnN, AxisT...>(), path!=""? path : other.path(), other, other.title()) { }
202
206 DbnStorage(DbnStorage&& other, const std::string& path = "") : BaseT(std::move(other)),
207 AnalysisObject(mkTypeString<DbnN, AxisT...>(), path!=""? path : other.path(), other, other.title()) { }
208
210 DbnStorage clone() const noexcept {
211 return DbnStorage(*this);
212 }
213
215 DbnStorage* newclone() const noexcept {
216 return new DbnStorage(*this);
217 }
218
220
221
224
229 virtual int fill(FillType&& coords, const double weight = 1.0, const double fraction = 1.0) {
230 return BaseT::fill(std::move(coords), std::make_index_sequence<sizeof...(AxisT)>{}, weight, fraction);
231 }
232
234 void scaleW(const double scalefactor) noexcept {
235 setAnnotation("ScaledBy", annotation<double>("ScaledBy", 1.0) * scalefactor);
236 for (auto& bin : BaseT::_bins) {
237 bin.scaleW(scalefactor);
238 }
239 }
240
242 void scale(const size_t i, const double scalefactor) noexcept {
243 setAnnotation("ScaledBy", annotation<double>("ScaledBy", 1.0) * scalefactor);
244 for (auto& bin : BaseT::_bins) {
245 bin.scale(i, scalefactor);
246 }
247 }
248
249
255 void normalize(const double normto=1.0, const bool includeOverflows=true) {
256 const double oldintegral = integral(includeOverflows);
257 if (oldintegral == 0) throw WeightError("Attempted to normalize a histogram with null area");
258 scaleW(normto / oldintegral);
259 }
260
261
270 template <size_t axisN>
271 void rebinBy(unsigned int n, size_t begin=1, size_t end=UINT_MAX) {
272 if (n < 1) throw UserError("Rebinning requested in groups of 0!");
273 if (!begin) throw UserError("Visible bins start with index 1!");
274 if (end > BaseT::numBinsAt(axisN)+1) end = BaseT::numBinsAt(axisN) + 1;
275 for (size_t m = begin; m < end; ++m) {
276 if (m > BaseT::numBinsAt(axisN)+1) break; // nothing to be done
277 const size_t myend = (m+n-1 < BaseT::numBinsAt(axisN)+1) ? m+n-1 : BaseT::numBinsAt(axisN);
278 if (myend > m) {
279 BaseT::template mergeBins<axisN>({m, myend});
280 end -= myend-m; //< reduce upper index by the number of removed bins
281 }
282 }
283 }
284
286 template <size_t axisN>
287 void rebin(unsigned int n, size_t begin=1, size_t end=UINT_MAX) {
288 rebinBy<axisN>(n, begin, end);
289 }
290
292 template <size_t axisN>
293 void rebinTo(const std::vector<typename BinningT::template getAxisT<axisN>::EdgeT>& newedges) {
294 if (newedges.size() < 2)
295 throw UserError("Requested rebinning to an edge list which defines no bins");
296 using thisAxisT = typename BinningT::template getAxisT<axisN>;
297 using thisEdgeT = typename thisAxisT::EdgeT;
298 // get list of shared edges
299 thisAxisT& oldAxis = BaseT::_binning.template axis<axisN>();
300 const thisAxisT newAxis(newedges);
301 const std::vector<thisEdgeT> eshared = oldAxis.sharedEdges(newAxis);
302 if (eshared.size() != newAxis.edges().size())
303 throw BinningError("Requested rebinning to incompatible edges");
304 // loop over new lower bin edges (= first bin index of merge range)
305 for (size_t begin = 0; begin < eshared.size() - 1; ++begin) {
306 // find index of upper edge along old axis
307 // (subtracting 1 gives index of last bin to be merged)
308 size_t end = oldAxis.index(eshared[begin+1]) - 1;
309 // if the current edge is the last visible edge before the overflow
310 // merge the remaining bins into the overflow
311 if (begin == newAxis.numBins(true)-1) end = oldAxis.numBins(true)-1;
312 // merge this range
313 if (end > begin) BaseT::template mergeBins<axisN>({begin, end});
314 if (eshared.size() == oldAxis.edges().size()) break; // we're done
315 }
316 }
317
319 template <size_t axisN>
320 void rebin(const std::vector<typename BinningT::template getAxisT<axisN>::EdgeT>& newedges) {
321 rebinTo<axisN>(newedges);
322 }
323
325 DbnStorage& operator = (const DbnStorage& dbn) noexcept {
326 if (this != &dbn) {
329 }
330 return *this;
331 }
332
335 if (this != &dbn) {
337 BaseT::operator = (std::move(dbn));
338 }
339 return *this;
340 }
341
342
350 if (*this != dbn)
351 throw BinningError("Arithmetic operation requires compatible binning!");
352 if (AO::hasAnnotation("ScaledBy")) AO::rmAnnotation("ScaledBy");
353 for (size_t i = 0; i < BaseT::numBins(true, true); ++i) {
354 BaseT::bin(i) += dbn.bin(i);
355 }
356 BaseT::maskBins(dbn.maskedBins(), true);
357 return *this;
358 }
359 //
361 if (*this != dbn)
362 throw BinningError("Arithmetic operation requires compatible binning!");
363 if (AO::hasAnnotation("ScaledBy")) AO::rmAnnotation("ScaledBy");
364 for (size_t i = 0; i < BaseT::numBins(true, true); ++i) {
365 BaseT::bin(i) += std::move(dbn.bin(i));
366 }
367 BaseT::maskBins(dbn.maskedBins(), true);
368 return *this;
369 }
370
371
377 if (*this != dbn)
378 throw BinningError("Arithmetic operation requires compatible binning!");
379 if (AO::hasAnnotation("ScaledBy")) AO::rmAnnotation("ScaledBy");
380 for (size_t i = 0; i < BaseT::numBins(true, true); ++i) {
381 BaseT::bin(i) -= dbn.bin(i);
382 }
383 BaseT::maskBins(dbn.maskedBins(), true);
384 return *this;
385 }
386 //
388 if (*this != dbn)
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) -= std::move(dbn.bin(i));
393 }
394 BaseT::maskBins(dbn.maskedBins(), true);
395 return *this;
396 }
397
399
402
406 void reset() noexcept { BaseT::reset(); }
407
409
410
413
414 size_t fillDim() const noexcept { return BaseT::fillDim(); }
415
417 size_t dim() const noexcept { return sizeof...(AxisT) + 1; }
418
420 std::string _config() const noexcept { return mkAxisConfig<AxisT...>(); }
421
423 template <size_t I, typename E = typename BinningT::template getEdgeT<I>>
424 std::vector<E> edges(const bool includeOverflows = false) const noexcept {
425 return BaseT::_binning.template edges<I>(includeOverflows);
426 }
427
434 template <size_t I, typename E = typename BinningT::template getEdgeT<I>>
435 std::enable_if_t<std::is_floating_point<E>::value, std::vector<E>>
436 widths(const bool includeOverflows = false) const noexcept {
437 return BaseT::_binning.template widths<I>(includeOverflows);
438 }
439
443 template <size_t I, typename E = typename BinningT::template getEdgeT<I>>
444 std::enable_if_t<std::is_floating_point<E>::value, E> min() const noexcept {
445 return BaseT::_binning.template min<I>();
446 }
447
451 template <size_t I, typename E = typename BinningT::template getEdgeT<I>>
452 std::enable_if_t<std::is_floating_point<E>::value, E> max() const noexcept {
453 return BaseT::_binning.template max<I>();
454 }
455
457
458
461
463 double integral(const bool includeOverflows=true) const noexcept {
464 return sumW(includeOverflows);
465 }
466
468 double integralError(const bool includeOverflows=true) const noexcept {
469 return sqrt(sumW2(includeOverflows));
470 }
471
473 double integralTo(const size_t binIndex) const noexcept {
474 return integralRange(0, binIndex);
475 }
476
479 double integralRange(const size_t binIndex1, size_t binIndex2) const {
480 assert(binIndex2 >= binIndex1);
481 if (binIndex1 >= BaseT::numBins(true)) throw RangeError("binindex1 is out of range");
482 if (binIndex2 >= BaseT::numBins(true)) throw RangeError("binindex2 is out of range");
483 double sumw = 0;
484 for (size_t idx = binIndex1; idx <= binIndex2; ++idx) {
485 if (BaseT::bin(idx).isMasked()) continue;
486 sumw += BaseT::bin(idx).sumW();
487 }
488 return sumw;
489 }
490
493 double integralRangeError(const size_t binIndex1, size_t binIndex2) const {
494 assert(binIndex2 >= binIndex1);
495 if (binIndex1 >= BaseT::numBins(true)) throw RangeError("binindex1 is out of range");
496 if (binIndex2 >= BaseT::numBins(true)) throw RangeError("binindex2 is out of range");
497 double sumw2 = 0;
498 for (size_t idx = binIndex1; idx <= binIndex2; ++idx) {
499 if (BaseT::bin(idx).isMasked()) continue;
500 sumw2 += BaseT::bin(idx).sumW2();
501 }
502 return sumw2;
503 }
504
506 double numEntries(const bool includeOverflows=true) const noexcept {
507 double n = 0;
508 for (const auto& b : BaseT::bins(includeOverflows))
509 n += b.numEntries();
510 return n;
511 }
512
514 double effNumEntries(const bool includeOverflows=true) const noexcept {
515 double n = 0;
516 for (const auto& b : BaseT::bins(includeOverflows))
517 n += b.effNumEntries();
518 return n;
519 }
520
522 double sumW(const bool includeOverflows=true) const noexcept {
523 double sumw = 0;
524 for (const auto& b : BaseT::bins(includeOverflows))
525 sumw += b.sumW();
526 return sumw;
527 }
528
530 double sumW2(const bool includeOverflows=true) const noexcept {
531 double sumw2 = 0;
532 for (const auto& b : BaseT::bins(includeOverflows))
533 sumw2 += b.sumW2();
534 return sumw2;
535 }
536
538 double sumWA(const size_t dim, const bool includeOverflows=true) const {
539 if (dim >= DbnN) throw RangeError("Invalid axis int, must be in range 0..dim-1");
540 double sumwa = 0;
541 for (const auto& b : BaseT::bins(includeOverflows))
542 sumwa += b.sumW(dim+1);
543 return sumwa;
544 }
545
547 double sumWA2(const size_t dim, const bool includeOverflows=true) const {
548 if (dim >= DbnN) throw RangeError("Invalid axis int, must be in range 0..dim-1");
549 double sumwa2 = 0;
550 for (const auto& b : BaseT::bins(includeOverflows))
551 sumwa2 += b.sumW2(dim+1);
552 return sumwa2;
553 }
554
556 template<size_t dim = DbnN, typename = std::enable_if_t<(dim >= 2)>>
557 double crossTerm(const size_t A1, const size_t A2, const bool includeOverflows=true) const {
558 if (A1 >= DbnN || A2 >= DbnN) throw RangeError("Invalid axis int, must be in range 0..dim-1");
559 if (A1 >= A2) throw RangeError("Indices need to be different for cross term");
560 double sumw = 0;
561 for (const auto& b : BaseT::bins(includeOverflows))
562 sumw += b.crossTerm(A1, A2);
563 return sumw;
564 }
565
567 double mean(size_t axisN, const bool includeOverflows=true) const noexcept {
568 Dbn<DbnN> dbn;
569 for (const auto& b : BaseT::bins(includeOverflows))
570 dbn += b;
571 return dbn.mean(axisN+1);
572 }
573
575 double variance(size_t axisN, const bool includeOverflows=true) const noexcept {
576 Dbn<DbnN> dbn;
577 for (const auto& b : BaseT::bins(includeOverflows))
578 dbn += b;
579 return dbn.variance(axisN+1);
580 }
581
583 double stdDev(size_t axisN, const bool includeOverflows=true) const noexcept {
584 return std::sqrt(variance(axisN, includeOverflows));
585 }
586
588 double stdErr(size_t axisN, const bool includeOverflows=true) const noexcept {
589 Dbn<DbnN> dbn;
590 for (const auto& b : BaseT::bins(includeOverflows))
591 dbn += b;
592 return dbn.stdErr(axisN+1);
593 }
594
596 double rms(size_t axisN, const bool includeOverflows=true) const noexcept {
597 Dbn<DbnN> dbn;
598 for (const auto& b : BaseT::bins(includeOverflows))
599 dbn += b;
600 return dbn.RMS(axisN+1);
601 }
602
603 double dVol(const bool includeOverflows=true) const noexcept {
604 double vol = 0.0;
605 for (const auto& b : BaseT::bins(includeOverflows))
606 vol += b.dVol();
607 return vol;
608 }
609
611 double density(const bool includeOverflows=true) const noexcept {
612 const double vol = dVol(includeOverflows);
613 if (vol) return integral(includeOverflows) / vol;
614 return std::numeric_limits<double>::quiet_NaN();
615 }
616
618 double densityError(const bool includeOverflows=true) const noexcept {
619 const double vol = dVol(includeOverflows);
620 if (vol) return integralError(includeOverflows) / vol;
621 return std::numeric_limits<double>::quiet_NaN();
622 }
623
625 double densitySum(const bool includeOverflows=true) const noexcept {
626 double rho = 0.0;
627 for (const auto& b : BaseT::bins(includeOverflows))
628 rho += b.sumW() / b.dVol();
629 return rho;
630 }
631
633 double maxDensity(const bool includeOverflows=true) const noexcept {
634 std::vector<double> vals;
635 for (auto& b : BaseT::bins(includeOverflows))
636 vals.emplace_back(b.sumW() / b.dVol());
637 return *max_element(vals.begin(), vals.end());
638 }
639
641
644
645 private:
646
647 // @brief Render information about this AO (private implementation)
648 template<size_t... Is>
649 void _renderYODA_aux(std::ostream& os, const int width, std::index_sequence<Is...>) const noexcept {
650
651 // YODA1-style metadata
652 if ( effNumEntries(true) > 0 ) {
653 os << "# Mean: ";
654 if (DbnN > 1) { os << "("; }
655 (( os << std::string(Is? ", " : "") << mean(Is, true)), ...);
656 if (DbnN > 1) { os << ")"; }
657 os << "\n# Integral: " << integral(true) << "\n";
658 }
659
660 // render bin edges
661 BaseT::_binning._renderYODA(os);
662
663 // column header: content types
664 os << std::setw(width) << std::left << "# sumW" << "\t";
665 os << std::setw(width) << std::left << "sumW2" << "\t";
666 (( os << std::setw(width) << std::left << ("sumW(A" + std::to_string(Is+1) + ")") << "\t"
667 << std::setw(width) << std::left << ("sumW2(A" + std::to_string(Is+1) + ")") << "\t"), ...);
668 if constexpr (DbnN >= 2) {
669 for (size_t i = 0; i < (DbnN-1); ++i) {
670 for (size_t j = i+1; j < DbnN; ++j) {
671 const std::string scross = "sumW(A" + std::to_string(i+1) + ",A" + std::to_string(j+1) + ")";
672 os << std::setw(width) << std::left << scross << "\t";
673 }
674 }
675 }
676 os << "numEntries\n";
677 // now write one row per bin
678 for (const auto& b : BaseT::bins(true, true)) {
679 os << std::setw(width) << std::left << b.sumW() << "\t"; // renders sumW
680 os << std::setw(width) << std::left << b.sumW2() << "\t"; // renders sumW2
681 ((os << std::setw(width) << std::left << b.sumW( Is+1) << "\t"
682 << std::setw(width) << std::left << b.sumW2(Is+1) << "\t"), ...); // renders first moments
683 if constexpr (DbnN >= 2) {
684 for (size_t i = 0; i < (DbnN-1); ++i) {
685 for (size_t j = i+1; j < DbnN; ++j) {
686 os << std::setw(width) << std::left << b.crossTerm(i,j) << "\t";
687 }
688 }
689 }
690 os << std::setw(width) << std::left << b.numEntries() << "\n"; // renders raw event count
691 }
692 }
693
694 public:
695
696 // @brief Render information about this AO (public API)
697 void _renderYODA(std::ostream& os, const int width = 13) const noexcept {
698 _renderYODA_aux(os, width, std::make_index_sequence<DbnN>{});
699 }
700
701 // @brief Render scatter-like information about this AO
702 void _renderFLAT(std::ostream& os, const int width = 13) const noexcept {
703 const ScatterND<sizeof...(AxisT)+1> tmp = mkScatter();
704 tmp._renderYODA(os, width);
705 }
706
708
710
711
712 size_t lengthContent(bool = false) const noexcept {
713 return BaseT::numBins(true, true) * Dbn<DbnN>::DataSize::value;
714 }
715
716 std::vector<double> serializeContent(bool = false) const noexcept {
717 std::vector<double> rtn;
718 const size_t nBins = BaseT::numBins(true, true);
719 rtn.reserve(nBins * Dbn<DbnN>::DataSize::value);
720 for (size_t i = 0; i < nBins; ++i) {
721 std::vector<double> bdata = BaseT::bin(i)._serializeContent();
722 rtn.insert(std::end(rtn),
723 std::make_move_iterator(std::begin(bdata)),
724 std::make_move_iterator(std::end(bdata)));
725 }
726 return rtn;
727 }
728
729 void deserializeContent(const std::vector<double>& data) {
730
731 constexpr size_t dbnSize = Dbn<DbnN>::DataSize::value;
732 const size_t nBins = BaseT::numBins(true, true);
733 if (data.size() != nBins * dbnSize)
734 throw UserError("Length of serialized data should be "
735 + std::to_string(nBins * dbnSize)+"!");
736
737 const auto itr = data.cbegin();
738 for (size_t i = 0; i < nBins; ++i) {
739 auto first = itr + i*dbnSize;
740 auto last = first + dbnSize;
741 BaseT::bin(i)._deserializeContent(std::vector<double>{first, last});
742 }
743
744 }
745
746 // @}
747
750
754 BinnedEstimate<AxisT...> mkEstimate(const std::string& path="",
755 const std::string& source = "",
756 [[maybe_unused]] const bool divbyvol=true) const {
757
758 // @todo Should we check BaseT::nanCount() and report?
759 BinnedEstimate<AxisT...> rtn(BaseT::_binning);
760 for (const std::string& a : annotations()) {
761 if (a != "Type") rtn.setAnnotation(a, annotation(a));
762 }
763 rtn.setAnnotation("Path", path);
764
765 if (BaseT::nanCount()) {
766 const double nanc = BaseT::nanCount();
767 const double nanw = BaseT::nanSumW();
768 const double frac = nanc / (nanc + numEntries());
769 const double wtot = nanw + effNumEntries();
770 rtn.setAnnotation("NanFraction", frac);
771 if (wtot) rtn.setAnnotation("WeightedNanFraction", nanw/wtot);
772 }
773
774 for (const auto& b : BaseT::bins(true, true)) {
775 if (!b.isVisible()) continue;
776 if constexpr(DbnN > sizeof...(AxisT)) {
777 rtn.bin(b.index()).setVal(b.mean(DbnN));
778 if (b.numEntries()) { // only set uncertainty for filled Dbns
779 rtn.bin(b.index()).setErr(b.stdErr(DbnN), source);
780 }
781 }
782 else {
783 const double scale = divbyvol? b.dVol() : 1.0;
784 rtn.bin(b.index()).setVal(b.sumW() / scale);
785 if (b.numEntries()) { // only set uncertainty for filled Dbns
786 rtn.bin(b.index()).setErr(b.errW() / scale, source);
787 }
788 }
789 }
790
791 return rtn;
792 }
793
798 template<size_t axisN, typename = std::enable_if_t< (axisN < sizeof...(AxisT)) >>
799 auto mkEstimates(const std::string& path="", const std::string source = "",
800 const bool divbyvol=true, const bool includeOverflows=false) {
801
802 BinnedEstimate<AxisT...> est = mkEstimate(path, source, divbyvol);
803 return est.template mkEstimates<axisN>(path, includeOverflows);
804 }
805
806
808 auto mkScatter(const std::string& path="", const bool divbyvol=true,
809 const bool usefocus=false,
810 const bool includeOverflows=false,
811 const bool includeMaskedBins=false) const {
812 const BinnedEstimate<AxisT...> est = mkEstimate("", "", divbyvol);
813 ScatterND<sizeof...(AxisT)+1> rtn = est.mkScatter(path, "", includeOverflows, includeMaskedBins);
814 if (usefocus) {
815 size_t idx = 0;
816 for (const auto& b : BaseT::bins(includeOverflows, includeMaskedBins)) {
817 auto shiftIfContinuous = [&rtn, &b, &idx](auto I) {
818 using isContinuous = typename BinningT::template is_CAxis<I>;
819 if constexpr (isContinuous::value) {
820 const double oldMax = rtn.point(idx).max(I);
821 const double oldMin = rtn.point(idx).min(I);
822 const double newVal = b.mean(I+1);
823 rtn.point(idx).set(I, newVal, newVal - oldMin, oldMax - newVal);
824 }
825 };
826 MetaUtils::staticFor<BinningT::Dimension::value>(shiftIfContinuous);
827 ++idx;
828 }
829 }
830 return rtn;
831 }
832
837 template<size_t N = DbnN, typename = std::enable_if_t< (N == sizeof...(AxisT)+1) >>
838 BinnedHisto<AxisT...> mkHisto(const std::string& path="") const {
839
840 BinnedHisto<AxisT...> rtn(BaseT::_binning);
841 rtn.setNanLog(BaseT::nanCount(), BaseT::nanSumW(), BaseT::nanSumW2());
842 for (const std::string& a : annotations()) {
843 if (a != "Type") rtn.setAnnotation(a, annotation(a));
844 }
845 rtn.setAnnotation("Path", path);
846
847 for (const auto& b : BaseT::bins(true)) {
848 rtn.bin(b.index()) += b.template reduce<N-1>();
849 }
850
851 return rtn;
852 }
853
865 template<size_t axisN, typename = std::enable_if_t< (axisN < sizeof...(AxisT)) >>
866 auto mkMarginalProfile(const std::string& path="") const {
867
868 auto rtn = BaseT::template _mkBinnedT<BinnedProfile>(BaseT::_binning.template _getAxesExcept<axisN>());
869 rtn.setNanLog(BaseT::nanCount(), BaseT::nanSumW(), BaseT::nanSumW2());
870 for (const std::string& a : annotations()) {
871 if (a != "Type") rtn.setAnnotation(a, annotation(a));
872 }
873 rtn.setAnnotation("Path", path);
874
875 auto collapseStorageBins =
876 [&oldBinning = BaseT::_binning, &oldBins = BaseT::_bins, &rtn](auto I, auto dbnRed) {
877
878 auto collapse = [&oldBins, &rtn](const auto& binsIndicesToMerge, auto axis) {
879 assert(rtn.numBins(true) == binsIndicesToMerge.size());
880
881 // for any given pivot, add the content
882 // from the old slice to the new slice
883 for (size_t i = 0; i < rtn.numBins(true); ++i) {
884 auto& pivotBin = rtn.bin(i);
885 auto& binToAppend = oldBins[binsIndicesToMerge[i]];
886 pivotBin += binToAppend.template reduce<axis>();
887 }
888 };
889
890 // get bin slice for any given bin along the axis that is to be
891 // collapsed, then copy the values into the new binning
892 ssize_t nBinRowsToBeMerged = oldBinning.numBinsAt(I);
893 while (nBinRowsToBeMerged--) {
896 collapse(oldBinning.sliceIndices(I, nBinRowsToBeMerged), dbnRed);
897 }
898 };
902 auto dbnRed = std::integral_constant<size_t, (sizeof...(AxisT) == DbnN)? DbnN : axisN>();
903 (void)collapseStorageBins(std::integral_constant<std::size_t, axisN>(), dbnRed);
904
905 return rtn;
906 }
907
919 template<size_t axisN, typename = std::enable_if_t< (axisN < sizeof...(AxisT)) >>
920 auto mkMarginalHisto(const std::string& path="") const {
921
922 if constexpr (DbnN != sizeof...(AxisT)) {
923 // Case 1: BP(N+1) -> BH(N+1) -> BHN
924 return mkHisto().template mkMarginalHisto<axisN>(path);
925 }
926 else {
927 // Case 2: BH(N+1) -> BHN
928
929 auto rtn = BaseT::template _mkBinnedT<BinnedHisto>(BaseT::_binning.template _getAxesExcept<axisN>());
930 rtn.setNanLog(BaseT::nanCount(), BaseT::nanSumW(), BaseT::nanSumW2());
931 for (const std::string& a : annotations()) {
932 if (a != "Type") rtn.setAnnotation(a, annotation(a));
933 }
934 rtn.setAnnotation("Path", path);
935
936 auto collapseStorageBins =
937 [&oldBinning = BaseT::_binning, &oldBins = BaseT::_bins, &rtn](auto I, auto dbnRed) {
938
939 auto collapse = [&oldBins, &rtn](const auto& binsIndicesToMerge, auto axis) {
940 assert(rtn.numBins(true) == binsIndicesToMerge.size());
941
942 // for any given pivot, add the content
943 // from the old slice to the new slice
944 for (size_t i = 0; i < rtn.numBins(true); ++i) {
945 auto& pivotBin = rtn.bin(i);
946 auto& binToAppend = oldBins[binsIndicesToMerge[i]];
947 pivotBin += binToAppend.template reduce<axis>();
948 }
949 };
950
951 // get bin slice for any given bin along the axis that is to be
952 // collapsed, then copy the values into the new binning
953 ssize_t nBinRowsToBeMerged = oldBinning.numBinsAt(I);
954 while (nBinRowsToBeMerged--) {
957 collapse(oldBinning.sliceIndices(I, nBinRowsToBeMerged), dbnRed);
958 }
959 };
960 // collapse Dbn along axisN
961 auto dbnRed = std::integral_constant<size_t, axisN>();
962 (void)collapseStorageBins(std::integral_constant<std::size_t, axisN>(), dbnRed);
963
964 return rtn;
965 }
966 }
967
968
973 template<size_t axisN, typename = std::enable_if_t< (axisN < sizeof...(AxisT) &&
974 sizeof...(AxisT)>=2 &&
975 DbnN > sizeof...(AxisT)) >>
976 auto mkProfiles(const std::string& path="", const bool includeOverflows=false) const {
977
978 // Need to provide a prescription for how to add the two bin contents
979 auto how2add = [](auto& pivot, const BinType& toCopy) { pivot = toCopy.template reduce<axisN>(); };
980 auto rtn = BaseT::template mkBinnedSlices<axisN, BinnedProfile>(how2add, includeOverflows);
981 for (const std::string& a : annotations()) {
982 if (a == "Type") continue;
983 for (size_t i = 0; i < rtn.size(); ++i) {
984 rtn[i].setAnnotation(a, annotation(a));
985 }
986 }
987 for (size_t i = 0; i < rtn.size(); ++i) {
988 rtn[i].setAnnotation("Path", path);
989 }
990 return rtn;
991 }
992
993
998 template<size_t axisN, typename = std::enable_if_t< (axisN < sizeof...(AxisT) && sizeof...(AxisT)>=2) >>
999 auto mkHistos(const std::string& path="", const bool includeOverflows=false) const {
1000
1001 if constexpr (DbnN != sizeof...(AxisT)) {
1002 // Case 1: BP(N+1) -> BH(N+1) -> BHN
1003 return mkHisto().template mkHistos<axisN>(path, includeOverflows);
1004 }
1005 else {
1006 // Case 2: BH(N+1) -> BHN
1007
1008 // Need to provide a prescription for how to add the two bin contents
1009 auto how2add = [](auto& pivot, const BinType& toCopy) { pivot = toCopy.template reduce<axisN>(); };
1010 auto rtn = BaseT::template mkBinnedSlices<axisN,BinnedHisto>(how2add, includeOverflows);
1011 for (const std::string& a : annotations()) {
1012 if (a == "Type") continue;
1013 for (size_t i = 0; i < rtn.size(); ++i) {
1014 rtn[i].setAnnotation(a, annotation(a));
1015 }
1016 }
1017 for (size_t i = 0; i < rtn.size(); ++i) {
1018 rtn[i].setAnnotation("Path", path);
1019 }
1020 return rtn;
1021 }
1022 }
1023
1024
1026 AnalysisObject* mkInert(const std::string& path = "",
1027 const std::string& source = "") const noexcept {
1028 return mkEstimate(path, source).newclone();
1029 }
1030
1032
1033 private:
1034
1037 template<size_t... Is>
1038 BinningT _mkBinning(const std::vector<size_t>& nBins,
1039 const std::vector<std::pair<double, double>>& limitsLowUp,
1040 std::index_sequence<Is...>) const {
1041 return BinningT({((void)Is, Axis<AxisT>(nBins[Is], limitsLowUp[Is].first, limitsLowUp[Is].second))...});
1042 }
1043
1045 template<size_t... Is>
1046 BinningT _mkBinning(const ScatterND<sizeof...(AxisT)+1>& s, std::index_sequence<Is...>) const {
1047 return BinningT(Axis<AxisT>(s.edges(Is))...);
1048 }
1049
1050 };
1051
1052
1053
1056
1058 template<size_t DbnN, typename... AxisT>
1059 inline BinnedDbn<DbnN, AxisT...>
1061 first += std::move(second);
1062 return first;
1063 }
1064 //
1065 template <size_t DbnN, typename... AxisT>
1066 inline BinnedDbn<DbnN, AxisT...>
1068 first += second;
1069 return first;
1070 }
1071
1072
1074 template <size_t DbnN, typename... AxisT>
1075 inline BinnedDbn<DbnN, AxisT...>
1077 first -= std::move(second);
1078 return first;
1079 }
1080 //
1081 template <size_t DbnN, typename... AxisT>
1082 inline BinnedDbn<DbnN, AxisT...>
1084 first -= second;
1085 return first;
1086 }
1087
1088
1090 template <size_t DbnN, typename... AxisT>
1091 inline BinnedEstimate<AxisT...>
1093
1094 if (numer != denom) {
1095 throw BinningError("Arithmetic operation requires compatible binning!");
1096 }
1097
1098 BinnedEstimate<AxisT...> rtn = numer.mkEstimate();
1099 if (numer.path() == denom.path()) rtn.setPath(numer.path());
1100 if (rtn.hasAnnotation("ScaledBy")) rtn.rmAnnotation("ScaledBy");
1101
1102 for (const auto& b_num : numer.bins(true, true)) {
1103 const size_t idx = b_num.index();
1104 const auto& b_den = denom.bin(idx);
1105 double v, e;
1106 if (!b_den.effNumEntries()) {
1107 v = std::numeric_limits<double>::quiet_NaN();
1108 e = std::numeric_limits<double>::quiet_NaN();
1109 }
1110 else {
1111 if constexpr(DbnN > sizeof...(AxisT)) {
1112 v = b_num.mean(DbnN) / b_den.mean(DbnN);
1113 const double e_num = b_num.effNumEntries()? b_num.relStdErr(DbnN) : 0;
1114 const double e_den = b_den.effNumEntries()? b_den.relStdErr(DbnN) : 0;
1115 e = fabs(v) * sqrt(sqr(e_num) + sqr(e_den));
1116 }
1117 else {
1118 v = b_num.sumW() / b_den.sumW();
1119 const double e_num = b_num.sumW()? b_num.relErrW() : 0;
1120 const double e_den = b_den.sumW()? b_den.relErrW() : 0;
1121 e = fabs(v) * sqrt(sqr(e_num) + sqr(e_den));
1122 }
1123 }
1124 rtn.bin(idx).set(v, {-e, e}); // @todo put "stats" as source?
1125 }
1126 rtn.maskBins(denom.maskedBins(), true);
1127
1128 return rtn;
1129 }
1130 //
1131 template <size_t DbnN, typename... AxisT>
1132 inline BinnedEstimate<AxisT...>
1134 return divide(numer, denom);
1135 }
1136 //
1137 template <size_t DbnN, typename... AxisT>
1138 inline BinnedEstimate<AxisT...>
1140 return divide(numer, std::move(denom));
1141 }
1142 //
1143 template <size_t DbnN, typename... AxisT>
1144 inline BinnedEstimate<AxisT...>
1146 return divide(std::move(numer), denom);
1147 }
1148 //
1149 template <size_t DbnN, typename... AxisT>
1150 inline BinnedEstimate<AxisT...>
1152 return divide(std::move(numer), std::move(denom));
1153 }
1154
1155
1160 template <size_t DbnN, typename... AxisT>
1161 inline BinnedEstimate<AxisT...>
1163
1164 if (accepted != total) {
1165 throw BinningError("Arithmetic operation requires compatible binning!");
1166 }
1167
1168 BinnedEstimate<AxisT...> rtn = divide(accepted, total);
1169
1170 for (const auto& b_acc : accepted.bins(true, true)) {
1171 const auto& b_tot = total.bin(b_acc.index());
1172 auto& b_rtn = rtn.bin(b_acc.index());
1173
1174 // Check that the numerator is consistent with being a subset of the denominator
1176 if (b_acc.numEntries() > b_tot.numEntries())
1177 throw UserError("Attempt to calculate an efficiency when the numerator is not a subset of the denominator: "
1178 + Utils::toStr(b_acc.numEntries()) + " entries / " + Utils::toStr(b_tot.numEntries()) + " entries");
1179
1180 // If no entries on the denominator, set eff = err = 0 and move to the next bin
1181 double eff = std::numeric_limits<double>::quiet_NaN();
1182 double err = std::numeric_limits<double>::quiet_NaN();
1183 try {
1184 if (b_tot.sumW()) {
1185 eff = b_rtn.val();
1186 err = sqrt(abs( ((1-2*eff)*b_acc.sumW2() + sqr(eff)*b_tot.sumW2()) / sqr(b_tot.sumW()) ));
1187 }
1188 } catch (const LowStatsError& e) {
1189 //
1190 }
1191
1192 b_rtn.setErr({-err, err}); // @todo put "stats" as source?
1193 }
1194 return rtn;
1195 }
1196
1197
1199 template <size_t DbnN, typename... AxisT>
1200 inline BinnedEstimate<AxisT...>
1202 return (a-b) / (a+b);
1203 }
1204
1205
1214 template <size_t DbnN, typename... AxisT>
1215 inline BinnedEstimate<AxisT...>
1216 mkIntegral(const BinnedDbn<DbnN, AxisT...>& histo, const bool includeOverflows = true) {
1217
1218 BinnedEstimate<AxisT...> rtn = histo.mkEstimate();
1219
1220 double sumW = 0.0, sumW2 = 0.0;
1221 for (const auto& b : histo.bins(includeOverflows)) {
1222 sumW += b.sumW();
1223 sumW2 += b.sumW2();
1224 const double e = sqrt(sumW2);
1225 rtn.bin(b.index()).set(sumW, {-e, e});
1226 }
1227
1228 return rtn;
1229 }
1230
1231
1243 template <size_t DbnN, typename... AxisT>
1244 inline BinnedEstimate<AxisT...>
1245 mkIntegralEff(const BinnedDbn<DbnN, AxisT...>& histo, const bool includeOverflows = true) {
1246
1247 BinnedEstimate<AxisT...> rtn = mkIntegral(histo, includeOverflows);
1248 const double integral = histo.integral(includeOverflows);
1249
1250 // If the integral is empty, the (integrated) efficiency values may as well all be zero, so return here
1254 if (!integral) return rtn;
1255
1256 const double integral_err = histo.integralError(includeOverflows);
1257 for (const auto& b : rtn.bins(includeOverflows)) {
1258 const double eff = b.val() / integral;
1259 const double err = sqrt(std::abs( ((1-2*eff)*sqr(b.relTotalErrAvg()) + sqr(eff)*sqr(integral_err)) / sqr(integral) ));
1260 b.set(eff, {-err,err});
1261 }
1262
1263 return rtn;
1264 }
1265
1266
1268 template <size_t DbnN, typename... AxisT>
1269 inline BinnedEstimate<AxisT...>
1271 return dbn.mkEstimate() + est;
1272 }
1273 //
1274 template <size_t DbnN, typename... AxisT>
1275 inline BinnedEstimate<AxisT...>
1277 return add(dbn, est);
1278 }
1279 //
1280 template <size_t DbnN, typename... AxisT>
1281 inline BinnedEstimate<AxisT...>
1283 return add(std::move(dbn), est);
1284 }
1285 //
1286 template <size_t DbnN, typename... AxisT>
1287 inline BinnedEstimate<AxisT...>
1289 return add(dbn, std::move(est));
1290 }
1291 //
1292 template <size_t DbnN, typename... AxisT>
1293 inline BinnedEstimate<AxisT...>
1295 return add(std::move(dbn), std::move(est));
1296 }
1297
1298
1300 template <size_t DbnN, typename... AxisT>
1301 inline BinnedEstimate<AxisT...>
1303 return dbn.mkEstimate() - est;
1304 }
1305 //
1306 template <size_t DbnN, typename... AxisT>
1307 inline BinnedEstimate<AxisT...>
1309 return subtract(dbn, est);
1310 }
1311 //
1312 template <size_t DbnN, typename... AxisT>
1313 inline BinnedEstimate<AxisT...>
1315 return subtract(std::move(dbn), est);
1316 }
1317 //
1318 template <size_t DbnN, typename... AxisT>
1319 inline BinnedEstimate<AxisT...>
1321 return subtract(dbn, std::move(est));
1322 }
1323 //
1324 template <size_t DbnN, typename... AxisT>
1325 inline BinnedEstimate<AxisT...>
1327 return subtract(std::move(dbn), std::move(est));
1328 }
1329
1330
1332 template <size_t DbnN, typename... AxisT>
1333 inline BinnedEstimate<AxisT...>
1335 return dbn.mkEstimate() / est;
1336 }
1337 //
1338 template <size_t DbnN, typename... AxisT>
1339 inline BinnedEstimate<AxisT...>
1341 return divide(dbn, est);
1342 }
1343 //
1344 template <size_t DbnN, typename... AxisT>
1345 inline BinnedEstimate<AxisT...>
1347 return divide(std::move(dbn), est);
1348 }
1349 //
1350 template <size_t DbnN, typename... AxisT>
1351 inline BinnedEstimate<AxisT...>
1353 return divide(dbn, std::move(est));
1354 }
1355 //
1356 template <size_t DbnN, typename... AxisT>
1357 inline BinnedEstimate<AxisT...>
1359 return divide(std::move(dbn), std::move(est));
1360 }
1361
1362
1371 template<size_t DbnN, typename... AxisT, typename... Args,
1372 typename = std::enable_if_t<(DbnN == sizeof...(AxisT)+1 &&
1373 (std::is_same_v<BinnedDbn<DbnN, AxisT...>, Args> && ...))>>
1374 ScatterND<sizeof...(Args)+1> zipProfiles(const BinnedDbn<DbnN, AxisT...>& p1, Args&&... others,
1375 const std::string& path = "") {
1376
1377 // Check profiles have the same binning
1378 if ( !((p1 == others) && ...) )
1379 throw BinningError("Requested zipping of profiles with incompatible binning!");
1380
1381 // Construct resulting Scatter whose coordinates
1382 // are given by the unbinned means
1383 constexpr size_t N = sizeof...(Args)+1;
1384 ScatterND<N> rtn;
1385 rtn.setAnnotation("Path", path);
1386 for (const auto& b1 : p1.bins()) {
1387 typename ScatterND<N>::NdVal vals = { b1.mean(DbnN), others.bin(b1.binIndex()).mean(DbnN) ... };
1388 typename ScatterND<N>::NdVal errs = { b1.stdErr(DbnN), others.bin(b1.binIndex()).stdErr(DbnN) ... };
1389 rtn.addPoint(vals, errs);
1390 }
1391 return rtn;
1392 }
1393
1395
1396}
1397
1398#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)
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)
virtual AnalysisObject * newclone() const =0
Make a copy on the heap, via 'new'.
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
User-facing BinnedDbn class in arbitrary dimension.
Definition BinnedDbn.h:50
typename BaseT::BinT BinType
Definition BinnedDbn.h:55
BinnedDbn< DbnN, AxisT... > HistoT
Definition BinnedDbn.h:52
HistoT * newclone() const noexcept
Make a copy on the heap.
Definition BinnedDbn.h:86
typename BaseT::FillType FillType
Definition BinnedDbn.h:54
BinnedDbn()=default
BinnedDbn(const BaseT &other)
Copy constructor (needed for clone functions).
Definition BinnedDbn.h:71
HistoT clone() const noexcept
Make a copy on the stack.
Definition BinnedDbn.h:81
BinnedDbn(const HistoT &)=default
std::shared_ptr< HistoT > Ptr
Definition BinnedDbn.h:56
BinnedDbn(HistoT &&)=default
BinnedDbn(HistoT &&other, const std::string &path)
Definition BinnedDbn.h:78
BinnedDbn(const HistoT &other, const std::string &path)
Definition BinnedDbn.h:73
BinnedDbn(BaseT &&other)
Move constructor.
Definition BinnedDbn.h:76
BinnedDbn & operator=(const HistoT &)=default
Forward declaration.
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.
bool isMasked(const size_t binIndex) const noexcept
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
Error for general binning problems.
Definition Exceptions.h:27
double RMS(const size_t i) const
Weighted RMS, , of distribution.
Definition Dbn.h:546
double mean(const size_t i) const
Weighted mean, , of distribution.
Definition Dbn.h:519
double variance(const size_t i) const
Weighted variance, , of distribution.
Definition Dbn.h:525
double stdErr(const size_t i) const
Weighted standard error on the mean, , of distribution.
Definition Dbn.h:531
All histograms can be instantiated through this alias.
Definition BinnedDbn.h:116
AnalysisObject * mkInert(const std::string &path="", const std::string &source="") const noexcept
Return an inert version of the analysis object (e.g. scatter, estimate)
Definition BinnedDbn.h:1026
double integralRange(const size_t binIndex1, size_t binIndex2) const
Calculates the integrated volume of the histogram between global bins binindex1 and binIndex2.
Definition BinnedDbn.h:479
double rms(size_t axisN, const bool includeOverflows=true) const noexcept
Calculates the RMS at axis.
Definition BinnedDbn.h:596
std::enable_if_t< std::is_floating_point< E >::value, E > min() const noexcept
Get the lowest non-overflow edge of the axis.
Definition BinnedDbn.h:444
BinnedEstimate< AxisT... > mkEstimate(const std::string &path="", const std::string &source="", const bool divbyvol=true) const
Produce a BinnedEstimate from a DbnStorage.
Definition BinnedDbn.h:754
void deserializeContent(const std::vector< double > &data)
Content deserialisation for MPI reduce operations.
Definition BinnedDbn.h:729
DbnStorage(Axis< AxisT > &&... axes, const std::string &path="", const std::string &title="")
Constructor given a sequence of rvalue axes.
Definition BinnedDbn.h:180
double sumWA(const size_t dim, const bool includeOverflows=true) const
Calculates first moment along axis dim in histo.
Definition BinnedDbn.h:538
void reset() noexcept
Reset the histogram.
Definition BinnedDbn.h:406
double sumWA2(const size_t dim, const bool includeOverflows=true) const
Calculates second moment along axis dim in histo.
Definition BinnedDbn.h:547
DbnStorage(std::initializer_list< AxisT > &&... binsEdges, const std::string &path="", const std::string &title="")
Constructor giving explicit bin edges as initializer list.
Definition BinnedDbn.h:160
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 reference.
Definition BinnedDbn.h:436
auto mkScatter(const std::string &path="", const bool divbyvol=true, const bool usefocus=false, const bool includeOverflows=false, const bool includeMaskedBins=false) const
Produce a ScatterND from a DbnStorage.
Definition BinnedDbn.h:808
void normalize(const double normto=1.0, const bool includeOverflows=true)
Normalize the (visible) histo "volume" to the normto value.
Definition BinnedDbn.h:255
double stdErr(size_t axisN, const bool includeOverflows=true) const noexcept
Calculates the standard error at axis.
Definition BinnedDbn.h:588
double densitySum(const bool includeOverflows=true) const noexcept
Returns the sum of the bin densities.
Definition BinnedDbn.h:625
double stdDev(size_t axisN, const bool includeOverflows=true) const noexcept
Calculates the standard deviation at axis.
Definition BinnedDbn.h:583
DbnStorage(std::vector< AxisT > &&... binsEdges, const std::string &path="", const std::string &title="")
Constructor giving explicit bin edges as rvalue reference.
Definition BinnedDbn.h:140
auto mkEstimates(const std::string &path="", const std::string source="", const bool divbyvol=true, const bool includeOverflows=false)
Produce a BinnedEstimate for each bin along axis axisN and return as a vector.
Definition BinnedDbn.h:799
double numEntries(const bool includeOverflows=true) const noexcept
Get the number of fills (fractional fills are possible).
Definition BinnedDbn.h:506
double density(const bool includeOverflows=true) const noexcept
Get the total density of the histogram.
Definition BinnedDbn.h:611
auto mkMarginalProfile(const std::string &path="") const
Produce a BinnedProfile from a DbnStorage.
Definition BinnedDbn.h:866
std::enable_if_t< std::is_floating_point< E >::value, E > max() const noexcept
Get the highest non-overflow edge of the axis.
Definition BinnedDbn.h:452
DbnStorage & operator+=(const DbnStorage &dbn)
Add two DbnStorages.
Definition BinnedDbn.h:349
DbnStorage * newclone() const noexcept
Make a copy on the heap.
Definition BinnedDbn.h:215
double effNumEntries(const bool includeOverflows=true) const noexcept
Get the effective number of fills.
Definition BinnedDbn.h:514
double integralError(const bool includeOverflows=true) const noexcept
Get the total volume error of the histogram.
Definition BinnedDbn.h:468
typename BaseT::BinningT BinningT
Definition BinnedDbn.h:120
DbnStorage & operator-=(const DbnStorage &dbn)
Subtract one DbnStorages from another one.
Definition BinnedDbn.h:376
FillableStorage< DbnN, Dbn< DbnN >, AxisT... > BaseT
Definition BinnedDbn.h:119
auto mkHistos(const std::string &path="", const bool includeOverflows=false) const
Split into vector of BinnedHisto along axis axisN.
Definition BinnedDbn.h:999
auto mkProfiles(const std::string &path="", const bool includeOverflows=false) const
Split into vector of BinnedProfile along axis axisN.
Definition BinnedDbn.h:976
double densityError(const bool includeOverflows=true) const noexcept
Get the total density error of the histogram.
Definition BinnedDbn.h:618
double crossTerm(const size_t A1, const size_t A2, const bool includeOverflows=true) const
Calculates cross-term along axes A1 and A2 in histo.
Definition BinnedDbn.h:557
auto mkMarginalHisto(const std::string &path="") const
Produce a BinnedHisto from a DbnStorage.
Definition BinnedDbn.h:920
DbnStorage(const DbnStorage &other, const std::string &path="")
Copy constructor.
Definition BinnedDbn.h:200
double dVol(const bool includeOverflows=true) const noexcept
Definition BinnedDbn.h:603
size_t fillDim() const noexcept
Fill-dimension of this data object.
Definition BinnedDbn.h:414
void rebin(unsigned int n, size_t begin=1, size_t end=UINT_MAX)
Overloaded alias for rebinBy.
Definition BinnedDbn.h:287
DbnStorage(const Axis< AxisT > &... axes, const std::string &path="", const std::string &title="")
Constructor given a sequence of axes.
Definition BinnedDbn.h:176
size_t lengthContent(bool=false) const noexcept
Length of serialized content vector for MPI reduce operations.
Definition BinnedDbn.h:712
double sumW(const bool includeOverflows=true) const noexcept
Calculates sum of weights in histo.
Definition BinnedDbn.h:522
double sumW2(const bool includeOverflows=true) const noexcept
Calculates sum of squared weights in histo.
Definition BinnedDbn.h:530
DbnStorage(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.
Definition BinnedDbn.h:170
double variance(size_t axisN, const bool includeOverflows=true) const noexcept
Calculates the variance at axis.
Definition BinnedDbn.h:575
void scaleW(const double scalefactor) noexcept
Rescale as if all fill weights had been different by factor scalefactor.
Definition BinnedDbn.h:234
DbnStorage(BinningT &&binning, const std::string &path="", const std::string &title="")
Constructor given an rvalue BinningT.
Definition BinnedDbn.h:188
typename BaseT::BinT BinType
Definition BinnedDbn.h:122
DbnStorage clone() const noexcept
Make a copy on the stack.
Definition BinnedDbn.h:210
virtual int fill(FillType &&coords, const double weight=1.0, const double fraction=1.0)
Triggers fill adapter on the bin corresponding to coords.
Definition BinnedDbn.h:229
DbnStorage(const std::vector< AxisT > &... binsEdges, const std::string &path="", const std::string &title="")
Constructor giving explicit bin edges as lvalue const reference.
Definition BinnedDbn.h:150
typename BaseT::FillType FillType
Definition BinnedDbn.h:123
double integralTo(const size_t binIndex) const noexcept
Get the total volume of the histogram.
Definition BinnedDbn.h:473
double integral(const bool includeOverflows=true) const noexcept
Get the total volume of the histogram.
Definition BinnedDbn.h:463
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.
Definition BinnedDbn.h:271
DbnStorage(const BinningT &binning, const std::string &path="", const std::string &title="")
Constructor given a BinningT (needed for type reductions)
Definition BinnedDbn.h:184
BinnedHisto< AxisT... > mkHisto(const std::string &path="") const
Produce a BinnedHisto from BinnedProfile.
Definition BinnedDbn.h:838
double mean(size_t axisN, const bool includeOverflows=true) const noexcept
Calculates the mean value at axis.
Definition BinnedDbn.h:567
DbnStorage(const ScatterND< sizeof...(AxisT)+1 > &s, const std::string &path="", const std::string &title="")
Constructor given a scatter.
Definition BinnedDbn.h:193
std::vector< E > edges(const bool includeOverflows=false) const noexcept
Returns the edges of axis N by value.
Definition BinnedDbn.h:424
double integralRangeError(const size_t binIndex1, size_t binIndex2) const
Calculates the integrated volume error of the histogram between global bins binindex1 and binIndex2.
Definition BinnedDbn.h:493
std::vector< double > serializeContent(bool=false) const noexcept
Content serialisation for MPI reduce operations.
Definition BinnedDbn.h:716
void scale(const size_t i, const double scalefactor) noexcept
Rescale as if all fill weights had been different by factor scalefactor along dimension i.
Definition BinnedDbn.h:242
DbnStorage()
Nullary constructor for unique pointers etc.
Definition BinnedDbn.h:133
double maxDensity(const bool includeOverflows=true) const noexcept
Returns the largest density in any of the bins.
Definition BinnedDbn.h:633
void rebin(const std::vector< typename BinningT::template getAxisT< axisN >::EdgeT > &newedges)
Overloaded alias for rebinTo.
Definition BinnedDbn.h:320
void rebinTo(const std::vector< typename BinningT::template getAxisT< axisN >::EdgeT > &newedges)
Rebin to the given list of bin edges.
Definition BinnedDbn.h:293
size_t dim() const noexcept
Total dimension of the object (number of axes + filled value)
Definition BinnedDbn.h:417
DbnStorage & operator=(const DbnStorage &dbn) noexcept
Copy assignment.
Definition BinnedDbn.h:325
DbnStorage(DbnStorage &&other, const std::string &path="")
Move constructor.
Definition BinnedDbn.h:206
User-facing Dbn class inheriting from DbnBase.
Definition Dbn.h:637
FillCoordsT FillType
Type of the fill coordinates.
size_t fillDim() const
Returns the dimension of the filling tuple.
int fill(FillCoordsT &&coords, std::index_sequence< Is... >, const double weight=1.0, const double fraction=1.0) noexcept
Triggers fill adapter on the bin corresponding to coords.
FillableStorage & operator=(const FillableStorage &other) noexcept
Copy assignment.
Bin< sizeof...(AxisT), Dbn< DbnN >, BinningT > BinT
A base class for all fillable objects.
Definition Fillable.h:13
Errors relating to insufficient (effective) statistics.
Definition Exceptions.h:72
Error for e.g. use of invalid bin ranges.
Definition Exceptions.h:34
A generic data type which is just a collection of n-dim data points with errors.
Definition Scatter.h:154
PointND< N > & point(size_t index)
Get a reference to the point with index index.
Definition Scatter.h:362
ScatterND< N > & addPoint(const PointND< N > &pt)
Insert a new point.
Definition Scatter.h:379
Utils::ndarray< double, N > NdVal
Definition Scatter.h:191
Error for problems introduced outside YODA, to put it nicely.
Definition Exceptions.h:100
Errors relating to event/bin weights.
Definition Exceptions.h:65
Anonymous namespace to limit visibility.
std::string mkTypeString()
Helper function to construct the BinnedDbn and BinnedEstimate type names.
double stdErr(const double sumWX, const double sumW, const double sumWX2, const double sumW2)
Calculate the weighted standard error of a sample.
Definition MathUtils.h:470
std::enable_if_t< all_CAxes< EdgeT... >::value > enable_if_all_CAxisT
Checks if all edge types are continuous.
BinnedEstimate< AxisT... > mkIntegralEff(const BinnedDbn< DbnN, AxisT... > &histo, const bool includeOverflows=true)
Convert a Histo1D to a Scatter2D where each bin is a fraction of the total.
Definition BinnedDbn.h:1245
std::string mkAxisConfig()
Helper function to construct the axis config.
BinnedDbn< DbnN, AxisT... > operator+(BinnedDbn< DbnN, AxisT... > first, BinnedDbn< DbnN, AxisT... > &&second)
Add two BinnedDbn objects.
Definition BinnedDbn.h:1060
BinnedEstimate< AxisT... > operator/(const BinnedDbn< DbnN, AxisT... > &numer, const BinnedDbn< DbnN, AxisT... > &denom)
Definition BinnedDbn.h:1133
BinnedEstimate< AxisT... > mkIntegral(const BinnedDbn< DbnN, AxisT... > &histo, const bool includeOverflows=true)
Convert a Histo1D to a Scatter2D representing the integral of the histogram.
Definition BinnedDbn.h:1216
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:1162
ScatterND< sizeof...(Args)+1 > zipProfiles(const BinnedDbn< DbnN, AxisT... > &p1, Args &&... others, const std::string &path="")
Zip profile objects of the same type into a combined scatter object.
Definition BinnedDbn.h:1374
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:1201
BinnedEstimate< AxisT... > add(const BinnedDbn< DbnN, AxisT... > &dbn, const BinnedEstimate< AxisT... > &est)
Calculate the addition of a BinnedDbn with a BinnedEstimate.
Definition BinnedDbn.h:1270
BinnedEstimate< AxisT... > subtract(const BinnedDbn< DbnN, AxisT... > &dbn, const BinnedEstimate< AxisT... > &est)
Calculate the subtraction of a BinnedEstimate from a BinnedDbn.
Definition BinnedDbn.h:1302
BinnedDbn< DbnN, AxisT... > operator-(BinnedDbn< DbnN, AxisT... > first, BinnedDbn< DbnN, AxisT... > &&second)
Subtract one BinnedDbn object from another.
Definition BinnedDbn.h:1076
BinnedEstimate< AxisT... > divide(const BinnedDbn< DbnN, AxisT... > &numer, const BinnedDbn< DbnN, AxisT... > &denom)
Divide two BinnedDbn objects.
Definition BinnedDbn.h:1092
double mean(const std::vector< int > &sample)
Calculate the mean of a sample.
Definition MathUtils.h:391