Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RVariableBinAxis.hxx
Go to the documentation of this file.
1/// \file
2/// \warning This is part of the %ROOT 7 prototype! It will change without notice. It might trigger earthquakes.
3/// Feedback is welcome!
4
5#ifndef ROOT_RVariableBinAxis
6#define ROOT_RVariableBinAxis
7
8#include "RBinIndex.hxx"
9#include "RBinIndexRange.hxx"
10#include "RLinearizedIndex.hxx"
11
12#include <cassert>
13#include <cmath>
14#include <cstddef>
15#include <cstdint>
16#include <stdexcept>
17#include <string>
18#include <utility>
19#include <vector>
20
21class TBuffer;
22
23namespace ROOT {
24namespace Experimental {
25
26/**
27An axis with variable bins defined by their edges.
28
29For example, the following creates an axis with 3 log-spaced bins:
30\code
31std::vector<double> binEdges = {1, 10, 100, 1000};
32ROOT::Experimental::RVariableBinAxis axis(binEdges);
33\endcode
34
35It is possible to disable underflow and overflow bins by passing `enableFlowBins = false`. In that case, arguments
36outside the axis will be silently discarded.
37
38\warning This is part of the %ROOT 7 prototype! It will change without notice. It might trigger earthquakes.
39Feedback is welcome!
40*/
42public:
44
45private:
46 /// The (ordered) edges of the normal bins
47 std::vector<double> fBinEdges;
48 /// Whether underflow and overflow bins are enabled
50
51public:
52 /// Construct an axis object with variable bins.
53 ///
54 /// \param[in] binEdges the (ordered) edges of the normal bins, must define at least one bin (i.e. size >= 2)
55 /// \param[in] enableFlowBins whether to enable underflow and overflow bins
56 explicit RVariableBinAxis(std::vector<double> binEdges, bool enableFlowBins = true)
58 {
59 if (fBinEdges.size() < 2) {
60 throw std::invalid_argument("must have >= 2 bin edges");
61 }
62 if (std::isnan(fBinEdges[0])) {
63 throw std::invalid_argument("bin egde 0 is NaN");
64 }
65 for (std::size_t i = 1; i < fBinEdges.size(); i++) {
66 if (std::isnan(fBinEdges[i])) {
67 throw std::invalid_argument("bin egde " + std::to_string(i) + " is NaN");
68 }
69 if (fBinEdges[i - 1] >= fBinEdges[i]) {
70 std::string msg = "binEdges must be sorted, but for bin " + std::to_string(i - 1) + ": ";
71 msg += std::to_string(fBinEdges[i - 1]) + " >= " + std::to_string(fBinEdges[i]);
72 throw std::invalid_argument(msg);
73 }
74 }
75 }
76
77 std::uint64_t GetNNormalBins() const { return fBinEdges.size() - 1; }
78 std::uint64_t GetTotalNBins() const { return fEnableFlowBins ? fBinEdges.size() + 1 : fBinEdges.size() - 1; }
79 const std::vector<double> &GetBinEdges() const { return fBinEdges; }
80 bool HasFlowBins() const { return fEnableFlowBins; }
81
83 {
84 return lhs.fBinEdges == rhs.fBinEdges && lhs.fEnableFlowBins == rhs.fEnableFlowBins;
85 }
86
87 /// Compute the linarized index for a single argument.
88 ///
89 /// If flow bins are disabled, the normal bins have indices \f$0\f$ to \f$fBinEdges.size() - 2\f$. Otherwise the
90 /// underflow bin has index \f$0\$, the indices of all normal bins shift by one, and the overflow bin has index
91 /// \f$fBinEdges.size()\f$. If the argument is outside all bin edges and the flow bins are disabled, the return value
92 /// is invalid.
93 ///
94 /// \param[in] x the argument
95 /// \return the linearized index that may be invalid
96 RLinearizedIndex ComputeLinearizedIndex(double x) const
97 {
98 bool underflow = x < fBinEdges.front();
99 // Put NaNs into overflow bin.
100 bool overflow = !(x < fBinEdges.back());
101 if (underflow) {
102 return {0, fEnableFlowBins};
103 } else if (overflow) {
104 return {fBinEdges.size(), fEnableFlowBins};
105 }
106
107 // TODO (for later): The following can be optimized with binary search...
108 for (std::size_t bin = 0; bin < fBinEdges.size() - 2; bin++) {
109 if (x < fBinEdges[bin + 1]) {
110 // If the underflow bin is enabled, shift the normal bins by one.
111 if (fEnableFlowBins) {
112 bin += 1;
113 }
114 return {bin, true};
115 }
116 }
117 std::size_t bin = fBinEdges.size() - 2;
118 // If the underflow bin is enabled, shift the normal bins by one.
119 if (fEnableFlowBins) {
120 bin += 1;
121 }
122 return {bin, true};
123 }
124
125 /// Get the linearized index for an RBinIndex.
126 ///
127 /// If flow bins are disabled, the normal bins have indices \f$0\f$ to \f$fBinEdges.size() - 2\f$. Otherwise the
128 /// underflow bin has index \f$0\$, the indices of all normal bins shift by one, and the overflow bin has index
129 /// \f$fBinEdges.size()\f$.
130 ///
131 /// \param[in] index the RBinIndex
132 /// \return the linearized index that may be invalid
134 {
135 if (index.IsUnderflow()) {
136 return {0, fEnableFlowBins};
137 } else if (index.IsOverflow()) {
138 return {fBinEdges.size(), fEnableFlowBins};
139 } else if (index.IsInvalid()) {
140 return {0, false};
141 }
142 assert(index.IsNormal());
143 std::uint64_t bin = index.GetIndex();
144 if (bin >= fBinEdges.size() - 1) {
145 // Index is out of range and invalid.
146 return {bin, false};
147 }
148 // If the underflow bin is enabled, shift the normal bins by one.
149 if (fEnableFlowBins) {
150 bin += 1;
151 }
152 return {bin, true};
153 }
154
155 /// Get the range of all normal bins.
156 ///
157 /// \return the bin index range from the first to the last normal bin, inclusive
159 {
161 }
162
163 /// Get a range of normal bins.
164 ///
165 /// \param[in] begin the begin of the bin index range (inclusive), must be normal
166 /// \param[in] end the end of the bin index range (exclusive), must be normal and >= begin
167 /// \return a bin index range \f$[begin, end)\f$
169 {
170 if (!begin.IsNormal()) {
171 throw std::invalid_argument("begin must be a normal bin");
172 }
173 if (begin.GetIndex() >= fBinEdges.size() - 1) {
174 throw std::invalid_argument("begin must be inside the axis");
175 }
176 if (!end.IsNormal()) {
177 throw std::invalid_argument("end must be a normal bin");
178 }
179 if (end.GetIndex() > fBinEdges.size() - 1) {
180 throw std::invalid_argument("end must be inside or past the axis");
181 }
182 if (!(end >= begin)) {
183 throw std::invalid_argument("end must be >= begin");
184 }
185 return Internal::CreateBinIndexRange(begin, end, 0);
186 }
187
188 /// Get the full range of all bins.
189 ///
190 /// This includes underflow and overflow bins, if enabled.
191 ///
192 /// \return the bin index range of all bins
198
199 /// %ROOT Streamer function to throw when trying to store an object of this class.
200 void Streamer(TBuffer &) { throw std::runtime_error("unable to store RVariableBinAxis"); }
201};
202
203} // namespace Experimental
204} // namespace ROOT
205
206#endif
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t index
A bin index with special values for underflow and overflow bins.
Definition RBinIndex.hxx:23
bool IsNormal() const
A bin index is normal iff it is not one of the special values.
Definition RBinIndex.hxx:80
std::uint64_t GetIndex() const
Return the index for a normal bin.
Definition RBinIndex.hxx:71
static RBinIndex Underflow()
An axis with variable bins defined by their edges.
RLinearizedIndex GetLinearizedIndex(RBinIndex index) const
Compute the linarized index for a single argument.
RBinIndexRange GetNormalRange(RBinIndex begin, RBinIndex end) const
Get a range of normal bins.
RBinIndexRange GetFullRange() const
Get the full range of all bins.
bool fEnableFlowBins
Whether underflow and overflow bins are enabled.
void Streamer(TBuffer &)
ROOT Streamer function to throw when trying to store an object of this class.
std::vector< double > fBinEdges
The (ordered) edges of the normal bins.
RVariableBinAxis(std::vector< double > binEdges, bool enableFlowBins=true)
Construct an axis object with variable bins.
friend bool operator==(const RVariableBinAxis &lhs, const RVariableBinAxis &rhs)
const std::vector< double > & GetBinEdges() const
RBinIndexRange GetNormalRange() const
Get the range of all normal bins.
Buffer base class used for serializing objects.
Definition TBuffer.h:43
Double_t x[n]
Definition legend1.C:17
static RBinIndexRange CreateBinIndexRange(RBinIndex begin, RBinIndex end, std::uint64_t nNormalBins)
Internal function to create RBinIndexRange.
A linearized index that can be invalid.