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