|
YODA - Yet more Objects for Data Analysis 2.0.0
|
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 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() && b.numEntries() == 0) continue;
776 const double scale = divbyvol? b.dVol() : 1.0;
778 if constexpr(DbnN > sizeof...(AxisT)) {
779 v = b.mean(DbnN) / scale;
780 e = b.stdErr(DbnN) / scale;
783 v = b.sumW() / scale;
784 e = b.errW() / scale;
786 rtn.bin(b.index()). set(v, e, source);
796 template< size_t axisN, typename = std::enable_if_t< (axisN < sizeof...(AxisT)) >>
798 const bool divbyvol= true, const bool includeOverflows= false) {
801 return est.template mkEstimates<axisN>( path, includeOverflows);
807 const bool usefocus= false,
808 const bool includeOverflows= false,
809 const bool includeMaskedBins= false) const {
811 ScatterND< sizeof...(AxisT)+1> rtn = est.mkScatter( path, includeOverflows, includeMaskedBins);
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);
824 MetaUtils::staticFor<BinningT::Dimension::value>(shiftIfContinuous);
835 template< size_t N = DbnN, typename = std::enable_if_t< (N == sizeof...(AxisT)+1) >>
841 if (a != "Type") rtn.setAnnotation(a, annotation(a));
843 rtn.setAnnotation( "Path", path);
846 rtn.bin(b.index()) += b.template reduce<N-1>();
863 template< size_t axisN, typename = std::enable_if_t< (axisN < sizeof...(AxisT)) >>
866 auto rtn = BaseT::template _mkBinnedT<BinnedProfile>(BaseT::_binning. template _getAxesExcept<axisN>());
869 if (a != "Type") rtn.setAnnotation(a, annotation(a));
871 rtn.setAnnotation( "Path", path);
873 auto collapseStorageBins =
874 [&oldBinning = BaseT::_binning, &oldBins = BaseT::_bins, &rtn]( auto I, auto dbnRed) {
876 auto collapse = [&oldBins, &rtn]( const auto& binsIndicesToMerge, auto axis) {
877 assert(rtn.numBins( true) == binsIndicesToMerge.size());
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>();
890 ssize_t nBinRowsToBeMerged = oldBinning.numBinsAt(I);
891 while (nBinRowsToBeMerged--) {
894 collapse(oldBinning.sliceIndices(I, nBinRowsToBeMerged), dbnRed);
900 auto dbnRed = std::integral_constant<size_t, ( sizeof...(AxisT) == DbnN)? DbnN : axisN>();
901 (void)collapseStorageBins(std::integral_constant<std::size_t, axisN>(), dbnRed);
917 template< size_t axisN, typename = std::enable_if_t< (axisN < sizeof...(AxisT)) >>
920 if constexpr (DbnN != sizeof...(AxisT)) {
922 return mkHisto().template mkMarginalHisto<axisN>( path);
927 auto rtn = BaseT::template _mkBinnedT<BinnedHisto>(BaseT::_binning. template _getAxesExcept<axisN>());
930 if (a != "Type") rtn.setAnnotation(a, annotation(a));
932 rtn.setAnnotation( "Path", path);
934 auto collapseStorageBins =
935 [&oldBinning = BaseT::_binning, &oldBins = BaseT::_bins, &rtn]( auto I, auto dbnRed) {
937 auto collapse = [&oldBins, &rtn]( const auto& binsIndicesToMerge, auto axis) {
938 assert(rtn.numBins( true) == binsIndicesToMerge.size());
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>();
951 ssize_t nBinRowsToBeMerged = oldBinning.numBinsAt(I);
952 while (nBinRowsToBeMerged--) {
955 collapse(oldBinning.sliceIndices(I, nBinRowsToBeMerged), dbnRed);
959 auto dbnRed = std::integral_constant<size_t, axisN>();
960 (void)collapseStorageBins(std::integral_constant<std::size_t, axisN>(), dbnRed);
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 {
977 auto how2add = []( auto& pivot, const BinType& toCopy) { pivot = toCopy.template reduce<axisN>(); };
978 auto rtn = BaseT::template mkBinnedSlices<axisN, BinnedProfile>(how2add, includeOverflows);
980 if (a == "Type") continue;
981 for ( size_t i = 0; i < rtn.size(); ++i) {
985 for ( size_t i = 0; i < rtn.size(); ++i) {
986 rtn[i].setAnnotation( "Path", path);
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 {
999 if constexpr (DbnN != sizeof...(AxisT)) {
1001 return mkHisto().template mkHistos<axisN>( path, includeOverflows);
1007 auto how2add = []( auto& pivot, const BinType& toCopy) { pivot = toCopy.template reduce<axisN>(); };
1008 auto rtn = BaseT::template mkBinnedSlices<axisN,BinnedHisto>(how2add, includeOverflows);
1010 if (a == "Type") continue;
1011 for ( size_t i = 0; i < rtn.size(); ++i) {
1015 for ( size_t i = 0; i < rtn.size(); ++i) {
1016 rtn[i].setAnnotation( "Path", path);
1025 const std::string& source = "") const noexcept {
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))...});
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))...);
1056 template< size_t DbnN, typename... AxisT>
1057 inline BinnedDbn<DbnN, AxisT...>
1059 first += std::move(second);
1063 template < size_t DbnN, typename... AxisT>
1064 inline BinnedDbn<DbnN, AxisT...>
1072 template < size_t DbnN, typename... AxisT>
1073 inline BinnedDbn<DbnN, AxisT...>
1075 first -= std::move(second);
1079 template < size_t DbnN, typename... AxisT>
1080 inline BinnedDbn<DbnN, AxisT...>
1088 template < size_t DbnN, typename... AxisT>
1089 inline BinnedEstimate<AxisT...>
1092 if (numer != denom) {
1093 throw BinningError( "Arithmetic operation requires compatible binning!");
1097 if (numer. path() == denom. path()) rtn.setPath(numer. path());
1098 if (rtn.hasAnnotation( "ScaledBy")) rtn.rmAnnotation( "ScaledBy");
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);
1104 if (!b_den.effNumEntries()) {
1105 v = std::numeric_limits<double>::quiet_NaN();
1106 e = std::numeric_limits<double>::quiet_NaN();
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));
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));
1122 rtn.bin(idx).set(v, {-e, e});
1129 template < size_t DbnN, typename... AxisT>
1130 inline BinnedEstimate<AxisT...>
1132 return divide(numer, denom);
1135 template < size_t DbnN, typename... AxisT>
1136 inline BinnedEstimate<AxisT...>
1138 return divide(numer, std::move(denom));
1141 template < size_t DbnN, typename... AxisT>
1142 inline BinnedEstimate<AxisT...>
1144 return divide(std::move(numer), denom);
1147 template < size_t DbnN, typename... AxisT>
1148 inline BinnedEstimate<AxisT...>
1150 return divide(std::move(numer), std::move(denom));
1158 template < size_t DbnN, typename... AxisT>
1159 inline BinnedEstimate<AxisT...>
1162 if (accepted != total) {
1163 throw BinningError( "Arithmetic operation requires compatible binning!");
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());
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");
1179 double eff = std::numeric_limits<double>::quiet_NaN();
1180 double err = std::numeric_limits<double>::quiet_NaN();
1184 err = sqrt(abs( ((1-2*eff)*b_acc.sumW2() + sqr(eff)*b_tot.sumW2()) / sqr(b_tot.sumW()) ));
1190 b_rtn.setErr({-err, err});
1197 template < size_t DbnN, typename... AxisT>
1198 inline BinnedEstimate<AxisT...>
1200 return (a-b) / (a+b);
1212 template < size_t DbnN, typename... AxisT>
1213 inline BinnedEstimate<AxisT...>
1218 double sumW = 0.0, sumW2 = 0.0;
1219 for ( const auto& b : histo. bins(includeOverflows)) {
1222 const double e = sqrt(sumW2);
1223 rtn.bin(b.index()).set(sumW, {-e, e});
1241 template < size_t DbnN, typename... AxisT>
1242 inline BinnedEstimate<AxisT...>
1246 const double integral = histo. integral(includeOverflows);
1252 if (!integral) return rtn;
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});
1266 template < size_t DbnN, typename... AxisT>
1267 inline BinnedEstimate<AxisT...>
1272 template < size_t DbnN, typename... AxisT>
1273 inline BinnedEstimate<AxisT...>
1275 return add(dbn, est);
1278 template < size_t DbnN, typename... AxisT>
1279 inline BinnedEstimate<AxisT...>
1281 return add(std::move(dbn), est);
1284 template < size_t DbnN, typename... AxisT>
1285 inline BinnedEstimate<AxisT...>
1287 return add(dbn, std::move(est));
1290 template < size_t DbnN, typename... AxisT>
1291 inline BinnedEstimate<AxisT...>
1293 return add(std::move(dbn), std::move(est));
1298 template < size_t DbnN, typename... AxisT>
1299 inline BinnedEstimate<AxisT...>
1304 template < size_t DbnN, typename... AxisT>
1305 inline BinnedEstimate<AxisT...>
1310 template < size_t DbnN, typename... AxisT>
1311 inline BinnedEstimate<AxisT...>
1313 return subtract(std::move(dbn), est);
1316 template < size_t DbnN, typename... AxisT>
1317 inline BinnedEstimate<AxisT...>
1319 return subtract(dbn, std::move(est));
1322 template < size_t DbnN, typename... AxisT>
1323 inline BinnedEstimate<AxisT...>
1325 return subtract(std::move(dbn), std::move(est));
1330 template < size_t DbnN, typename... AxisT>
1331 inline BinnedEstimate<AxisT...>
1336 template < size_t DbnN, typename... AxisT>
1337 inline BinnedEstimate<AxisT...>
1342 template < size_t DbnN, typename... AxisT>
1343 inline BinnedEstimate<AxisT...>
1345 return divide(std::move(dbn), est);
1348 template < size_t DbnN, typename... AxisT>
1349 inline BinnedEstimate<AxisT...>
1351 return divide(dbn, std::move(est));
1354 template < size_t DbnN, typename... AxisT>
1355 inline BinnedEstimate<AxisT...>
1357 return divide(std::move(dbn), std::move(est));
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.
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.
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.
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.
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.
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.
|