yoda is hosted by Hepforge, IPPP Durham
YODA - Yet more Objects for Data Analysis 2.0.0
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-2023 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 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() && b.numEntries() == 0) continue;
776 const double scale = divbyvol? b.dVol() : 1.0;
777 double v, e;
778 if constexpr(DbnN > sizeof...(AxisT)) {
779 v = b.mean(DbnN) / scale;
780 e = b.stdErr(DbnN) / scale;
781 }
782 else {
783 v = b.sumW() / scale;
784 e = b.errW() / scale;
785 }
786 rtn.bin(b.index()).set(v, e, source);
787 }
788
789 return rtn;
790 }
791
796 template<size_t axisN, typename = std::enable_if_t< (axisN < sizeof...(AxisT)) >>
797 auto mkEstimates(const std::string& path="", const std::string source = "",
798 const bool divbyvol=true, const bool includeOverflows=false) {
799
800 BinnedEstimate<AxisT...> est = mkEstimate(path, source, divbyvol);
801 return est.template mkEstimates<axisN>(path, includeOverflows);
802 }
803
804
806 auto mkScatter(const std::string& path="", const bool divbyvol=true,
807 const bool usefocus=false,
808 const bool includeOverflows=false,
809 const bool includeMaskedBins=false) const {
810 const BinnedEstimate<AxisT...> est = mkEstimate("", "", divbyvol);
811 ScatterND<sizeof...(AxisT)+1> rtn = est.mkScatter(path, includeOverflows, includeMaskedBins);
812 if (usefocus) {
813 size_t idx = 0;
814 for (const auto& b : BaseT::bins(includeOverflows, includeMaskedBins)) {
815 auto shiftIfContinuous = [&rtn, &b, &idx](auto I) {
816 using isContinuous = typename BinningT::template is_CAxis<I>;
817 if constexpr (isContinuous::value) {
818 const double oldMax = rtn.point(idx).max(I);
819 const double oldMin = rtn.point(idx).min(I);
820 const double newVal = b.mean(I+1);
821 rtn.point(idx).set(I, newVal, newVal - oldMin, oldMax - newVal);
822 }
823 };
824 MetaUtils::staticFor<BinningT::Dimension::value>(shiftIfContinuous);
825 ++idx;
826 }
827 }
828 return rtn;
829 }
830
835 template<size_t N = DbnN, typename = std::enable_if_t< (N == sizeof...(AxisT)+1) >>
836 BinnedHisto<AxisT...> mkHisto(const std::string& path="") const {
837
838 BinnedHisto<AxisT...> rtn(BaseT::_binning);
839 rtn.setNanLog(BaseT::nanCount(), BaseT::nanSumW(), BaseT::nanSumW2());
840 for (const std::string& a : annotations()) {
841 if (a != "Type") rtn.setAnnotation(a, annotation(a));
842 }
843 rtn.setAnnotation("Path", path);
844
845 for (const auto& b : BaseT::bins(true)) {
846 rtn.bin(b.index()) += b.template reduce<N-1>();
847 }
848
849 return rtn;
850 }
851
863 template<size_t axisN, typename = std::enable_if_t< (axisN < sizeof...(AxisT)) >>
864 auto mkMarginalProfile(const std::string& path="") const {
865
866 auto rtn = BaseT::template _mkBinnedT<BinnedProfile>(BaseT::_binning.template _getAxesExcept<axisN>());
867 rtn.setNanLog(BaseT::nanCount(), BaseT::nanSumW(), BaseT::nanSumW2());
868 for (const std::string& a : annotations()) {
869 if (a != "Type") rtn.setAnnotation(a, annotation(a));
870 }
871 rtn.setAnnotation("Path", path);
872
873 auto collapseStorageBins =
874 [&oldBinning = BaseT::_binning, &oldBins = BaseT::_bins, &rtn](auto I, auto dbnRed) {
875
876 auto collapse = [&oldBins, &rtn](const auto& binsIndicesToMerge, auto axis) {
877 assert(rtn.numBins(true) == binsIndicesToMerge.size());
878
879 // for any given pivot, add the content
880 // from the old slice to the new slice
881 for (size_t i = 0; i < rtn.numBins(true); ++i) {
882 auto& pivotBin = rtn.bin(i);
883 auto& binToAppend = oldBins[binsIndicesToMerge[i]];
884 pivotBin += binToAppend.template reduce<axis>();
885 }
886 };
887
888 // get bin slice for any given bin along the axis that is to be
889 // collapsed, then copy the values into the new binning
890 ssize_t nBinRowsToBeMerged = oldBinning.numBinsAt(I);
891 while (nBinRowsToBeMerged--) {
894 collapse(oldBinning.sliceIndices(I, nBinRowsToBeMerged), dbnRed);
895 }
896 };
900 auto dbnRed = std::integral_constant<size_t, (sizeof...(AxisT) == DbnN)? DbnN : axisN>();
901 (void)collapseStorageBins(std::integral_constant<std::size_t, axisN>(), dbnRed);
902
903 return rtn;
904 }
905
917 template<size_t axisN, typename = std::enable_if_t< (axisN < sizeof...(AxisT)) >>
918 auto mkMarginalHisto(const std::string& path="") const {
919
920 if constexpr (DbnN != sizeof...(AxisT)) {
921 // Case 1: BP(N+1) -> BH(N+1) -> BHN
922 return mkHisto().template mkMarginalHisto<axisN>(path);
923 }
924 else {
925 // Case 2: BH(N+1) -> BHN
926
927 auto rtn = BaseT::template _mkBinnedT<BinnedHisto>(BaseT::_binning.template _getAxesExcept<axisN>());
928 rtn.setNanLog(BaseT::nanCount(), BaseT::nanSumW(), BaseT::nanSumW2());
929 for (const std::string& a : annotations()) {
930 if (a != "Type") rtn.setAnnotation(a, annotation(a));
931 }
932 rtn.setAnnotation("Path", path);
933
934 auto collapseStorageBins =
935 [&oldBinning = BaseT::_binning, &oldBins = BaseT::_bins, &rtn](auto I, auto dbnRed) {
936
937 auto collapse = [&oldBins, &rtn](const auto& binsIndicesToMerge, auto axis) {
938 assert(rtn.numBins(true) == binsIndicesToMerge.size());
939
940 // for any given pivot, add the content
941 // from the old slice to the new slice
942 for (size_t i = 0; i < rtn.numBins(true); ++i) {
943 auto& pivotBin = rtn.bin(i);
944 auto& binToAppend = oldBins[binsIndicesToMerge[i]];
945 pivotBin += binToAppend.template reduce<axis>();
946 }
947 };
948
949 // get bin slice for any given bin along the axis that is to be
950 // collapsed, then copy the values into the new binning
951 ssize_t nBinRowsToBeMerged = oldBinning.numBinsAt(I);
952 while (nBinRowsToBeMerged--) {
955 collapse(oldBinning.sliceIndices(I, nBinRowsToBeMerged), dbnRed);
956 }
957 };
958 // collapse Dbn along axisN
959 auto dbnRed = std::integral_constant<size_t, axisN>();
960 (void)collapseStorageBins(std::integral_constant<std::size_t, axisN>(), dbnRed);
961
962 return rtn;
963 }
964 }
965
966
971 template<size_t axisN, typename = std::enable_if_t< (axisN < sizeof...(AxisT) &&
972 sizeof...(AxisT)>=2 &&
973 DbnN > sizeof...(AxisT)) >>
974 auto mkProfiles(const std::string& path="", const bool includeOverflows=false) const {
975
976 // Need to provide a prescription for how to add the two bin contents
977 auto how2add = [](auto& pivot, const BinType& toCopy) { pivot = toCopy.template reduce<axisN>(); };
978 auto rtn = BaseT::template mkBinnedSlices<axisN, BinnedProfile>(how2add, includeOverflows);
979 for (const std::string& a : annotations()) {
980 if (a == "Type") continue;
981 for (size_t i = 0; i < rtn.size(); ++i) {
982 rtn[i].setAnnotation(a, annotation(a));
983 }
984 }
985 for (size_t i = 0; i < rtn.size(); ++i) {
986 rtn[i].setAnnotation("Path", path);
987 }
988 return rtn;
989 }
990
991
996 template<size_t axisN, typename = std::enable_if_t< (axisN < sizeof...(AxisT) && sizeof...(AxisT)>=2) >>
997 auto mkHistos(const std::string& path="", const bool includeOverflows=false) const {
998
999 if constexpr (DbnN != sizeof...(AxisT)) {
1000 // Case 1: BP(N+1) -> BH(N+1) -> BHN
1001 return mkHisto().template mkHistos<axisN>(path, includeOverflows);
1002 }
1003 else {
1004 // Case 2: BH(N+1) -> BHN
1005
1006 // Need to provide a prescription for how to add the two bin contents
1007 auto how2add = [](auto& pivot, const BinType& toCopy) { pivot = toCopy.template reduce<axisN>(); };
1008 auto rtn = BaseT::template mkBinnedSlices<axisN,BinnedHisto>(how2add, includeOverflows);
1009 for (const std::string& a : annotations()) {
1010 if (a == "Type") continue;
1011 for (size_t i = 0; i < rtn.size(); ++i) {
1012 rtn[i].setAnnotation(a, annotation(a));
1013 }
1014 }
1015 for (size_t i = 0; i < rtn.size(); ++i) {
1016 rtn[i].setAnnotation("Path", path);
1017 }
1018 return rtn;
1019 }
1020 }
1021
1022
1024 AnalysisObject* mkInert(const std::string& path = "",
1025 const std::string& source = "") const noexcept {
1026 return mkEstimate(path, source).newclone();
1027 }
1028
1030
1031 private:
1032
1035 template<size_t... Is>
1036 BinningT _mkBinning(const std::vector<size_t>& nBins,
1037 const std::vector<std::pair<double, double>>& limitsLowUp,
1038 std::index_sequence<Is...>) const {
1039 return BinningT({((void)Is, Axis<AxisT>(nBins[Is], limitsLowUp[Is].first, limitsLowUp[Is].second))...});
1040 }
1041
1043 template<size_t... Is>
1044 BinningT _mkBinning(const ScatterND<sizeof...(AxisT)+1>& s, std::index_sequence<Is...>) const {
1045 return BinningT(Axis<AxisT>(s.edges(Is))...);
1046 }
1047
1048 };
1049
1050
1051
1054
1056 template<size_t DbnN, typename... AxisT>
1057 inline BinnedDbn<DbnN, AxisT...>
1059 first += std::move(second);
1060 return first;
1061 }
1062 //
1063 template <size_t DbnN, typename... AxisT>
1064 inline BinnedDbn<DbnN, AxisT...>
1066 first += second;
1067 return first;
1068 }
1069
1070
1072 template <size_t DbnN, typename... AxisT>
1073 inline BinnedDbn<DbnN, AxisT...>
1075 first -= std::move(second);
1076 return first;
1077 }
1078 //
1079 template <size_t DbnN, typename... AxisT>
1080 inline BinnedDbn<DbnN, AxisT...>
1082 first -= second;
1083 return first;
1084 }
1085
1086
1088 template <size_t DbnN, typename... AxisT>
1089 inline BinnedEstimate<AxisT...>
1091
1092 if (numer != denom) {
1093 throw BinningError("Arithmetic operation requires compatible binning!");
1094 }
1095
1096 BinnedEstimate<AxisT...> rtn = numer.mkEstimate();
1097 if (numer.path() == denom.path()) rtn.setPath(numer.path());
1098 if (rtn.hasAnnotation("ScaledBy")) rtn.rmAnnotation("ScaledBy");
1099
1100 for (const auto& b_num : numer.bins(true, true)) {
1101 const size_t idx = b_num.index();
1102 const auto& b_den = denom.bin(idx);
1103 double v, e;
1104 if (!b_den.effNumEntries()) {
1105 v = std::numeric_limits<double>::quiet_NaN();
1106 e = std::numeric_limits<double>::quiet_NaN();
1107 }
1108 else {
1109 if constexpr(DbnN > sizeof...(AxisT)) {
1110 v = b_num.mean(DbnN) / b_den.mean(DbnN);
1111 const double e_num = b_num.effNumEntries()? b_num.relStdErr(DbnN) : 0;
1112 const double e_den = b_den.effNumEntries()? b_den.relStdErr(DbnN) : 0;
1113 e = fabs(v) * sqrt(sqr(e_num) + sqr(e_den));
1114 }
1115 else {
1116 v = b_num.sumW() / b_den.sumW();
1117 const double e_num = b_num.sumW()? b_num.relErrW() : 0;
1118 const double e_den = b_den.sumW()? b_den.relErrW() : 0;
1119 e = fabs(v) * sqrt(sqr(e_num) + sqr(e_den));
1120 }
1121 }
1122 rtn.bin(idx).set(v, {-e, e}); // @todo put "stats" as source?
1123 }
1124 rtn.maskBins(denom.maskedBins(), true);
1125
1126 return rtn;
1127 }
1128 //
1129 template <size_t DbnN, typename... AxisT>
1130 inline BinnedEstimate<AxisT...>
1132 return divide(numer, denom);
1133 }
1134 //
1135 template <size_t DbnN, typename... AxisT>
1136 inline BinnedEstimate<AxisT...>
1138 return divide(numer, std::move(denom));
1139 }
1140 //
1141 template <size_t DbnN, typename... AxisT>
1142 inline BinnedEstimate<AxisT...>
1144 return divide(std::move(numer), denom);
1145 }
1146 //
1147 template <size_t DbnN, typename... AxisT>
1148 inline BinnedEstimate<AxisT...>
1150 return divide(std::move(numer), std::move(denom));
1151 }
1152
1153
1158 template <size_t DbnN, typename... AxisT>
1159 inline BinnedEstimate<AxisT...>
1161
1162 if (accepted != total) {
1163 throw BinningError("Arithmetic operation requires compatible binning!");
1164 }
1165
1166 BinnedEstimate<AxisT...> rtn = divide(accepted, total);
1167
1168 for (const auto& b_acc : accepted.bins(true, true)) {
1169 const auto& b_tot = total.bin(b_acc.index());
1170 auto& b_rtn = rtn.bin(b_acc.index());
1171
1172 // Check that the numerator is consistent with being a subset of the denominator
1174 if (b_acc.numEntries() > b_tot.numEntries())
1175 throw UserError("Attempt to calculate an efficiency when the numerator is not a subset of the denominator: "
1176 + Utils::toStr(b_acc.numEntries()) + " entries / " + Utils::toStr(b_tot.numEntries()) + " entries");
1177
1178 // If no entries on the denominator, set eff = err = 0 and move to the next bin
1179 double eff = std::numeric_limits<double>::quiet_NaN();
1180 double err = std::numeric_limits<double>::quiet_NaN();
1181 try {
1182 if (b_tot.sumW()) {
1183 eff = b_rtn.val();
1184 err = sqrt(abs( ((1-2*eff)*b_acc.sumW2() + sqr(eff)*b_tot.sumW2()) / sqr(b_tot.sumW()) ));
1185 }
1186 } catch (const LowStatsError& e) {
1187 //
1188 }
1189
1190 b_rtn.setErr({-err, err}); // @todo put "stats" as source?
1191 }
1192 return rtn;
1193 }
1194
1195
1197 template <size_t DbnN, typename... AxisT>
1198 inline BinnedEstimate<AxisT...>
1200 return (a-b) / (a+b);
1201 }
1202
1203
1212 template <size_t DbnN, typename... AxisT>
1213 inline BinnedEstimate<AxisT...>
1214 mkIntegral(const BinnedDbn<DbnN, AxisT...>& histo, const bool includeOverflows = true) {
1215
1216 BinnedEstimate<AxisT...> rtn = histo.mkEstimate();
1217
1218 double sumW = 0.0, sumW2 = 0.0;
1219 for (const auto& b : histo.bins(includeOverflows)) {
1220 sumW += b.sumW();
1221 sumW2 += b.sumW2();
1222 const double e = sqrt(sumW2);
1223 rtn.bin(b.index()).set(sumW, {-e, e});
1224 }
1225
1226 return rtn;
1227 }
1228
1229
1241 template <size_t DbnN, typename... AxisT>
1242 inline BinnedEstimate<AxisT...>
1243 mkIntegralEff(const BinnedDbn<DbnN, AxisT...>& histo, const bool includeOverflows = true) {
1244
1245 BinnedEstimate<AxisT...> rtn = mkIntegral(histo, includeOverflows);
1246 const double integral = histo.integral(includeOverflows);
1247
1248 // If the integral is empty, the (integrated) efficiency values may as well all be zero, so return here
1252 if (!integral) return rtn;
1253
1254 const double integral_err = histo.integralError(includeOverflows);
1255 for (const auto& b : rtn.bins(includeOverflows)) {
1256 const double eff = b.val() / integral;
1257 const double err = sqrt(std::abs( ((1-2*eff)*sqr(b.relTotalErrAvg()) + sqr(eff)*sqr(integral_err)) / sqr(integral) ));
1258 b.set(eff, {-err,err});
1259 }
1260
1261 return rtn;
1262 }
1263
1264
1266 template <size_t DbnN, typename... AxisT>
1267 inline BinnedEstimate<AxisT...>
1269 return dbn.mkEstimate() + est;
1270 }
1271 //
1272 template <size_t DbnN, typename... AxisT>
1273 inline BinnedEstimate<AxisT...>
1275 return add(dbn, est);
1276 }
1277 //
1278 template <size_t DbnN, typename... AxisT>
1279 inline BinnedEstimate<AxisT...>
1281 return add(std::move(dbn), est);
1282 }
1283 //
1284 template <size_t DbnN, typename... AxisT>
1285 inline BinnedEstimate<AxisT...>
1287 return add(dbn, std::move(est));
1288 }
1289 //
1290 template <size_t DbnN, typename... AxisT>
1291 inline BinnedEstimate<AxisT...>
1293 return add(std::move(dbn), std::move(est));
1294 }
1295
1296
1298 template <size_t DbnN, typename... AxisT>
1299 inline BinnedEstimate<AxisT...>
1301 return dbn.mkEstimate() - est;
1302 }
1303 //
1304 template <size_t DbnN, typename... AxisT>
1305 inline BinnedEstimate<AxisT...>
1307 return subtract(dbn, est);
1308 }
1309 //
1310 template <size_t DbnN, typename... AxisT>
1311 inline BinnedEstimate<AxisT...>
1313 return subtract(std::move(dbn), est);
1314 }
1315 //
1316 template <size_t DbnN, typename... AxisT>
1317 inline BinnedEstimate<AxisT...>
1319 return subtract(dbn, std::move(est));
1320 }
1321 //
1322 template <size_t DbnN, typename... AxisT>
1323 inline BinnedEstimate<AxisT...>
1325 return subtract(std::move(dbn), std::move(est));
1326 }
1327
1328
1330 template <size_t DbnN, typename... AxisT>
1331 inline BinnedEstimate<AxisT...>
1333 return dbn.mkEstimate() / est;
1334 }
1335 //
1336 template <size_t DbnN, typename... AxisT>
1337 inline BinnedEstimate<AxisT...>
1339 return divide(dbn, est);
1340 }
1341 //
1342 template <size_t DbnN, typename... AxisT>
1343 inline BinnedEstimate<AxisT...>
1345 return divide(std::move(dbn), est);
1346 }
1347 //
1348 template <size_t DbnN, typename... AxisT>
1349 inline BinnedEstimate<AxisT...>
1351 return divide(dbn, std::move(est));
1352 }
1353 //
1354 template <size_t DbnN, typename... AxisT>
1355 inline BinnedEstimate<AxisT...>
1357 return divide(std::move(dbn), std::move(est));
1358 }
1359
1361
1362}
1363
1364#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.
void set(typename BinningT::EdgeTypesTuple &&coords, BinContentT &&content) noexcept
Sets the bin corresponding to coords with an rvalue content.
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:1024
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:806
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:797
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:864
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:997
auto mkProfiles(const std::string &path="", const bool includeOverflows=false) const
Split into vector of BinnedProfile along axis axisN.
Definition BinnedDbn.h:974
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:918
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:836
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:352
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.
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:1243
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:1058
BinnedEstimate< AxisT... > operator/(const BinnedDbn< DbnN, AxisT... > &numer, const BinnedDbn< DbnN, AxisT... > &denom)
Definition BinnedDbn.h:1131
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:1214
NUM sqr(NUM a)
Named number-type squaring operation.
Definition MathUtils.h:216
BinnedEstimate< AxisT... > efficiency(const BinnedDbn< DbnN, AxisT... > &accepted, const BinnedDbn< DbnN, AxisT... > &total)
Calculate a binned efficiency ratio of two BinnedDbn objects.
Definition BinnedDbn.h:1160
BinnedEstimate< AxisT... > asymm(const BinnedDbn< DbnN, AxisT... > &a, const BinnedDbn< DbnN, AxisT... > &b)
Calculate the asymmetry (a-b)/(a+b) of two BinnedDbn objects.
Definition BinnedDbn.h:1199
BinnedEstimate< AxisT... > add(const BinnedDbn< DbnN, AxisT... > &dbn, const BinnedEstimate< AxisT... > &est)
Calculate the addition of a BinnedDbn with a BinnedEstimate.
Definition BinnedDbn.h:1268
BinnedEstimate< AxisT... > subtract(const BinnedDbn< DbnN, AxisT... > &dbn, const BinnedEstimate< AxisT... > &est)
Calculate the subtraction of a BinnedEstimate from a BinnedDbn.
Definition BinnedDbn.h:1300
BinnedDbn< DbnN, AxisT... > operator-(BinnedDbn< DbnN, AxisT... > first, BinnedDbn< DbnN, AxisT... > &&second)
Subtract one BinnedDbn object from another.
Definition BinnedDbn.h:1074
BinnedEstimate< AxisT... > divide(const BinnedDbn< DbnN, AxisT... > &numer, const BinnedDbn< DbnN, AxisT... > &denom)
Divide two BinnedDbn objects.
Definition BinnedDbn.h:1090