File indexing completed on 2025-12-14 10:31:21
0001
0002
0003
0004
0005 #ifndef ROOT_RVariableBinAxis
0006 #define ROOT_RVariableBinAxis
0007
0008 #include "RBinIndex.hxx"
0009 #include "RBinIndexRange.hxx"
0010 #include "RLinearizedIndex.hxx"
0011
0012 #include <cassert>
0013 #include <cstddef>
0014 #include <stdexcept>
0015 #include <string>
0016 #include <utility>
0017 #include <vector>
0018
0019 class TBuffer;
0020
0021 namespace ROOT {
0022 namespace Experimental {
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039 class RVariableBinAxis final {
0040 public:
0041 using ArgumentType = double;
0042
0043 private:
0044
0045 std::vector<double> fBinEdges;
0046
0047 bool fEnableFlowBins;
0048
0049 public:
0050
0051
0052
0053
0054 explicit RVariableBinAxis(std::vector<double> binEdges, bool enableFlowBins = true)
0055 : fBinEdges(std::move(binEdges)), fEnableFlowBins(enableFlowBins)
0056 {
0057 if (fBinEdges.size() < 2) {
0058 throw std::invalid_argument("must have >= 2 bin edges");
0059 }
0060 for (std::size_t i = 1; i < fBinEdges.size(); i++) {
0061 if (fBinEdges[i - 1] >= fBinEdges[i]) {
0062 std::string msg = "binEdges must be sorted, but for bin " + std::to_string(i - 1) + ": ";
0063 msg += std::to_string(fBinEdges[i - 1]) + " >= " + std::to_string(fBinEdges[i]);
0064 throw std::invalid_argument(msg);
0065 }
0066 }
0067 }
0068
0069 std::size_t GetNNormalBins() const { return fBinEdges.size() - 1; }
0070 std::size_t GetTotalNBins() const { return fEnableFlowBins ? fBinEdges.size() + 1 : fBinEdges.size() - 1; }
0071 const std::vector<double> &GetBinEdges() const { return fBinEdges; }
0072 bool HasFlowBins() const { return fEnableFlowBins; }
0073
0074 friend bool operator==(const RVariableBinAxis &lhs, const RVariableBinAxis &rhs)
0075 {
0076 return lhs.fBinEdges == rhs.fBinEdges && lhs.fEnableFlowBins == rhs.fEnableFlowBins;
0077 }
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087 RLinearizedIndex ComputeLinearizedIndex(double x) const
0088 {
0089 bool underflow = x < fBinEdges.front();
0090
0091 bool overflow = !(x < fBinEdges.back());
0092 if (underflow) {
0093 return {fBinEdges.size() - 1, fEnableFlowBins};
0094 } else if (overflow) {
0095 return {fBinEdges.size(), fEnableFlowBins};
0096 }
0097
0098
0099 for (std::size_t bin = 0; bin < fBinEdges.size() - 2; bin++) {
0100 if (x < fBinEdges[bin + 1]) {
0101 return {bin, true};
0102 }
0103 }
0104 std::size_t bin = fBinEdges.size() - 2;
0105 return {bin, true};
0106 }
0107
0108
0109
0110
0111
0112
0113
0114
0115 RLinearizedIndex GetLinearizedIndex(RBinIndex index) const
0116 {
0117 if (index.IsUnderflow()) {
0118 return {fBinEdges.size() - 1, fEnableFlowBins};
0119 } else if (index.IsOverflow()) {
0120 return {fBinEdges.size(), fEnableFlowBins};
0121 } else if (index.IsInvalid()) {
0122 return {0, false};
0123 }
0124 assert(index.IsNormal());
0125 std::size_t bin = index.GetIndex();
0126 return {bin, bin < fBinEdges.size() - 1};
0127 }
0128
0129
0130
0131
0132 RBinIndexRange GetNormalRange() const
0133 {
0134 return Internal::CreateBinIndexRange(RBinIndex(0), RBinIndex(fBinEdges.size() - 1), 0);
0135 }
0136
0137
0138
0139
0140
0141
0142 RBinIndexRange GetNormalRange(RBinIndex begin, RBinIndex end) const
0143 {
0144 if (!begin.IsNormal()) {
0145 throw std::invalid_argument("begin must be a normal bin");
0146 }
0147 if (begin.GetIndex() >= fBinEdges.size() - 1) {
0148 throw std::invalid_argument("begin must be inside the axis");
0149 }
0150 if (!end.IsNormal()) {
0151 throw std::invalid_argument("end must be a normal bin");
0152 }
0153 if (end.GetIndex() > fBinEdges.size() - 1) {
0154 throw std::invalid_argument("end must be inside or past the axis");
0155 }
0156 if (!(end >= begin)) {
0157 throw std::invalid_argument("end must be >= begin");
0158 }
0159 return Internal::CreateBinIndexRange(begin, end, 0);
0160 }
0161
0162
0163
0164
0165
0166
0167 RBinIndexRange GetFullRange() const
0168 {
0169 return fEnableFlowBins ? Internal::CreateBinIndexRange(RBinIndex::Underflow(), RBinIndex(), fBinEdges.size() - 1)
0170 : GetNormalRange();
0171 }
0172
0173
0174 void Streamer(TBuffer &) { throw std::runtime_error("unable to store RVariableBinAxis"); }
0175 };
0176
0177 }
0178 }
0179
0180 #endif