Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RAxes.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_RAxes
6#define ROOT_RAxes
7
8#include "RBinIndex.hxx"
10#include "RLinearizedIndex.hxx"
11#include "RRegularAxis.hxx"
12#include "RVariableBinAxis.hxx"
13
14#include <array>
15#include <cassert>
16#include <cstddef>
17#include <cstdint>
18#include <stdexcept>
19#include <tuple>
20#include <type_traits>
21#include <utility>
22#include <variant>
23#include <vector>
24
25class TBuffer;
26
27namespace ROOT {
28namespace Experimental {
29
30/// Variant of all supported axis types.
31using RAxisVariant = std::variant<RRegularAxis, RVariableBinAxis, RCategoricalAxis>;
32
33// forward declaration for friend declaration
34template <typename T>
35class RHistEngine;
36
37namespace Internal {
38
39/**
40Bin configurations for all dimensions of a histogram.
41*/
42class RAxes final {
43 template <typename T>
44 friend class ::ROOT::Experimental::RHistEngine;
45
46 std::vector<RAxisVariant> fAxes;
47
48public:
49 /// \param[in] axes the axis objects, must have size > 0
50 explicit RAxes(std::vector<RAxisVariant> axes) : fAxes(std::move(axes))
51 {
52 if (fAxes.empty()) {
53 throw std::invalid_argument("must have at least 1 axis object");
54 }
55 }
56
57 std::size_t GetNDimensions() const { return fAxes.size(); }
58 const std::vector<RAxisVariant> &Get() const { return fAxes; }
59
60 friend bool operator==(const RAxes &lhs, const RAxes &rhs) { return lhs.fAxes == rhs.fAxes; }
61 friend bool operator!=(const RAxes &lhs, const RAxes &rhs) { return !(lhs == rhs); }
62
63 /// Compute the total number of bins for all axes.
64 ///
65 /// It is the product of each dimension's total number of bins.
66 ///
67 /// \return the total number of bins
68 std::uint64_t ComputeTotalNBins() const
69 {
70 std::uint64_t totalNBins = 1;
71 for (auto &&axis : fAxes) {
72 if (auto *regular = std::get_if<RRegularAxis>(&axis)) {
73 totalNBins *= regular->GetTotalNBins();
74 } else if (auto *variable = std::get_if<RVariableBinAxis>(&axis)) {
75 totalNBins *= variable->GetTotalNBins();
76 } else if (auto *categorical = std::get_if<RCategoricalAxis>(&axis)) {
77 totalNBins *= categorical->GetTotalNBins();
78 } else {
79 throw std::logic_error("unimplemented axis type"); // GCOVR_EXCL_LINE
80 }
81 }
82 return totalNBins;
83 }
84
85private:
86 template <std::size_t I, std::size_t N, typename... A>
87 RLinearizedIndex ComputeGlobalIndexImpl(std::size_t index, const std::tuple<A...> &args) const
88 {
89 using ArgumentType = std::tuple_element_t<I, std::tuple<A...>>;
90 const auto &axis = fAxes[I];
92 if (auto *regular = std::get_if<RRegularAxis>(&axis)) {
93 if constexpr (std::is_convertible_v<ArgumentType, RRegularAxis::ArgumentType>) {
94 index *= regular->GetTotalNBins();
95 linIndex = regular->ComputeLinearizedIndex(std::get<I>(args));
96 } else {
97 throw std::invalid_argument("invalid type of argument");
98 }
99 } else if (auto *variable = std::get_if<RVariableBinAxis>(&axis)) {
100 if constexpr (std::is_convertible_v<ArgumentType, RVariableBinAxis::ArgumentType>) {
101 index *= variable->GetTotalNBins();
102 linIndex = variable->ComputeLinearizedIndex(std::get<I>(args));
103 } else {
104 throw std::invalid_argument("invalid type of argument");
105 }
106 } else if (auto *categorical = std::get_if<RCategoricalAxis>(&axis)) {
107 if constexpr (std::is_convertible_v<ArgumentType, RCategoricalAxis::ArgumentType>) {
108 index *= categorical->GetTotalNBins();
109 linIndex = categorical->ComputeLinearizedIndex(std::get<I>(args));
110 } else {
111 throw std::invalid_argument("invalid type of argument");
112 }
113 } else {
114 throw std::logic_error("unimplemented axis type"); // GCOVR_EXCL_LINE
115 }
116 if (!linIndex.fValid) {
117 return {0, false};
118 }
119 index += linIndex.fIndex;
120 if constexpr (I + 1 < N) {
122 }
123 return {index, true};
124 }
125
126 template <std::size_t N, typename... A>
127 RLinearizedIndex ComputeGlobalIndexImpl(const std::tuple<A...> &args) const
128 {
129 return ComputeGlobalIndexImpl<0, N>(0, args);
130 }
131
132public:
133 /// Compute the global index for all axes.
134 ///
135 /// Throws an exception if the number of arguments does not match the axis configuration, or if an argument cannot be
136 /// converted for the axis type at run-time.
137 ///
138 /// \param[in] args the arguments
139 /// \return the global index that may be invalid
140 template <typename... A>
141 RLinearizedIndex ComputeGlobalIndex(const std::tuple<A...> &args) const
142 {
143 if (sizeof...(A) != fAxes.size()) {
144 throw std::invalid_argument("invalid number of arguments to ComputeGlobalIndex");
145 }
146 return ComputeGlobalIndexImpl<sizeof...(A)>(args);
147 }
148
149 /// Compute the global index for all axes.
150 ///
151 /// \param[in] indices the array of RBinIndex
152 /// \return the global index that may be invalid
153 template <std::size_t N>
154 RLinearizedIndex ComputeGlobalIndex(const std::array<RBinIndex, N> &indices) const
155 {
156 if (N != fAxes.size()) {
157 throw std::invalid_argument("invalid number of indices passed to ComputeGlobalIndex");
158 }
159 std::uint64_t globalIndex = 0;
160 for (std::size_t i = 0; i < N; i++) {
161 const auto &index = indices[i];
162 const auto &axis = fAxes[i];
164 if (auto *regular = std::get_if<RRegularAxis>(&axis)) {
165 globalIndex *= regular->GetTotalNBins();
166 linIndex = regular->GetLinearizedIndex(index);
167 } else if (auto *variable = std::get_if<RVariableBinAxis>(&axis)) {
168 globalIndex *= variable->GetTotalNBins();
169 linIndex = variable->GetLinearizedIndex(index);
170 } else if (auto *categorical = std::get_if<RCategoricalAxis>(&axis)) {
171 globalIndex *= categorical->GetTotalNBins();
172 linIndex = categorical->GetLinearizedIndex(index);
173 } else {
174 throw std::logic_error("unimplemented axis type"); // GCOVR_EXCL_LINE
175 }
176 if (!linIndex.fValid) {
177 return {0, false};
178 }
179 globalIndex += linIndex.fIndex;
180 }
181 return {globalIndex, true};
182 }
183
184 /// %ROOT Streamer function to throw when trying to store an object of this class.
185 void Streamer(TBuffer &) { throw std::runtime_error("unable to store RAxes"); }
186};
187
188} // namespace Internal
189} // namespace Experimental
190} // namespace ROOT
191
192#endif
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
Bin configurations for all dimensions of a histogram.
Definition RAxes.hxx:42
friend bool operator==(const RAxes &lhs, const RAxes &rhs)
Definition RAxes.hxx:60
std::size_t GetNDimensions() const
Definition RAxes.hxx:57
friend bool operator!=(const RAxes &lhs, const RAxes &rhs)
Definition RAxes.hxx:61
RLinearizedIndex ComputeGlobalIndexImpl(std::size_t index, const std::tuple< A... > &args) const
Definition RAxes.hxx:87
RLinearizedIndex ComputeGlobalIndex(const std::tuple< A... > &args) const
Compute the global index for all axes.
Definition RAxes.hxx:141
RLinearizedIndex ComputeGlobalIndexImpl(const std::tuple< A... > &args) const
Definition RAxes.hxx:127
std::uint64_t ComputeTotalNBins() const
Compute the total number of bins for all axes.
Definition RAxes.hxx:68
RAxes(std::vector< RAxisVariant > axes)
Definition RAxes.hxx:50
void Streamer(TBuffer &)
ROOT Streamer function to throw when trying to store an object of this class.
Definition RAxes.hxx:185
RLinearizedIndex ComputeGlobalIndex(const std::array< RBinIndex, N > &indices) const
Compute the global index for all axes.
Definition RAxes.hxx:154
std::vector< RAxisVariant > fAxes
Definition RAxes.hxx:46
const std::vector< RAxisVariant > & Get() const
Definition RAxes.hxx:58
A histogram data structure to bin data along multiple dimensions.
Buffer base class used for serializing objects.
Definition TBuffer.h:43
#define I(x, y, z)
std::variant< RRegularAxis, RVariableBinAxis, RCategoricalAxis > RAxisVariant
Variant of all supported axis types.
Definition RAxes.hxx:31
A linearized index that can be invalid.