|
YODA - Yet more Objects for Data Analysis 2.0.2
|
Go to the documentation of this file.
6#ifndef YODA_BinnedDbn_h
7#define YODA_BinnedDbn_h
45 template < size_t DbnN, typename... AxisT>
49 template < size_t DbnN, typename... AxisT>
56 using Ptr = std::shared_ptr<HistoT>;
66 using AnalysisObject::operator =;
96 template < typename... AxisTypes>
99 template < typename... AxisTypes>
114 template < size_t DbnN, typename... AxisT>
124 using AnalysisObject::operator =;
141 const std::string& path = "", const std::string& title = "")
142 : BaseT( Axis<AxisT>(std::move(binsEdges))...),
151 const std::string& path = "", const std::string& title = "")
161 const std::string& path = "", const std::string& title = "")
162 : BaseT( Axis<AxisT>(std::move(binsEdges))...),
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)>{}) ),
194 : BaseT(_mkBinning(s, std::make_index_sequence<sizeof...(AxisT)>{})),
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);
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);
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);
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);
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!");
275 for ( size_t m = begin; m < end; ++m) {
279 BaseT::template mergeBins<axisN>({m, myend});
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);
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;
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");
305 for ( size_t begin = 0; begin < eshared.size() - 1; ++begin) {
308 size_t end = oldAxis.index(eshared[begin+1]) - 1;
311 if (begin == newAxis.numBins( true)-1) end = oldAxis.numBins( true)-1;
313 if (end > begin) BaseT::template mergeBins<axisN>({begin, end});
314 if (eshared.size() == oldAxis.edges().size()) break;
319 template < size_t axisN>
320 void rebin( const std::vector< typename BinningT::template getAxisT<axisN>::EdgeT>& newedges) {
321 rebinTo<axisN>(newedges);
351 throw BinningError( "Arithmetic operation requires compatible binning!");
362 throw BinningError( "Arithmetic operation requires compatible binning!");
378 throw BinningError( "Arithmetic operation requires compatible binning!");
389 throw BinningError( "Arithmetic operation requires compatible binning!");
417 size_t dim() const noexcept { return sizeof...(AxisT) + 1; }
420 std::string _config() const noexcept { return mkAxisConfig<AxisT...>(); }
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);
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);
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>();
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>();
463 double integral( const bool includeOverflows= true) const noexcept {
464 return sumW(includeOverflows);
469 return sqrt( sumW2(includeOverflows));
480 assert(binIndex2 >= binIndex1);
484 for ( size_t idx = binIndex1; idx <= binIndex2; ++idx) {
494 assert(binIndex2 >= binIndex1);
498 for ( size_t idx = binIndex1; idx <= binIndex2; ++idx) {
506 double numEntries( const bool includeOverflows= true) const noexcept {
508 for ( const auto& b : BaseT::bins(includeOverflows))
516 for ( const auto& b : BaseT::bins(includeOverflows))
517 n += b.effNumEntries();
522 double sumW( const bool includeOverflows= true) const noexcept {
524 for ( const auto& b : BaseT::bins(includeOverflows))
530 double sumW2( const bool includeOverflows= true) const noexcept {
532 for ( const auto& b : BaseT::bins(includeOverflows))
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");
541 for ( const auto& b : BaseT::bins(includeOverflows))
542 sumwa += b.sumW( dim+1);
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");
550 for ( const auto& b : BaseT::bins(includeOverflows))
551 sumwa2 += b.sumW2( dim+1);
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");
561 for ( const auto& b : BaseT::bins(includeOverflows))
562 sumw += b.crossTerm(A1, A2);
567 double mean( size_t axisN, const bool includeOverflows= true) const noexcept {
569 for ( const auto& b : BaseT::bins(includeOverflows))
571 return dbn. mean(axisN+1);
575 double variance( size_t axisN, const bool includeOverflows= true) const noexcept {
577 for ( const auto& b : BaseT::bins(includeOverflows))
583 double stdDev( size_t axisN, const bool includeOverflows= true) const noexcept {
584 return std::sqrt( variance(axisN, includeOverflows));
588 double stdErr( size_t axisN, const bool includeOverflows= true) const noexcept {
590 for ( const auto& b : BaseT::bins(includeOverflows))
592 return dbn. stdErr(axisN+1);
596 double rms( size_t axisN, const bool includeOverflows= true) const noexcept {
598 for ( const auto& b : BaseT::bins(includeOverflows))
600 return dbn. RMS(axisN+1);
603 double dVol( const bool includeOverflows= true) const noexcept {
605 for ( const auto& b : BaseT::bins(includeOverflows))
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();
619 const double vol = dVol(includeOverflows);
621 return std::numeric_limits<double>::quiet_NaN();
625 double densitySum( const bool includeOverflows= true) const noexcept {
627 for ( const auto& b : BaseT::bins(includeOverflows))
628 rho += b.sumW() / b.dVol();
633 double maxDensity( const bool includeOverflows= true) const noexcept {
634 std::vector<double> vals;
636 vals.emplace_back(b.sumW() / b.dVol());
637 return *max_element(vals.begin(), vals.end());
648 template< size_t... Is>
649 void _renderYODA_aux(std::ostream& os, const int width, std::index_sequence<Is...>) const noexcept {
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";
661 BaseT::_binning._renderYODA(os);
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";
676 os << "numEntries\n";
678 for ( const auto& b : BaseT:: bins(true, true)) {
679 os << std::setw(width) << std::left << b.sumW() << "\t";
680 os << std::setw(width) << std::left << b.sumW2() << "\t";
681 ((os << std::setw(width) << std::left << b.sumW( Is+1) << "\t"
682 << std::setw(width) << std::left << b.sumW2(Is+1) << "\t"), ...);
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";
690 os << std::setw(width) << std::left << b.numEntries() << "\n";
697 void _renderYODA(std::ostream& os, const int width = 13) const noexcept {
698 _renderYODA_aux(os, width, std::make_index_sequence<DbnN>{});
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);
717 std::vector<double> rtn;
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)));
733 if (data.size() != nBins * dbnSize)
734 throw UserError( "Length of serialized data should be "
735 + std::to_string(nBins * dbnSize)+ "!");
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});
755 const std::string& source = "",
756 [[maybe_unused]] const bool divbyvol= true) const {
761 if (a != "Type") rtn.setAnnotation(a, annotation(a));
763 rtn.setAnnotation( "Path", path);
768 const double frac = nanc / (nanc + numEntries());
770 rtn.setAnnotation( "NanFraction", frac);
771 if (wtot) rtn.setAnnotation( "WeightedNanFraction", nanw/wtot);
775 if (!b.isVisible()) continue;
776 if constexpr(DbnN > sizeof...(AxisT)) {
777 rtn.bin(b.index()).setVal(b.mean(DbnN));
778 if (b.numEntries()) {
779 rtn.bin(b.index()).setErr(b.stdErr(DbnN), source);
783 const double scale = divbyvol? b.dVol() : 1.0;
784 rtn.bin(b.index()).setVal(b.sumW() / scale);
785 if (b.numEntries()) {
786 rtn.bin(b.index()).setErr(b.errW() / scale, source);
798 template< size_t axisN, typename = std::enable_if_t< (axisN < sizeof...(AxisT)) >>
800 const bool divbyvol= true, const bool includeOverflows= false) {
803 return est.template mkEstimates<axisN>( path, includeOverflows);
809 const bool usefocus= false,
810 const bool includeOverflows= false,
811 const bool includeMaskedBins= false) const {
813 ScatterND< sizeof...(AxisT)+1> rtn = est.mkScatter( path, "", includeOverflows, includeMaskedBins);
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);
826 MetaUtils::staticFor<BinningT::Dimension::value>(shiftIfContinuous);
837 template< size_t N = DbnN, typename = std::enable_if_t< (N == sizeof...(AxisT)+1) >>
843 if (a != "Type") rtn.setAnnotation(a, annotation(a));
845 rtn.setAnnotation( "Path", path);
848 rtn.bin(b.index()) += b.template reduce<N-1>();
865 template< size_t axisN, typename = std::enable_if_t< (axisN < sizeof...(AxisT)) >>
868 auto rtn = BaseT::template _mkBinnedT<BinnedProfile>(BaseT::_binning. template _getAxesExcept<axisN>());
871 if (a != "Type") rtn.setAnnotation(a, annotation(a));
873 rtn.setAnnotation( "Path", path);
875 auto collapseStorageBins =
876 [&oldBinning = BaseT::_binning, &oldBins = BaseT::_bins, &rtn]( auto I, auto dbnRed) {
878 auto collapse = [&oldBins, &rtn]( const auto& binsIndicesToMerge, auto axis) {
879 assert(rtn.numBins( true) == binsIndicesToMerge.size());
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>();
892 ssize_t nBinRowsToBeMerged = oldBinning.numBinsAt(I);
893 while (nBinRowsToBeMerged--) {
896 collapse(oldBinning.sliceIndices(I, nBinRowsToBeMerged), dbnRed);
902 auto dbnRed = std::integral_constant<size_t, ( sizeof...(AxisT) == DbnN)? DbnN : axisN>();
903 (void)collapseStorageBins(std::integral_constant<std::size_t, axisN>(), dbnRed);
919 template< size_t axisN, typename = std::enable_if_t< (axisN < sizeof...(AxisT)) >>
922 if constexpr (DbnN != sizeof...(AxisT)) {
924 return mkHisto().template mkMarginalHisto<axisN>( path);
929 auto rtn = BaseT::template _mkBinnedT<BinnedHisto>(BaseT::_binning. template _getAxesExcept<axisN>());
932 if (a != "Type") rtn.setAnnotation(a, annotation(a));
934 rtn.setAnnotation( "Path", path);
936 auto collapseStorageBins =
937 [&oldBinning = BaseT::_binning, &oldBins = BaseT::_bins, &rtn]( auto I, auto dbnRed) {
939 auto collapse = [&oldBins, &rtn]( const auto& binsIndicesToMerge, auto axis) {
940 assert(rtn.numBins( true) == binsIndicesToMerge.size());
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>();
953 ssize_t nBinRowsToBeMerged = oldBinning.numBinsAt(I);
954 while (nBinRowsToBeMerged--) {
957 collapse(oldBinning.sliceIndices(I, nBinRowsToBeMerged), dbnRed);
961 auto dbnRed = std::integral_constant<size_t, axisN>();
962 (void)collapseStorageBins(std::integral_constant<std::size_t, axisN>(), dbnRed);
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 {
979 auto how2add = []( auto& pivot, const BinType& toCopy) { pivot = toCopy.template reduce<axisN>(); };
980 auto rtn = BaseT::template mkBinnedSlices<axisN, BinnedProfile>(how2add, includeOverflows);
982 if (a == "Type") continue;
983 for ( size_t i = 0; i < rtn.size(); ++i) {
987 for ( size_t i = 0; i < rtn.size(); ++i) {
988 rtn[i].setAnnotation( "Path", path);
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 {
1001 if constexpr (DbnN != sizeof...(AxisT)) {
1003 return mkHisto().template mkHistos<axisN>( path, includeOverflows);
1009 auto how2add = []( auto& pivot, const BinType& toCopy) { pivot = toCopy.template reduce<axisN>(); };
1010 auto rtn = BaseT::template mkBinnedSlices<axisN,BinnedHisto>(how2add, includeOverflows);
1012 if (a == "Type") continue;
1013 for ( size_t i = 0; i < rtn.size(); ++i) {
1017 for ( size_t i = 0; i < rtn.size(); ++i) {
1018 rtn[i].setAnnotation( "Path", path);
1027 const std::string& source = "") const noexcept {
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))...});
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))...);
1058 template< size_t DbnN, typename... AxisT>
1059 inline BinnedDbn<DbnN, AxisT...>
1061 first += std::move(second);
1065 template < size_t DbnN, typename... AxisT>
1066 inline BinnedDbn<DbnN, AxisT...>
1074 template < size_t DbnN, typename... AxisT>
1075 inline BinnedDbn<DbnN, AxisT...>
1077 first -= std::move(second);
1081 template < size_t DbnN, typename... AxisT>
1082 inline BinnedDbn<DbnN, AxisT...>
1090 template < size_t DbnN, typename... AxisT>
1091 inline BinnedEstimate<AxisT...>
1094 if (numer != denom) {
1095 throw BinningError( "Arithmetic operation requires compatible binning!");
1099 if (numer. path() == denom. path()) rtn.setPath(numer. path());
1100 if (rtn.hasAnnotation( "ScaledBy")) rtn.rmAnnotation( "ScaledBy");
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);
1106 if (!b_den.effNumEntries()) {
1107 v = std::numeric_limits<double>::quiet_NaN();
1108 e = std::numeric_limits<double>::quiet_NaN();
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));
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));
1124 rtn.bin(idx).set(v, {-e, e});
1131 template < size_t DbnN, typename... AxisT>
1132 inline BinnedEstimate<AxisT...>
1134 return divide(numer, denom);
1137 template < size_t DbnN, typename... AxisT>
1138 inline BinnedEstimate<AxisT...>
1140 return divide(numer, std::move(denom));
1143 template < size_t DbnN, typename... AxisT>
1144 inline BinnedEstimate<AxisT...>
1146 return divide(std::move(numer), denom);
1149 template < size_t DbnN, typename... AxisT>
1150 inline BinnedEstimate<AxisT...>
1152 return divide(std::move(numer), std::move(denom));
1160 template < size_t DbnN, typename... AxisT>
1161 inline BinnedEstimate<AxisT...>
1164 if (accepted != total) {
1165 throw BinningError( "Arithmetic operation requires compatible binning!");
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());
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");
1181 double eff = std::numeric_limits<double>::quiet_NaN();
1182 double err = std::numeric_limits<double>::quiet_NaN();
1186 err = sqrt(abs( ((1-2*eff)*b_acc.sumW2() + sqr(eff)*b_tot.sumW2()) / sqr(b_tot.sumW()) ));
1192 b_rtn.setErr({-err, err});
1199 template < size_t DbnN, typename... AxisT>
1200 inline BinnedEstimate<AxisT...>
1202 return (a-b) / (a+b);
1214 template < size_t DbnN, typename... AxisT>
1215 inline BinnedEstimate<AxisT...>
1220 double sumW = 0.0, sumW2 = 0.0;
1221 for ( const auto& b : histo. bins(includeOverflows)) {
1224 const double e = sqrt(sumW2);
1225 rtn.bin(b.index()).set(sumW, {-e, e});
1243 template < size_t DbnN, typename... AxisT>
1244 inline BinnedEstimate<AxisT...>
1248 const double integral = histo. integral(includeOverflows);
1254 if (!integral) return rtn;
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});
1268 template < size_t DbnN, typename... AxisT>
1269 inline BinnedEstimate<AxisT...>
1274 template < size_t DbnN, typename... AxisT>
1275 inline BinnedEstimate<AxisT...>
1277 return add(dbn, est);
1280 template < size_t DbnN, typename... AxisT>
1281 inline BinnedEstimate<AxisT...>
1283 return add(std::move(dbn), est);
1286 template < size_t DbnN, typename... AxisT>
1287 inline BinnedEstimate<AxisT...>
1289 return add(dbn, std::move(est));
1292 template < size_t DbnN, typename... AxisT>
1293 inline BinnedEstimate<AxisT...>
1295 return add(std::move(dbn), std::move(est));
1300 template < size_t DbnN, typename... AxisT>
1301 inline BinnedEstimate<AxisT...>
1306 template < size_t DbnN, typename... AxisT>
1307 inline BinnedEstimate<AxisT...>
1312 template < size_t DbnN, typename... AxisT>
1313 inline BinnedEstimate<AxisT...>
1315 return subtract(std::move(dbn), est);
1318 template < size_t DbnN, typename... AxisT>
1319 inline BinnedEstimate<AxisT...>
1321 return subtract(dbn, std::move(est));
1324 template < size_t DbnN, typename... AxisT>
1325 inline BinnedEstimate<AxisT...>
1327 return subtract(std::move(dbn), std::move(est));
1332 template < size_t DbnN, typename... AxisT>
1333 inline BinnedEstimate<AxisT...>
1338 template < size_t DbnN, typename... AxisT>
1339 inline BinnedEstimate<AxisT...>
1344 template < size_t DbnN, typename... AxisT>
1345 inline BinnedEstimate<AxisT...>
1347 return divide(std::move(dbn), est);
1350 template < size_t DbnN, typename... AxisT>
1351 inline BinnedEstimate<AxisT...>
1353 return divide(dbn, std::move(est));
1356 template < size_t DbnN, typename... AxisT>
1357 inline BinnedEstimate<AxisT...>
1359 return divide(std::move(dbn), std::move(est));
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> && ...))>>
1375 const std::string& path = "") {
1378 if ( !((p1 == others) && ...) )
1379 throw BinningError( "Requested zipping of profiles with incompatible binning!");
1383 constexpr size_t N = sizeof...(Args)+1;
1386 for ( const auto& b1 : p1. bins()) {
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.
User-facing BinnedDbn class in arbitrary dimension.
typename BaseT::BinT BinType
BinnedDbn< DbnN, AxisT... > HistoT
HistoT * newclone() const noexcept Make a copy on the heap.
typename BaseT::FillType FillType
BinnedDbn(const BaseT &other) Copy constructor (needed for clone functions).
HistoT clone() const noexcept Make a copy on the stack.
BinnedDbn(const HistoT &)=default
std::shared_ptr< HistoT > Ptr
BinnedDbn(HistoT &&)=default
BinnedDbn(HistoT &&other, const std::string &path)
BinnedDbn(const HistoT &other, const std::string &path)
BinnedDbn(BaseT &&other) Move constructor.
BinnedDbn & operator=(const HistoT &)=default
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.
double RMS(const size_t i) const Weighted RMS, , of distribution.
double mean(const size_t i) const Weighted mean, , of distribution.
double variance(const size_t i) const Weighted variance, , of distribution.
double stdErr(const size_t i) const Weighted standard error on the mean, , of distribution.
All histograms can be instantiated through this alias.
AnalysisObject * mkInert(const std::string &path="", const std::string &source="") const noexcept Return an inert version of the analysis object (e.g. scatter, estimate)
double integralRange(const size_t binIndex1, size_t binIndex2) const Calculates the integrated volume of the histogram between global bins binindex1 and binIndex2.
double rms(size_t axisN, const bool includeOverflows=true) const noexcept Calculates the RMS at axis.
std::enable_if_t< std::is_floating_point< E >::value, E > min() const noexcept Get the lowest non-overflow edge of the axis.
BinnedEstimate< AxisT... > mkEstimate(const std::string &path="", const std::string &source="", const bool divbyvol=true) const Produce a BinnedEstimate from a DbnStorage.
void deserializeContent(const std::vector< double > &data) Content deserialisation for MPI reduce operations.
DbnStorage(Axis< AxisT > &&... axes, const std::string &path="", const std::string &title="") Constructor given a sequence of rvalue axes.
double sumWA(const size_t dim, const bool includeOverflows=true) const Calculates first moment along axis dim in histo.
void reset() noexcept Reset the histogram.
double sumWA2(const size_t dim, const bool includeOverflows=true) const Calculates second moment along axis dim in histo.
DbnStorage(std::initializer_list< AxisT > &&... binsEdges, const std::string &path="", const std::string &title="") Constructor giving explicit bin edges as initializer list.
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.
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.
void normalize(const double normto=1.0, const bool includeOverflows=true) Normalize the (visible) histo "volume" to the normto value.
double stdErr(size_t axisN, const bool includeOverflows=true) const noexcept Calculates the standard error at axis.
double densitySum(const bool includeOverflows=true) const noexcept Returns the sum of the bin densities.
double stdDev(size_t axisN, const bool includeOverflows=true) const noexcept Calculates the standard deviation at axis.
DbnStorage(std::vector< AxisT > &&... binsEdges, const std::string &path="", const std::string &title="") Constructor giving explicit bin edges as rvalue reference.
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.
double numEntries(const bool includeOverflows=true) const noexcept Get the number of fills (fractional fills are possible).
double density(const bool includeOverflows=true) const noexcept Get the total density of the histogram.
auto mkMarginalProfile(const std::string &path="") const Produce a BinnedProfile from a DbnStorage.
std::enable_if_t< std::is_floating_point< E >::value, E > max() const noexcept Get the highest non-overflow edge of the axis.
DbnStorage & operator+=(const DbnStorage &dbn) Add two DbnStorages.
DbnStorage * newclone() const noexcept Make a copy on the heap.
double effNumEntries(const bool includeOverflows=true) const noexcept Get the effective number of fills.
double integralError(const bool includeOverflows=true) const noexcept Get the total volume error of the histogram.
typename BaseT::BinningT BinningT
DbnStorage & operator-=(const DbnStorage &dbn) Subtract one DbnStorages from another one.
FillableStorage< DbnN, Dbn< DbnN >, AxisT... > BaseT
auto mkHistos(const std::string &path="", const bool includeOverflows=false) const Split into vector of BinnedHisto along axis axisN.
auto mkProfiles(const std::string &path="", const bool includeOverflows=false) const Split into vector of BinnedProfile along axis axisN.
double densityError(const bool includeOverflows=true) const noexcept Get the total density error of the histogram.
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.
auto mkMarginalHisto(const std::string &path="") const Produce a BinnedHisto from a DbnStorage.
DbnStorage(const DbnStorage &other, const std::string &path="") Copy constructor.
double dVol(const bool includeOverflows=true) const noexcept
size_t fillDim() const noexcept Fill-dimension of this data object.
void rebin(unsigned int n, size_t begin=1, size_t end=UINT_MAX) Overloaded alias for rebinBy.
DbnStorage(const Axis< AxisT > &... axes, const std::string &path="", const std::string &title="") Constructor given a sequence of axes.
size_t lengthContent(bool=false) const noexcept Length of serialized content vector for MPI reduce operations.
double sumW(const bool includeOverflows=true) const noexcept Calculates sum of weights in histo.
double sumW2(const bool includeOverflows=true) const noexcept Calculates sum of squared weights in histo.
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.
double variance(size_t axisN, const bool includeOverflows=true) const noexcept Calculates the variance at axis.
void scaleW(const double scalefactor) noexcept Rescale as if all fill weights had been different by factor scalefactor.
DbnStorage(BinningT &&binning, const std::string &path="", const std::string &title="") Constructor given an rvalue BinningT.
typename BaseT::BinT BinType
DbnStorage clone() const noexcept Make a copy on the stack.
typename BaseT::BinT BinT
virtual int fill(FillType &&coords, const double weight=1.0, const double fraction=1.0) Triggers fill adapter on the bin corresponding to coords.
DbnStorage(const std::vector< AxisT > &... binsEdges, const std::string &path="", const std::string &title="") Constructor giving explicit bin edges as lvalue const reference.
typename BaseT::FillType FillType
double integralTo(const size_t binIndex) const noexcept Get the total volume of the histogram.
double integral(const bool includeOverflows=true) const noexcept Get the total volume of the histogram.
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.
DbnStorage(const BinningT &binning, const std::string &path="", const std::string &title="") Constructor given a BinningT (needed for type reductions)
BinnedHisto< AxisT... > mkHisto(const std::string &path="") const Produce a BinnedHisto from BinnedProfile.
double mean(size_t axisN, const bool includeOverflows=true) const noexcept Calculates the mean value at axis.
DbnStorage(const ScatterND< sizeof...(AxisT)+1 > &s, const std::string &path="", const std::string &title="") Constructor given a scatter.
std::vector< E > edges(const bool includeOverflows=false) const noexcept Returns the edges of axis N by value.
double integralRangeError(const size_t binIndex1, size_t binIndex2) const Calculates the integrated volume error of the histogram between global bins binindex1 and binIndex2.
std::vector< double > serializeContent(bool=false) const noexcept Content serialisation for MPI reduce operations.
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.
DbnStorage() Nullary constructor for unique pointers etc.
double maxDensity(const bool includeOverflows=true) const noexcept Returns the largest density in any of the bins.
void rebin(const std::vector< typename BinningT::template getAxisT< axisN >::EdgeT > &newedges) Overloaded alias for rebinTo.
void rebinTo(const std::vector< typename BinningT::template getAxisT< axisN >::EdgeT > &newedges) Rebin to the given list of bin edges.
size_t dim() const noexcept Total dimension of the object (number of axes + filled value)
DbnStorage & operator=(const DbnStorage &dbn) noexcept Copy assignment.
DbnStorage(DbnStorage &&other, const std::string &path="") Move constructor.
User-facing Dbn class inheriting from DbnBase.
typename BaseT::BinningT BinningT
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
void reset() noexcept Reset the Fillable.
A base class for all fillable objects.
Errors relating to insufficient (effective) statistics.
Error for e.g. use of invalid bin ranges.
A generic data type which is just a collection of n-dim data points with errors.
PointND< N > & point(size_t index) Get a reference to the point with index index.
ScatterND< N > & addPoint(const PointND< N > &pt) Insert a new point.
Utils::ndarray< double, N > NdVal
Error for problems introduced outside YODA, to put it nicely.
Errors relating to event/bin weights.
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.
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.
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.
BinnedEstimate< AxisT... > operator/(const BinnedDbn< DbnN, AxisT... > &numer, const BinnedDbn< DbnN, AxisT... > &denom)
BinnedEstimate< AxisT... > mkIntegral(const BinnedDbn< DbnN, AxisT... > &histo, const bool includeOverflows=true) Convert a Histo1D to a Scatter2D representing the integral of the histogram.
NUM sqr(NUM a) Named number-type squaring operation.
BinnedEstimate< AxisT... > efficiency(const BinnedDbn< DbnN, AxisT... > &accepted, const BinnedDbn< DbnN, AxisT... > &total) Calculate a binned efficiency ratio of two BinnedDbn objects.
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.
BinnedEstimate< AxisT... > asymm(const BinnedDbn< DbnN, AxisT... > &a, const BinnedDbn< DbnN, AxisT... > &b) Calculate the asymmetry (a-b)/(a+b) of two BinnedDbn objects.
BinnedEstimate< AxisT... > add(const BinnedDbn< DbnN, AxisT... > &dbn, const BinnedEstimate< AxisT... > &est) Calculate the addition of a BinnedDbn with a BinnedEstimate.
BinnedEstimate< AxisT... > subtract(const BinnedDbn< DbnN, AxisT... > &dbn, const BinnedEstimate< AxisT... > &est) Calculate the subtraction of a BinnedEstimate from a BinnedDbn.
BinnedDbn< DbnN, AxisT... > operator-(BinnedDbn< DbnN, AxisT... > first, BinnedDbn< DbnN, AxisT... > &&second) Subtract one BinnedDbn object from another.
BinnedEstimate< AxisT... > divide(const BinnedDbn< DbnN, AxisT... > &numer, const BinnedDbn< DbnN, AxisT... > &denom) Divide two BinnedDbn objects.
double mean(const std::vector< int > &sample) Calculate the mean of a sample.
|