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 "RAxisVariant.hxx"
10#include "RBinIndex.hxx"
12#include "RHistUtils.hxx"
13#include "RLinearizedIndex.hxx"
14#include "RRegularAxis.hxx"
15#include "RWeight.hxx"
16
17#include <array>
18#include <cassert>
19#include <cstddef>
20#include <cstdint>
21#include <stdexcept>
22#include <tuple>
23#include <type_traits>
24#include <utility>
25#include <vector>
26
27class TBuffer;
28
29namespace ROOT {
30namespace Experimental {
31
32// forward declarations for friend declaration
33template <typename BinContentType>
34class RHistEngine;
35namespace Internal {
36template <typename T, std::size_t N>
37static void SetBinContent(RHistEngine<T> &hist, const std::array<RBinIndex, N> &indices, const T &value);
38} // namespace Internal
39
40/**
41A histogram data structure to bin data along multiple dimensions.
42
43Every call to \ref Fill(const A &... args) "Fill" bins the data according to the axis configuration and increments the
44bin content:
45\code
46ROOT::Experimental::RHistEngine<int> hist(10, {5, 15});
47hist.Fill(8.5);
48// hist.GetBinContent(ROOT::Experimental::RBinIndex(3)) will return 1
49\endcode
50
51The class is templated on the bin content type. For counting, as in the example above, it may be an integral type such
52as `int` or `long`. Narrower types such as `unsigned char` or `short` are supported, but may overflow due to their
53limited range and must be used with care. For weighted filling, the bin content type must not be an integral type, but
54a floating-point type such as `float` or `double`, or the special type RBinWithError. Note that `float` has a limited
55significand precision of 24 bits.
56
57An object can have arbitrary dimensionality determined at run-time. The axis configuration is passed as a vector of
58RAxisVariant:
59\code
60std::vector<ROOT::Experimental::RAxisVariant> axes;
61axes.push_back(ROOT::Experimental::RRegularAxis(10, {5, 15}));
62axes.push_back(ROOT::Experimental::RVariableBinAxis({1, 10, 100, 1000}));
63ROOT::Experimental::RHistEngine<int> hist(axes);
64// hist.GetNDimensions() will return 2
65\endcode
66
67\warning This is part of the %ROOT 7 prototype! It will change without notice. It might trigger earthquakes.
68Feedback is welcome!
69*/
70template <typename BinContentType>
72 // For conversion, all other template instantiations must be a friend.
73 template <typename U>
74 friend class RHistEngine;
75
76 template <typename T, std::size_t N>
77 friend void Internal::SetBinContent(RHistEngine<T> &, const std::array<RBinIndex, N> &, const T &);
78
79 /// The axis configuration for this histogram. Relevant methods are forwarded from the public interface.
81 /// The bin contents for this histogram
82 std::vector<BinContentType> fBinContents;
83
84public:
85 /// Construct a histogram engine.
86 ///
87 /// \param[in] axes the axis objects, must have size > 0
88 explicit RHistEngine(std::vector<RAxisVariant> axes) : fAxes(std::move(axes))
89 {
91 }
92
93 /// Construct a histogram engine.
94 ///
95 /// Note that there is no perfect forwarding of the axis objects. If that is needed, use the
96 /// \ref RHistEngine(std::vector<RAxisVariant> axes) "overload accepting a std::vector".
97 ///
98 /// \param[in] axes the axis objects, must have size > 0
99 explicit RHistEngine(std::initializer_list<RAxisVariant> axes) : RHistEngine(std::vector(axes)) {}
100
101 /// Construct a histogram engine.
102 ///
103 /// Note that there is no perfect forwarding of the axis objects. If that is needed, use the
104 /// \ref RHistEngine(std::vector<RAxisVariant> axes) "overload accepting a std::vector".
105 ///
106 /// \param[in] axis1 the first axis object
107 /// \param[in] axes the remaining axis objects
108 template <typename... Axes>
109 explicit RHistEngine(const RAxisVariant &axis1, const Axes &...axes)
110 : RHistEngine(std::vector<RAxisVariant>{axis1, axes...})
111 {
112 }
113
114 /// Construct a one-dimensional histogram engine with a regular axis.
115 ///
116 /// \param[in] nNormalBins the number of normal bins, must be > 0
117 /// \param[in] interval the axis interval (lower end inclusive, upper end exclusive)
118 /// \par See also
119 /// the \ref RRegularAxis::RRegularAxis(std::uint64_t nNormalBins, std::pair<double, double> interval, bool
120 /// enableFlowBins) "constructor of RRegularAxis"
121 RHistEngine(std::uint64_t nNormalBins, std::pair<double, double> interval)
123 {
124 }
125
126 /// The copy constructor is deleted.
127 ///
128 /// Copying all bin contents can be an expensive operation, depending on the number of bins. If required, users can
129 /// explicitly call Clone().
130 RHistEngine(const RHistEngine &) = delete;
131 /// Efficiently move construct a histogram engine.
132 ///
133 /// After this operation, the moved-from object is invalid.
135
136 /// The copy assignment operator is deleted.
137 ///
138 /// Copying all bin contents can be an expensive operation, depending on the number of bins. If required, users can
139 /// explicitly call Clone().
141 /// Efficiently move a histogram engine.
142 ///
143 /// After this operation, the moved-from object is invalid.
145
146 ~RHistEngine() = default;
147
148 const std::vector<RAxisVariant> &GetAxes() const { return fAxes.Get(); }
149 std::size_t GetNDimensions() const { return fAxes.GetNDimensions(); }
150 std::uint64_t GetTotalNBins() const { return fBinContents.size(); }
151
152 /// Get the content of a single bin.
153 ///
154 /// \code
155 /// ROOT::Experimental::RHistEngine<int> hist({/* two dimensions */});
156 /// std::array<ROOT::Experimental::RBinIndex, 2> indices = {3, 5};
157 /// int content = hist.GetBinContent(indices);
158 /// \endcode
159 ///
160 /// \note Compared to TH1 conventions, the first normal bin has index 0 and underflow and overflow bins are special
161 /// values. See also the class documentation of RBinIndex.
162 ///
163 /// Throws an exception if the number of indices does not match the axis configuration or the bin is not found.
164 ///
165 /// \param[in] indices the array of indices for each axis
166 /// \return the bin content
167 /// \par See also
168 /// the \ref GetBinContent(const A &... args) const "variadic function template overload" accepting arguments
169 /// directly
170 template <std::size_t N>
171 const BinContentType &GetBinContent(const std::array<RBinIndex, N> &indices) const
172 {
173 // We could rely on RAxes::ComputeGlobalIndex to check the number of arguments, but its exception message might
174 // be confusing for users.
175 if (N != GetNDimensions()) {
176 throw std::invalid_argument("invalid number of indices passed to GetBinContent");
177 }
179 if (!index.fValid) {
180 throw std::invalid_argument("bin not found in GetBinContent");
181 }
182 assert(index.fIndex < fBinContents.size());
183 return fBinContents[index.fIndex];
184 }
185
186 /// Get the content of a single bin.
187 ///
188 /// \code
189 /// ROOT::Experimental::RHistEngine<int> hist({/* two dimensions */});
190 /// std::vector<ROOT::Experimental::RBinIndex> indices = {3, 5};
191 /// int content = hist.GetBinContent(indices);
192 /// \endcode
193 ///
194 /// \note Compared to TH1 conventions, the first normal bin has index 0 and underflow and overflow bins are special
195 /// values. See also the class documentation of RBinIndex.
196 ///
197 /// Throws an exception if the number of indices does not match the axis configuration or the bin is not found.
198 ///
199 /// \param[in] indices the vector of indices for each axis
200 /// \return the bin content
201 /// \par See also
202 /// the \ref GetBinContent(const A &... args) const "variadic function template overload" accepting arguments
203 /// directly
204 const BinContentType &GetBinContent(const std::vector<RBinIndex> &indices) const
205 {
206 // We could rely on RAxes::ComputeGlobalIndex to check the number of arguments, but its exception message might
207 // be confusing for users.
208 if (indices.size() != GetNDimensions()) {
209 throw std::invalid_argument("invalid number of indices passed to GetBinContent");
210 }
212 if (!index.fValid) {
213 throw std::invalid_argument("bin not found in GetBinContent");
214 }
215 assert(index.fIndex < fBinContents.size());
216 return fBinContents[index.fIndex];
217 }
218
219 /// Get the content of a single bin.
220 ///
221 /// \code
222 /// ROOT::Experimental::RHistEngine<int> hist({/* two dimensions */});
223 /// int content = hist.GetBinContent(ROOT::Experimental::RBinIndex(3), ROOT::Experimental::RBinIndex(5));
224 /// // ... or construct the RBinIndex arguments implicitly from integers:
225 /// content = hist.GetBinContent(3, 5);
226 /// \endcode
227 ///
228 /// \note Compared to TH1 conventions, the first normal bin has index 0 and underflow and overflow bins are special
229 /// values. See also the class documentation of RBinIndex.
230 ///
231 /// Throws an exception if the number of arguments does not match the axis configuration or the bin is not found.
232 ///
233 /// \param[in] args the arguments for each axis
234 /// \return the bin content
235 /// \par See also
236 /// the function overloads accepting \ref GetBinContent(const std::array<RBinIndex, N> &indices) const "`std::array`"
237 /// or \ref GetBinContent(const std::vector<RBinIndex> &indices) const "`std::vector`"
238 template <typename... A>
239 const BinContentType &GetBinContent(const A &...args) const
240 {
241 std::array<RBinIndex, sizeof...(A)> indices{args...};
242 return GetBinContent(indices);
243 }
244
245 /// Get the multidimensional range of all bins.
246 ///
247 /// \return the multidimensional range
249
250 /// Add all bin contents of another histogram.
251 ///
252 /// Throws an exception if the axes configurations are not identical.
253 ///
254 /// \param[in] other another histogram
255 void Add(const RHistEngine &other)
256 {
257 if (fAxes != other.fAxes) {
258 throw std::invalid_argument("axes configurations not identical in Add");
259 }
260 for (std::size_t i = 0; i < fBinContents.size(); i++) {
261 fBinContents[i] += other.fBinContents[i];
262 }
263 }
264
265 /// Add all bin contents of another histogram using atomic instructions.
266 ///
267 /// Throws an exception if the axes configurations are not identical.
268 ///
269 /// \param[in] other another histogram that must not be modified during the operation
271 {
272 if (fAxes != other.fAxes) {
273 throw std::invalid_argument("axes configurations not identical in AddAtomic");
274 }
275 for (std::size_t i = 0; i < fBinContents.size(); i++) {
276 Internal::AtomicAdd(&fBinContents[i], other.fBinContents[i]);
277 }
278 }
279
280 /// Clear all bin contents.
281 void Clear()
282 {
283 for (std::size_t i = 0; i < fBinContents.size(); i++) {
284 fBinContents[i] = {};
285 }
286 }
287
288 /// Clone this histogram engine.
289 ///
290 /// Copying all bin contents can be an expensive operation, depending on the number of bins.
291 ///
292 /// \return the cloned object
294 {
296 for (std::size_t i = 0; i < fBinContents.size(); i++) {
297 h.fBinContents[i] = fBinContents[i];
298 }
299 return h;
300 }
301
302 /// Convert this histogram engine to a different bin content type.
303 ///
304 /// There is no bounds checking to make sure that the converted values can be represented. Note that it is not
305 /// possible to convert to RBinWithError since the information about individual weights has been lost since filling.
306 ///
307 /// Converting all bin contents can be an expensive operation, depending on the number of bins.
308 ///
309 /// \return the converted object
310 template <typename U>
312 {
314 for (std::size_t i = 0; i < fBinContents.size(); i++) {
315 h.fBinContents[i] = static_cast<U>(fBinContents[i]);
316 }
317 return h;
318 }
319
320 /// Whether this histogram engine type supports weighted filling.
321 static constexpr bool SupportsWeightedFilling = !std::is_integral_v<BinContentType>;
322
323 /// Fill an entry into the histogram.
324 ///
325 /// \code
326 /// ROOT::Experimental::RHistEngine<int> hist({/* two dimensions */});
327 /// auto args = std::make_tuple(8.5, 10.5);
328 /// hist.Fill(args);
329 /// \endcode
330 ///
331 /// If one of the arguments is outside the corresponding axis and flow bins are disabled, the entry will be silently
332 /// discarded.
333 ///
334 /// Throws an exception if the number of arguments does not match the axis configuration, or if an argument cannot be
335 /// converted for the axis type at run-time.
336 ///
337 /// \param[in] args the arguments for each axis
338 /// \par See also
339 /// the \ref Fill(const A &... args) "variadic function template overload" accepting arguments directly and the
340 /// \ref Fill(const std::tuple<A...> &args, RWeight weight) "overload for weighted filling"
341 template <typename... A>
342 void Fill(const std::tuple<A...> &args)
343 {
344 // We could rely on RAxes::ComputeGlobalIndex to check the number of arguments, but its exception message might
345 // be confusing for users.
346 if (sizeof...(A) != GetNDimensions()) {
347 throw std::invalid_argument("invalid number of arguments to Fill");
348 }
350 if (index.fValid) {
351 assert(index.fIndex < fBinContents.size());
352 fBinContents[index.fIndex]++;
353 }
354 }
355
356 /// Fill an entry into the histogram with a weight.
357 ///
358 /// This overload is not available for integral bin content types (see \ref SupportsWeightedFilling).
359 ///
360 /// \code
361 /// ROOT::Experimental::RHistEngine<float> hist({/* two dimensions */});
362 /// auto args = std::make_tuple(8.5, 10.5);
363 /// hist.Fill(args, ROOT::Experimental::RWeight(0.8));
364 /// \endcode
365 ///
366 /// If one of the arguments is outside the corresponding axis and flow bins are disabled, the entry will be silently
367 /// discarded.
368 ///
369 /// Throws an exception if the number of arguments does not match the axis configuration, or if an argument cannot be
370 /// converted for the axis type at run-time.
371 ///
372 /// \param[in] args the arguments for each axis
373 /// \param[in] weight the weight for this entry
374 /// \par See also
375 /// the \ref Fill(const A &... args) "variadic function template overload" accepting arguments directly and the
376 /// \ref Fill(const std::tuple<A...> &args) "overload for unweighted filling"
377 template <typename... A>
378 void Fill(const std::tuple<A...> &args, RWeight weight)
379 {
380 static_assert(SupportsWeightedFilling, "weighted filling is not supported for integral bin content types");
381
382 // We could rely on RAxes::ComputeGlobalIndex to check the number of arguments, but its exception message might
383 // be confusing for users.
384 if (sizeof...(A) != GetNDimensions()) {
385 throw std::invalid_argument("invalid number of arguments to Fill");
386 }
388 if (index.fValid) {
389 assert(index.fIndex < fBinContents.size());
390 fBinContents[index.fIndex] += weight.fValue;
391 }
392 }
393
394 /// Fill an entry into the histogram with a user-defined weight.
395 ///
396 /// This overload is only available for user-defined bin content types.
397 ///
398 /// If one of the arguments is outside the corresponding axis and flow bins are disabled, the entry will be silently
399 /// discarded.
400 ///
401 /// Throws an exception if the number of arguments does not match the axis configuration, or if an argument cannot be
402 /// converted for the axis type at run-time.
403 ///
404 /// \param[in] args the arguments for each axis
405 /// \param[in] weight the weight for this entry
406 template <typename... A, typename W>
407 void Fill(const std::tuple<A...> &args, const W &weight)
408 {
409 static_assert(std::is_class_v<BinContentType>,
410 "user-defined weight types are only supported for user-defined bin content types");
411
412 // We could rely on RAxes::ComputeGlobalIndex to check the number of arguments, but its exception message might
413 // be confusing for users.
414 if (sizeof...(A) != GetNDimensions()) {
415 throw std::invalid_argument("invalid number of arguments to Fill");
416 }
418 if (index.fValid) {
419 assert(index.fIndex < fBinContents.size());
420 fBinContents[index.fIndex] += weight;
421 }
422 }
423
424 /// Fill an entry into the histogram.
425 ///
426 /// \code
427 /// ROOT::Experimental::RHistEngine<int> hist({/* two dimensions */});
428 /// hist.Fill(8.5, 10.5);
429 /// \endcode
430 ///
431 /// For weighted filling, pass an RWeight as the last argument:
432 /// \code
433 /// ROOT::Experimental::RHistEngine<float> hist({/* two dimensions */});
434 /// hist.Fill(8.5, 10.5, ROOT::Experimental::RWeight(0.8));
435 /// \endcode
436 /// This is not available for integral bin content types (see \ref SupportsWeightedFilling).
437 ///
438 /// If one of the arguments is outside the corresponding axis and flow bins are disabled, the entry will be silently
439 /// discarded.
440 ///
441 /// Throws an exception if the number of arguments does not match the axis configuration, or if an argument cannot be
442 /// converted for the axis type at run-time.
443 ///
444 /// \param[in] args the arguments for each axis
445 /// \par See also
446 /// the function overloads accepting `std::tuple` \ref Fill(const std::tuple<A...> &args) "for unweighted filling"
447 /// and \ref Fill(const std::tuple<A...> &args, RWeight) "for weighted filling"
448 template <typename... A>
449 void Fill(const A &...args)
450 {
451 static_assert(sizeof...(A) >= 1, "need at least one argument to Fill");
452 if constexpr (sizeof...(A) >= 1) {
453 auto t = std::forward_as_tuple(args...);
454 if constexpr (std::is_same_v<typename Internal::LastType<A...>::type, RWeight>) {
455 static_assert(SupportsWeightedFilling, "weighted filling is not supported for integral bin content types");
456 static constexpr std::size_t N = sizeof...(A) - 1;
457 if (N != fAxes.GetNDimensions()) {
458 throw std::invalid_argument("invalid number of arguments to Fill");
459 }
460 RWeight weight = std::get<N>(t);
462 if (index.fValid) {
463 assert(index.fIndex < fBinContents.size());
464 fBinContents[index.fIndex] += weight.fValue;
465 }
466 } else {
467 Fill(t);
468 }
469 }
470 }
471
472 /// Fill an entry into the histogram using atomic instructions.
473 ///
474 /// \param[in] args the arguments for each axis
475 /// \see Fill(const std::tuple<A...> &args)
476 template <typename... A>
477 void FillAtomic(const std::tuple<A...> &args)
478 {
479 // We could rely on RAxes::ComputeGlobalIndex to check the number of arguments, but its exception message might
480 // be confusing for users.
481 if (sizeof...(A) != GetNDimensions()) {
482 throw std::invalid_argument("invalid number of arguments to Fill");
483 }
485 if (index.fValid) {
486 assert(index.fIndex < fBinContents.size());
488 }
489 }
490
491 /// Fill an entry into the histogram with a weight using atomic instructions.
492 ///
493 /// This overload is not available for integral bin content types (see \ref SupportsWeightedFilling).
494 ///
495 /// \param[in] args the arguments for each axis
496 /// \param[in] weight the weight for this entry
497 /// \see Fill(const std::tuple<A...> &args, RWeight weight)
498 template <typename... A>
499 void FillAtomic(const std::tuple<A...> &args, RWeight weight)
500 {
501 static_assert(SupportsWeightedFilling, "weighted filling is not supported for integral bin content types");
502
503 // We could rely on RAxes::ComputeGlobalIndex to check the number of arguments, but its exception message might
504 // be confusing for users.
505 if (sizeof...(A) != GetNDimensions()) {
506 throw std::invalid_argument("invalid number of arguments to Fill");
507 }
509 if (index.fValid) {
510 assert(index.fIndex < fBinContents.size());
512 }
513 }
514
515 /// Fill an entry into the histogram with a user-defined weight using atomic instructions.
516 ///
517 /// This overload is only available for user-defined bin content types.
518 ///
519 /// \param[in] args the arguments for each axis
520 /// \param[in] weight the weight for this entry
521 /// \see Fill(const std::tuple<A...> &args, const W &weight)
522 template <typename... A, typename W>
523 void FillAtomic(const std::tuple<A...> &args, const W &weight)
524 {
525 static_assert(std::is_class_v<BinContentType>,
526 "user-defined weight types are only supported for user-defined bin content types");
527
528 // We could rely on RAxes::ComputeGlobalIndex to check the number of arguments, but its exception message might
529 // be confusing for users.
530 if (sizeof...(A) != GetNDimensions()) {
531 throw std::invalid_argument("invalid number of arguments to Fill");
532 }
534 if (index.fValid) {
535 assert(index.fIndex < fBinContents.size());
536 Internal::AtomicAdd(&fBinContents[index.fIndex], weight);
537 }
538 }
539
540 /// Fill an entry into the histogram using atomic instructions.
541 ///
542 /// \param[in] args the arguments for each axis
543 /// \see Fill(const A &...args)
544 template <typename... A>
545 void FillAtomic(const A &...args)
546 {
547 static_assert(sizeof...(A) >= 1, "need at least one argument to Fill");
548 if constexpr (sizeof...(A) >= 1) {
549 auto t = std::forward_as_tuple(args...);
550 if constexpr (std::is_same_v<typename Internal::LastType<A...>::type, RWeight>) {
551 static_assert(SupportsWeightedFilling, "weighted filling is not supported for integral bin content types");
552 static constexpr std::size_t N = sizeof...(A) - 1;
553 if (N != fAxes.GetNDimensions()) {
554 throw std::invalid_argument("invalid number of arguments to Fill");
555 }
556 RWeight weight = std::get<N>(t);
558 if (index.fValid) {
559 assert(index.fIndex < fBinContents.size());
561 }
562 } else {
563 FillAtomic(t);
564 }
565 }
566 }
567
568 /// Scale all histogram bin contents.
569 ///
570 /// This method is not available for integral bin content types.
571 ///
572 /// \param[in] factor the scale factor
573 void Scale(double factor)
574 {
575 static_assert(!std::is_integral_v<BinContentType>, "scaling is not supported for integral bin content types");
576 for (std::size_t i = 0; i < fBinContents.size(); i++) {
577 fBinContents[i] *= factor;
578 }
579 }
580
581 /// %ROOT Streamer function to throw when trying to store an object of this class.
582 void Streamer(TBuffer &) { throw std::runtime_error("unable to store RHistEngine"); }
583};
584
585namespace Internal {
586/// %Internal function to set the content of a single bin.
587template <typename T, std::size_t N>
588static void SetBinContent(RHistEngine<T> &hist, const std::array<RBinIndex, N> &indices, const T &value)
589{
590 RLinearizedIndex index = hist.fAxes.ComputeGlobalIndex(indices);
591 if (!index.fValid) {
592 throw std::invalid_argument("bin not found in SetBinContent");
593 }
594 assert(index.fIndex < hist.fBinContents.size());
595 hist.fBinContents[index.fIndex] = value;
596}
597} // namespace Internal
598
599} // namespace Experimental
600} // namespace ROOT
601
602#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 value
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:41
std::size_t GetNDimensions() const
Definition RAxes.hxx:56
RLinearizedIndex ComputeGlobalIndexImpl(std::size_t index, const std::tuple< A... > &args) const
Definition RAxes.hxx:78
RLinearizedIndex ComputeGlobalIndex(const std::tuple< A... > &args) const
Compute the global index for all axes.
Definition RAxes.hxx:132
RBinIndexMultiDimRange GetFullMultiDimRange() const
Get the multidimensional range of all bins.
Definition RAxes.hxx:196
std::uint64_t ComputeTotalNBins() const
Compute the total number of bins for all axes.
Definition RAxes.hxx:67
const std::vector< RAxisVariant > & Get() const
Definition RAxes.hxx:57
A variant of all supported axis types.
A multidimensional range of bin indices.
A bin index with special values for underflow and overflow bins.
Definition RBinIndex.hxx:23
A histogram data structure to bin data along multiple dimensions.
RHistEngine(const RAxisVariant &axis1, const Axes &...axes)
Construct a histogram engine.
void Fill(const A &...args)
Fill an entry into the histogram.
const std::vector< RAxisVariant > & GetAxes() const
RBinIndexMultiDimRange GetFullMultiDimRange() const
Get the multidimensional range of all bins.
RHistEngine Clone() const
Clone this histogram engine.
RHistEngine & operator=(RHistEngine &&)=default
Efficiently move a histogram engine.
void Scale(double factor)
Scale all histogram bin contents.
void Fill(const std::tuple< A... > &args)
Fill an entry into the histogram.
void FillAtomic(const std::tuple< A... > &args)
Fill an entry into the histogram using atomic instructions.
RHistEngine(std::uint64_t nNormalBins, std::pair< double, double > interval)
Construct a one-dimensional histogram engine with a regular axis.
RHistEngine & operator=(const RHistEngine &)=delete
The copy assignment operator is deleted.
const BinContentType & GetBinContent(const std::vector< RBinIndex > &indices) const
Get the content of a single bin.
RHistEngine(RHistEngine &&)=default
Efficiently move construct a histogram engine.
RHistEngine(const RHistEngine &)=delete
The copy constructor is deleted.
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.
void AddAtomic(const RHistEngine &other)
Add all bin contents of another histogram using atomic instructions.
std::size_t GetNDimensions() const
void Fill(const std::tuple< A... > &args, const W &weight)
Fill an entry into the histogram with a user-defined weight.
void Add(const RHistEngine &other)
Add all bin contents of another histogram.
void FillAtomic(const std::tuple< A... > &args, RWeight weight)
Fill an entry into the histogram with a weight using atomic instructions.
static constexpr bool SupportsWeightedFilling
Whether this histogram engine type supports weighted filling.
void Clear()
Clear all bin contents.
std::uint64_t GetTotalNBins() const
void FillAtomic(const std::tuple< A... > &args, const W &weight)
Fill an entry into the histogram with a user-defined weight using atomic instructions.
RHistEngine(std::vector< RAxisVariant > axes)
Construct a histogram engine.
void FillAtomic(const A &...args)
Fill an entry into the histogram using atomic instructions.
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(std::initializer_list< RAxisVariant > axes)
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.
RHistEngine< U > Convert() const
Convert this histogram engine to a different bin content type.
A regular axis with equidistant bins in the interval .
Buffer base class used for serializing objects.
Definition TBuffer.h:43
std::enable_if_t< std::is_arithmetic_v< T > > AtomicInc(T *ptr)
static void SetBinContent(RHistEngine< T > &hist, const std::array< RBinIndex, N > &indices, const T &value)
Internal function to set the content of a single bin.
std::enable_if_t< std::is_integral_v< T > > AtomicAdd(T *ptr, T val)
A linearized index that can be invalid.
A weight for filling histograms.
Definition RWeight.hxx:17