Project
Loading...
Searching...
No Matches
BinningPolicy.h
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
12#ifndef FRAMEWORK_BINNINGPOLICY_H
13#define FRAMEWORK_BINNINGPOLICY_H
14
15#include "Framework/HistogramSpec.h" // only for VARIABLE_WIDTH
16#include "Framework/Pack.h"
17
18namespace o2::framework
19{
20
21namespace binning_helpers
22{
23inline void expandConstantBinning(std::vector<double> const& bins, std::vector<double>& expanded)
24{
25 if (bins[0] != VARIABLE_WIDTH) {
26 int nBins = static_cast<int>(bins[0]);
27 expanded.clear();
28 expanded.resize(nBins + 2);
29 expanded[0] = VARIABLE_WIDTH;
30 for (int i = 0; i <= nBins; i++) {
31 expanded[i + 1] = bins[1] + i * (bins[2] - bins[1]) / nBins;
32 }
33 }
34}
35} // namespace binning_helpers
36
37template <std::size_t N>
39 BinningPolicyBase(std::array<std::vector<double>, N> bins, bool ignoreOverflows = true) : mBins(bins), mIgnoreOverflows(ignoreOverflows)
40 {
41 static_assert(N <= 3, "No default binning for more than 3 columns, you need to implement a binning class yourself");
42 for (int i = 0; i < N; i++) {
44 }
45 }
46
47 template <typename... Ts>
48 int getBin(std::tuple<Ts...> const& data) const
49 {
50 static_assert(sizeof...(Ts) == N, "There must be the same number of binning axes and data values/columns");
51
52 unsigned int i = 2, j = 2, k = 2;
53 if (this->mIgnoreOverflows) {
54 // underflow
55 if (std::get<0>(data) < this->mBins[0][1]) { // mBins[0][0] is a dummy VARIABLE_WIDTH
56 return -1;
57 }
58 if constexpr (N > 1) {
59 if (std::get<1>(data) < this->mBins[1][1]) { // mBins[1][0] is a dummy VARIABLE_WIDTH
60 return -1;
61 }
62 }
63 if constexpr (N > 2) {
64 if (std::get<2>(data) < this->mBins[2][1]) { // mBins[2][0] is a dummy VARIABLE_WIDTH
65 return -1;
66 }
67 }
68 } else {
69 i = 1;
70 j = 1;
71 k = 1;
72 }
73
74 for (; i < this->mBins[0].size(); i++) {
75 if (std::get<0>(data) < this->mBins[0][i]) {
76
77 if constexpr (N > 1) {
78 for (; j < this->mBins[1].size(); j++) {
79 if (std::get<1>(data) < this->mBins[1][j]) {
80
81 if constexpr (N > 2) {
82 for (; k < this->mBins[2].size(); k++) {
83 if (std::get<2>(data) < this->mBins[2][k]) {
84 return getBinAt(i, j, k);
85 }
86 }
87 if (this->mIgnoreOverflows) {
88 return -1;
89 }
90 }
91
92 // overflow for mBins[2] only
93 return getBinAt(i, j, k);
94 }
95 }
96
97 if (this->mIgnoreOverflows) {
98 return -1;
99 }
100
101 // overflow for mBins[1] only
102 if constexpr (N > 2) {
103 for (k = 2; k < this->mBins[2].size(); k++) {
104 if (std::get<2>(data) < this->mBins[2][k]) {
105 return getBinAt(i, j, k);
106 }
107 }
108 }
109 }
110
111 // overflow for mBins[2] and mBins[1]
112 return getBinAt(i, j, k);
113 }
114 }
115
116 if (this->mIgnoreOverflows) {
117 // overflow
118 return -1;
119 }
120
121 // overflow for mBins[0] only
122 if constexpr (N > 1) {
123 for (j = 2; j < this->mBins[1].size(); j++) {
124 if (std::get<1>(data) < this->mBins[1][j]) {
125
126 if constexpr (N > 2) {
127 for (k = 2; k < this->mBins[2].size(); k++) {
128 if (std::get<2>(data) < this->mBins[2][k]) {
129 return getBinAt(i, j, k);
130 }
131 }
132 }
133
134 // overflow for mBins[0] and mBins[2]
135 return getBinAt(i, j, k);
136 }
137 }
138 }
139
140 // overflow for mBins[0] and mBins[1]
141 if constexpr (N > 2) {
142 for (k = 2; k < this->mBins[2].size(); k++) {
143 if (std::get<2>(data) < this->mBins[2][k]) {
144 return getBinAt(i, j, k);
145 }
146 }
147 }
148
149 // overflow for all bins
150 return getBinAt(i, j, k);
151 }
152
153 // Note: Overflow / underflow bin -1 is not included
154 int getXBinsCount() const
155 {
156 return getBinsCount(mBins[0]);
157 }
158
159 // Note: Overflow / underflow bin -1 is not included
160 int getYBinsCount() const
161 {
162 if constexpr (N == 1) {
163 return 0;
164 }
165 return getBinsCount(mBins[1]);
166 }
167
168 // Note: Overflow / underflow bin -1 is not included
169 int getZBinsCount() const
170 {
171 if constexpr (N < 3) {
172 return 0;
173 }
174 return getBinsCount(mBins[2]);
175 }
176
177 // Note: Overflow / underflow bin -1 is not included
178 int getAllBinsCount() const
179 {
180 if constexpr (N == 1) {
181 return getXBinsCount();
182 }
183 if constexpr (N == 2) {
184 return getXBinsCount() * getYBinsCount();
185 }
186 if constexpr (N == 2) {
188 }
189 return -1;
190 }
191
192 std::array<std::vector<double>, N> mBins;
194
195 private:
196 // We substract 1 to account for VARIABLE_WIDTH in the bins vector
197 // We substract second 1 if we omit values below minima (underflow, mapped to -1)
198 // Otherwise we add 1 and we get the number of bins including those below and over the outer edges
199 int getBinAt(unsigned int iRaw, unsigned int jRaw, unsigned int kRaw) const
200 {
201 int shiftBinsWithoutOverflow = getOverflowShift();
202 unsigned int i = iRaw - 1 - shiftBinsWithoutOverflow;
203 unsigned int j = jRaw - 1 - shiftBinsWithoutOverflow;
204 unsigned int k = kRaw - 1 - shiftBinsWithoutOverflow;
205 auto xBinsCount = getXBinsCount();
206 if constexpr (N == 1) {
207 return i;
208 } else if constexpr (N == 2) {
209 return i + j * xBinsCount;
210 } else if constexpr (N == 3) {
211 return i + j * xBinsCount + k * xBinsCount * getYBinsCount();
212 } else {
213 return -1;
214 }
215 }
216
217 int getOverflowShift() const
218 {
219 return mIgnoreOverflows ? 1 : -1;
220 }
221
222 // Note: Overflow / underflow bin -1 is not included
223 int getBinsCount(std::vector<double> const& bins) const
224 {
225 return bins.size() - 1 - getOverflowShift();
226 }
227};
228
229template <typename, typename...>
231
232template <typename... Ts, typename... Ls>
233struct FlexibleBinningPolicy<std::tuple<Ls...>, Ts...> : BinningPolicyBase<sizeof...(Ts)> {
234 FlexibleBinningPolicy(std::tuple<Ls...> const& lambdaPtrs, std::array<std::vector<double>, sizeof...(Ts)> bins, bool ignoreOverflows = true) : BinningPolicyBase<sizeof...(Ts)>(bins, ignoreOverflows), mBinningFunctions{lambdaPtrs}
235 {
236 }
237
238 template <typename T, typename T2>
239 auto getBinningValue(T& rowIterator, arrow::Table* table, uint64_t ci = -1, uint64_t ai = -1, uint64_t globalIndex = -1) const
240 {
241 if constexpr (has_type<T2>(pack<Ls...>{})) {
242 if (globalIndex != -1) {
243 rowIterator.setCursor(globalIndex);
244 }
245 return std::get<T2>(mBinningFunctions)(rowIterator);
246 } else {
247 return soa::row_helpers::getSingleRowData<T, T2>(table, rowIterator, ci, ai, globalIndex);
248 }
249 }
250
251 template <typename T>
252 auto getBinningValues(T& rowIterator, arrow::Table* table, uint64_t ci = -1, uint64_t ai = -1, uint64_t globalIndex = -1) const
253 {
254 return std::make_tuple(getBinningValue<T, Ts>(rowIterator, table, ci, ai, globalIndex)...);
255 }
256
257 template <typename T>
258 auto getBinningValues(typename T::iterator rowIterator, T& table, uint64_t ci = -1, uint64_t ai = -1, uint64_t globalIndex = -1) const
259 {
260 return getBinningValues(rowIterator, table.asArrowTable().get(), ci, ai, globalIndex);
261 }
262
263 template <typename... T2s>
264 int getBin(std::tuple<T2s...> const& data) const
265 {
266 return BinningPolicyBase<sizeof...(Ts)>::template getBin<T2s...>(data);
267 }
268
270
271 private:
272 std::tuple<Ls...> mBinningFunctions;
273};
274
275template <typename... Ts>
276struct ColumnBinningPolicy : BinningPolicyBase<sizeof...(Ts)> {
277 ColumnBinningPolicy(std::array<std::vector<double>, sizeof...(Ts)> bins, bool ignoreOverflows = true) : BinningPolicyBase<sizeof...(Ts)>(bins, ignoreOverflows)
278 {
279 }
280
281 template <typename T>
282 auto getBinningValues(T& rowIterator, arrow::Table* table, uint64_t ci = -1, uint64_t ai = -1, uint64_t globalIndex = -1) const
283 {
284 return std::make_tuple(soa::row_helpers::getSingleRowData<T, Ts>(table, rowIterator, ci, ai, globalIndex)...);
285 }
286
287 template <typename T>
288 auto getBinningValues(typename T::iterator rowIterator, T& table, uint64_t ci = -1, uint64_t ai = -1, uint64_t globalIndex = -1) const
289 {
290 return getBinningValues(rowIterator, table.asArrowTable().get(), ci, ai, globalIndex);
291 }
292
293 int getBin(std::tuple<typename Ts::type...> const& data) const
294 {
295 return BinningPolicyBase<sizeof...(Ts)>::template getBin<typename Ts::type...>(data);
296 }
297
299};
300
301template <typename C>
303 // Just take the bin number from the column data
304 NoBinningPolicy() = default;
305
306 template <typename T>
307 auto getBinningValues(T& rowIterator, arrow::Table* table, uint64_t ci = -1, uint64_t ai = -1, uint64_t globalIndex = -1) const
308 {
309 return std::make_tuple(soa::row_helpers::getSingleRowData<T, C>(table, rowIterator, ci, ai, globalIndex));
310 }
311
312 template <typename T>
313 auto getBinningValues(typename T::iterator rowIterator, T& table, uint64_t ci = -1, uint64_t ai = -1, uint64_t globalIndex = -1) const
314 {
315 return getBinningValues(rowIterator, table.asArrowTable().get(), ci, ai, globalIndex);
316 }
317
318 int getBin(std::tuple<typename C::type> const& data) const
319 {
320 return std::get<0>(data);
321 }
322
324};
325
326} // namespace o2::framework
327#endif // FRAMEWORK_BINNINGPOLICY_H_
const auto bins
Definition PID.cxx:49
int32_t i
uint32_t j
Definition RawData.h:0
GLboolean * data
Definition glcorearb.h:298
void expandConstantBinning(std::vector< double > const &bins, std::vector< double > &expanded)
Defining PrimaryVertex explicitly as messageable.
Definition TFIDInfo.h:20
std::decay_t< decltype(prune_voids_pack(pack<>{}, with_condition_pack< Condition, Types... >{}))> selected_pack
Definition Pack.h:179
constexpr double VARIABLE_WIDTH
std::conditional_t< is_persistent_column< C >, std::true_type, std::false_type > is_persistent_column_t
Definition ASoA.h:189
Defining DataPointCompositeObject explicitly as copiable.
int getBin(std::tuple< Ts... > const &data) const
BinningPolicyBase(std::array< std::vector< double >, N > bins, bool ignoreOverflows=true)
std::array< std::vector< double >, N > mBins
auto getBinningValues(T &rowIterator, arrow::Table *table, uint64_t ci=-1, uint64_t ai=-1, uint64_t globalIndex=-1) const
auto getBinningValues(typename T::iterator rowIterator, T &table, uint64_t ci=-1, uint64_t ai=-1, uint64_t globalIndex=-1) const
framework::selected_pack< o2::soa::is_persistent_column_t, Ts... > persistent_columns_t
ColumnBinningPolicy(std::array< std::vector< double >, sizeof...(Ts)> bins, bool ignoreOverflows=true)
int getBin(std::tuple< typename Ts::type... > const &data) const
auto getBinningValues(typename T::iterator rowIterator, T &table, uint64_t ci=-1, uint64_t ai=-1, uint64_t globalIndex=-1) const
framework::selected_pack< o2::soa::is_persistent_column_t, Ts... > persistent_columns_t
auto getBinningValue(T &rowIterator, arrow::Table *table, uint64_t ci=-1, uint64_t ai=-1, uint64_t globalIndex=-1) const
FlexibleBinningPolicy(std::tuple< Ls... > const &lambdaPtrs, std::array< std::vector< double >, sizeof...(Ts)> bins, bool ignoreOverflows=true)
auto getBinningValues(T &rowIterator, arrow::Table *table, uint64_t ci=-1, uint64_t ai=-1, uint64_t globalIndex=-1) const
framework::selected_pack< o2::soa::is_persistent_column_t, C > persistent_columns_t
auto getBinningValues(typename T::iterator rowIterator, T &table, uint64_t ci=-1, uint64_t ai=-1, uint64_t globalIndex=-1) const
auto getBinningValues(T &rowIterator, arrow::Table *table, uint64_t ci=-1, uint64_t ai=-1, uint64_t globalIndex=-1) const
int getBin(std::tuple< typename C::type > const &data) const