Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RHistEngine.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_RHistEngine
6#define ROOT_RHistEngine
7
8#include "RAxes.hxx"
9#include "RBinIndex.hxx"
10#include "RBinWithError.hxx"
11#include "RHistUtils.hxx"
12#include "RLinearizedIndex.hxx"
13#include "RRegularAxis.hxx"
14#include "RWeight.hxx"
15
16#include <array>
17#include <cassert>
18#include <stdexcept>
19#include <tuple>
20#include <type_traits>
21#include <utility>
22#include <vector>
23
24class TBuffer;
25
26namespace ROOT {
27namespace Experimental {
28
29/**
30A histogram data structure to bin data along multiple dimensions.
31
32Every call to \ref Fill(const A &... args) "Fill" bins the data according to the axis configuration and increments the
33bin content:
34\code
35ROOT::Experimental::RHistEngine<int> hist(10, 5, 15);
36hist.Fill(8.5);
37// hist.GetBinContent(ROOT::Experimental::RBinIndex(3)) will return 1
38\endcode
39
40The class is templated on the bin content type. For counting, as in the example above, it may be an integer type such as
41`int` or `long`. Narrower types such as `unsigned char` or `short` are supported, but may overflow due to their limited
42range and must be used with care. For weighted filling, the bin content type must be a floating-point type such as
43`float` or `double`, or the special type RBinWithError. Note that `float` has a limited significant precision of 24
44bits.
45
46An object can have arbitrary dimensionality determined at run-time. The axis configuration is passed as a vector of
47RAxisVariant:
48\code
49std::vector<ROOT::Experimental::RAxisVariant> axes;
50axes.push_back(ROOT::Experimental::RRegularAxis(10, 5, 15));
51axes.push_back(ROOT::Experimental::RVariableBinAxis({1, 10, 100, 1000}));
52ROOT::Experimental::RHistEngine<int> hist(axes);
53// hist.GetNDimensions() will return 2
54\endcode
55
56\warning This is part of the %ROOT 7 prototype! It will change without notice. It might trigger earthquakes.
57Feedback is welcome!
58*/
59template <typename BinContentType>
61 /// The axis configuration for this histogram. Relevant methods are forwarded from the public interface.
63 /// The bin contents for this histogram
64 std::vector<BinContentType> fBinContents;
65
66public:
67 /// Construct a histogram engine.
68 ///
69 /// \param[in] axes the axis objects, must have size > 0
70 explicit RHistEngine(std::vector<RAxisVariant> axes) : fAxes(std::move(axes))
71 {
73 }
74
75 /// Construct a one-dimensional histogram engine with a regular axis.
76 ///
77 /// \param[in] nNormalBins the number of normal bins, must be > 0
78 /// \param[in] low the lower end of the axis interval (inclusive)
79 /// \param[in] high the upper end of the axis interval (exclusive), must be > low
80 /// \par See also
81 /// the \ref RRegularAxis::RRegularAxis(std::size_t nNormalBins, double low, double high, bool enableFlowBins)
82 /// "constructor of RRegularAxis"
83 RHistEngine(std::size_t nNormalBins, double low, double high) : RHistEngine({RRegularAxis(nNormalBins, low, high)})
84 {
85 }
86
87 /// The copy constructor is deleted.
88 ///
89 /// Copying all bin contents can be an expensive operation, depending on the number of bins. If required, users can
90 /// explicitly call Clone().
92 /// Efficiently move construct a histogram engine.
93 ///
94 /// After this operation, the moved-from object is invalid.
96
97 /// The copy assignment operator is deleted.
98 ///
99 /// Copying all bin contents can be an expensive operation, depending on the number of bins. If required, users can
100 /// explicitly call Clone().
102 /// Efficiently move a histogram engine.
103 ///
104 /// After this operation, the moved-from object is invalid.
106
107 ~RHistEngine() = default;
108
109 const std::vector<RAxisVariant> &GetAxes() const { return fAxes.Get(); }
110 std::size_t GetNDimensions() const { return fAxes.GetNDimensions(); }
111 std::size_t GetTotalNBins() const { return fBinContents.size(); }
112
113 /// Get the content of a single bin.
114 ///
115 /// \code
116 /// ROOT::Experimental::RHistEngine<int> hist({/* two dimensions */});
117 /// std::array<ROOT::Experimental::RBinIndex, 2> indices = {3, 5};
118 /// int content = hist.GetBinContent(indices);
119 /// \endcode
120 ///
121 /// \note Compared to TH1 conventions, the first normal bin has index 0 and underflow and overflow bins are special
122 /// values. See also the class documentation of RBinIndex.
123 ///
124 /// Throws an exception if the number of indices does not match the axis configuration or the bin is not found.
125 ///
126 /// \param[in] indices the array of indices for each axis
127 /// \return the bin content
128 /// \par See also
129 /// the \ref GetBinContent(const A &... args) const "variadic function template overload" accepting arguments
130 /// directly
131 template <std::size_t N>
132 const BinContentType &GetBinContent(const std::array<RBinIndex, N> &indices) const
133 {
134 // We could rely on RAxes::ComputeGlobalIndex to check the number of arguments, but its exception message might
135 // be confusing for users.
136 if (N != GetNDimensions()) {
137 throw std::invalid_argument("invalid number of indices passed to GetBinContent");
138 }
140 if (!index.fValid) {
141 throw std::invalid_argument("bin not found in GetBinContent");
142 }
143 assert(index.fIndex < fBinContents.size());
144 return fBinContents[index.fIndex];
145 }
146
147 /// Get the content of a single bin.
148 ///
149 /// \code
150 /// ROOT::Experimental::RHistEngine<int> hist({/* two dimensions */});
151 /// int content = hist.GetBinContent(ROOT::Experimental::RBinIndex(3), ROOT::Experimental::RBinIndex(5));
152 /// // ... or construct the RBinIndex arguments implicitly from integers:
153 /// content = hist.GetBinContent(3, 5);
154 /// \endcode
155 ///
156 /// \note Compared to TH1 conventions, the first normal bin has index 0 and underflow and overflow bins are special
157 /// values. See also the class documentation of RBinIndex.
158 ///
159 /// Throws an exception if the number of arguments does not match the axis configuration or the bin is not found.
160 ///
161 /// \param[in] args the arguments for each axis
162 /// \return the bin content
163 /// \par See also
164 /// the \ref GetBinContent(const std::array<RBinIndex, N> &indices) const "function overload" accepting
165 /// `std::array`
166 template <typename... A>
167 const BinContentType &GetBinContent(const A &...args) const
168 {
169 std::array<RBinIndex, sizeof...(A)> indices{args...};
170 return GetBinContent(indices);
171 }
172
173 /// Add all bin contents of another histogram.
174 ///
175 /// Throws an exception if the axes configurations are not identical.
176 ///
177 /// \param[in] other another histogram
179 {
180 if (fAxes != other.fAxes) {
181 throw std::invalid_argument("axes configurations not identical in Add");
182 }
183 for (std::size_t i = 0; i < fBinContents.size(); i++) {
184 fBinContents[i] += other.fBinContents[i];
185 }
186 }
187
188 /// Clear all bin contents.
189 void Clear()
190 {
191 for (std::size_t i = 0; i < fBinContents.size(); i++) {
192 fBinContents[i] = {};
193 }
194 }
195
196 /// Clone this histogram engine.
197 ///
198 /// Copying all bin contents can be an expensive operation, depending on the number of bins.
199 ///
200 /// \return the cloned object
202 {
204 for (std::size_t i = 0; i < fBinContents.size(); i++) {
205 h.fBinContents[i] = fBinContents[i];
206 }
207 return h;
208 }
209
210 /// Whether this histogram engine type supports weighted filling.
211 static constexpr bool SupportsWeightedFilling =
212 std::is_floating_point_v<BinContentType> || std::is_same_v<BinContentType, RBinWithError>;
213
214 /// Fill an entry into the histogram.
215 ///
216 /// \code
217 /// ROOT::Experimental::RHistEngine<int> hist({/* two dimensions */});
218 /// auto args = std::make_tuple(8.5, 10.5);
219 /// hist.Fill(args);
220 /// \endcode
221 ///
222 /// If one of the arguments is outside the corresponding axis and flow bins are disabled, the entry will be silently
223 /// discarded.
224 ///
225 /// Throws an exception if the number of arguments does not match the axis configuration.
226 ///
227 /// \param[in] args the arguments for each axis
228 /// \par See also
229 /// the \ref Fill(const A &... args) "variadic function template overload" accepting arguments directly and the
230 /// \ref Fill(const std::tuple<A...> &args, RWeight weight) "overload for weighted filling"
231 template <typename... A>
232 void Fill(const std::tuple<A...> &args)
233 {
234 // We could rely on RAxes::ComputeGlobalIndex to check the number of arguments, but its exception message might
235 // be confusing for users.
236 if (sizeof...(A) != GetNDimensions()) {
237 throw std::invalid_argument("invalid number of arguments to Fill");
238 }
240 if (index.fValid) {
241 assert(index.fIndex < fBinContents.size());
242 fBinContents[index.fIndex]++;
243 }
244 }
245
246 /// Fill an entry into the histogram with a weight.
247 ///
248 /// This overload is only available for floating-point bin content types (see \ref SupportsWeightedFilling).
249 ///
250 /// \code
251 /// ROOT::Experimental::RHistEngine<float> hist({/* two dimensions */});
252 /// auto args = std::make_tuple(8.5, 10.5);
253 /// hist.Fill(args, ROOT::Experimental::RWeight(0.8));
254 /// \endcode
255 ///
256 /// If one of the arguments is outside the corresponding axis and flow bins are disabled, the entry will be silently
257 /// discarded.
258 ///
259 /// Throws an exception if the number of arguments does not match the axis configuration.
260 ///
261 /// \param[in] args the arguments for each axis
262 /// \param[in] weight the weight for this entry
263 /// \par See also
264 /// the \ref Fill(const A &... args) "variadic function template overload" accepting arguments directly and the
265 /// \ref Fill(const std::tuple<A...> &args) "overload for unweighted filling"
266 template <typename... A>
267 void Fill(const std::tuple<A...> &args, RWeight weight)
268 {
269 static_assert(SupportsWeightedFilling, "weighted filling is only supported for floating-point bin content types");
270
271 // We could rely on RAxes::ComputeGlobalIndex to check the number of arguments, but its exception message might
272 // be confusing for users.
273 if (sizeof...(A) != GetNDimensions()) {
274 throw std::invalid_argument("invalid number of arguments to Fill");
275 }
277 if (index.fValid) {
278 assert(index.fIndex < fBinContents.size());
279 fBinContents[index.fIndex] += weight.fValue;
280 }
281 }
282
283 /// Fill an entry into the histogram.
284 ///
285 /// \code
286 /// ROOT::Experimental::RHistEngine<int> hist({/* two dimensions */});
287 /// hist.Fill(8.5, 10.5);
288 /// \endcode
289 ///
290 /// For weighted filling, pass an RWeight as the last argument:
291 /// \code
292 /// ROOT::Experimental::RHistEngine<float> hist({/* two dimensions */});
293 /// hist.Fill(8.5, 10.5, ROOT::Experimental::RWeight(0.8));
294 /// \endcode
295 /// This is only available for floating-point bin content types (see \ref SupportsWeightedFilling).
296 ///
297 /// If one of the arguments is outside the corresponding axis and flow bins are disabled, the entry will be silently
298 /// discarded.
299 ///
300 /// Throws an exception if the number of arguments does not match the axis configuration.
301 ///
302 /// \param[in] args the arguments for each axis
303 /// \par See also
304 /// the function overloads accepting `std::tuple` \ref Fill(const std::tuple<A...> &args) "for unweighted filling"
305 /// and \ref Fill(const std::tuple<A...> &args, RWeight) "for weighted filling"
306 template <typename... A>
307 void Fill(const A &...args)
308 {
309 auto t = std::forward_as_tuple(args...);
310 if constexpr (std::is_same_v<typename Internal::LastType<A...>::type, RWeight>) {
311 static_assert(SupportsWeightedFilling,
312 "weighted filling is only supported for floating-point bin content types");
313 static constexpr std::size_t N = sizeof...(A) - 1;
314 if (N != fAxes.GetNDimensions()) {
315 throw std::invalid_argument("invalid number of arguments to Fill");
316 }
317 RWeight weight = std::get<N>(t);
319 if (index.fValid) {
320 assert(index.fIndex < fBinContents.size());
321 fBinContents[index.fIndex] += weight.fValue;
322 }
323 } else {
324 Fill(t);
325 }
326 }
327
328 /// %ROOT Streamer function to throw when trying to store an object of this class.
329 void Streamer(TBuffer &) { throw std::runtime_error("unable to store RHistEngine"); }
330};
331
332} // namespace Experimental
333} // namespace ROOT
334
335#endif
#define h(i)
Definition RSha256.hxx:106
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
#define N
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
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t type
Bin configurations for all dimensions of a histogram.
Definition RAxes.hxx:39
std::size_t GetNDimensions() const
Definition RAxes.hxx:54
RLinearizedIndex ComputeGlobalIndexImpl(std::size_t index, const std::tuple< A... > &args) const
Definition RAxes.hxx:82
RLinearizedIndex ComputeGlobalIndex(const std::tuple< A... > &args) const
Compute the global index for all axes.
Definition RAxes.hxx:117
std::size_t ComputeTotalNBins() const
Compute the total number of bins for all axes.
Definition RAxes.hxx:65
const std::vector< RAxisVariant > & Get() const
Definition RAxes.hxx:55
A bin index with special values for underflow and overflow bins.
Definition RBinIndex.hxx:22
A histogram data structure to bin data along multiple dimensions.
void Fill(const A &...args)
Fill an entry into the histogram.
const std::vector< RAxisVariant > & GetAxes() const
RHistEngine< BinContentType > Clone() const
Clone this histogram engine.
RHistEngine< BinContentType > & operator=(const RHistEngine< BinContentType > &)=delete
The copy assignment operator is deleted.
std::size_t GetTotalNBins() const
void Fill(const std::tuple< A... > &args)
Fill an entry into the histogram.
RHistEngine< BinContentType > & operator=(RHistEngine< BinContentType > &&)=default
Efficiently move a histogram engine.
const BinContentType & GetBinContent(const std::array< RBinIndex, N > &indices) const
Get the content of a single bin.
const BinContentType & GetBinContent(const A &...args) const
Get the content of a single bin.
RHistEngine(const RHistEngine< BinContentType > &)=delete
The copy constructor is deleted.
RHistEngine(std::size_t nNormalBins, double low, double high)
Construct a one-dimensional histogram engine with a regular axis.
void Add(const RHistEngine< BinContentType > &other)
Add all bin contents of another histogram.
std::size_t GetNDimensions() const
static constexpr bool SupportsWeightedFilling
Whether this histogram engine type supports weighted filling.
void Clear()
Clear all bin contents.
RHistEngine(std::vector< RAxisVariant > axes)
Construct a histogram engine.
Internal::RAxes fAxes
The axis configuration for this histogram. Relevant methods are forwarded from the public interface.
void Fill(const std::tuple< A... > &args, RWeight weight)
Fill an entry into the histogram with a weight.
RHistEngine(RHistEngine< BinContentType > &&)=default
Efficiently move construct a histogram engine.
void Streamer(TBuffer &)
ROOT Streamer function to throw when trying to store an object of this class.
std::vector< BinContentType > fBinContents
The bin contents for this histogram.
A regular axis with equidistant bins in the interval .
Buffer base class used for serializing objects.
Definition TBuffer.h:43
A linearized index that can be invalid.
A weight for filling histograms.
Definition RWeight.hxx:17