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