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/ASoA.h"
16#include "Framework/HistogramSpec.h" // only for VARIABLE_WIDTH
17
18#include <cstddef>
19#include <cstdint>
20#include <tuple>
21#include <vector>
22
23namespace o2::framework
24{
25
26namespace binning_helpers
27{
28inline void expandConstantBinning(std::vector<double> const& bins, std::vector<double>& expanded)
29{
30 if (bins[0] != VARIABLE_WIDTH) {
31 int nBins = static_cast<int>(bins[0]);
32 expanded.clear();
33 expanded.resize(nBins + 2);
34 expanded[0] = VARIABLE_WIDTH;
35 for (int i = 0; i <= nBins; i++) {
36 expanded[i + 1] = bins[1] + i * (bins[2] - bins[1]) / nBins;
37 }
38 }
39}
40} // namespace binning_helpers
41
42template <std::size_t N>
44 BinningPolicyBase(std::array<std::vector<double>, N> bins, bool ignoreOverflows = true) : mBins(bins), mIgnoreOverflows(ignoreOverflows)
45 {
46 static_assert(N <= 3, "No default binning for more than 3 columns, you need to implement a binning class yourself");
47 for (int i = 0; i < N; i++) {
49 }
50 }
51
52 template <typename... Ts>
53 int getBin(std::tuple<Ts...> const& data) const
54 {
55 static_assert(sizeof...(Ts) == N, "There must be the same number of binning axes and data values/columns");
56
57 unsigned int i = 2, j = 2, k = 2;
58 if (this->mIgnoreOverflows) {
59 // underflow
60 if (std::get<0>(data) < this->mBins[0][1]) { // mBins[0][0] is a dummy VARIABLE_WIDTH
61 return -1;
62 }
63 if constexpr (N > 1) {
64 if (std::get<1>(data) < this->mBins[1][1]) { // mBins[1][0] is a dummy VARIABLE_WIDTH
65 return -1;
66 }
67 }
68 if constexpr (N > 2) {
69 if (std::get<2>(data) < this->mBins[2][1]) { // mBins[2][0] is a dummy VARIABLE_WIDTH
70 return -1;
71 }
72 }
73 } else {
74 i = 1;
75 j = 1;
76 k = 1;
77 }
78
79 for (; i < this->mBins[0].size(); i++) {
80 if (std::get<0>(data) < this->mBins[0][i]) {
81
82 if constexpr (N > 1) {
83 for (; j < this->mBins[1].size(); j++) {
84 if (std::get<1>(data) < this->mBins[1][j]) {
85
86 if constexpr (N > 2) {
87 for (; k < this->mBins[2].size(); k++) {
88 if (std::get<2>(data) < this->mBins[2][k]) {
89 return getBinAt(i, j, k);
90 }
91 }
92 if (this->mIgnoreOverflows) {
93 return -1;
94 }
95 }
96
97 // overflow for mBins[2] only
98 return getBinAt(i, j, k);
99 }
100 }
101
102 if (this->mIgnoreOverflows) {
103 return -1;
104 }
105
106 // overflow for mBins[1] only
107 if constexpr (N > 2) {
108 for (k = 2; k < this->mBins[2].size(); k++) {
109 if (std::get<2>(data) < this->mBins[2][k]) {
110 return getBinAt(i, j, k);
111 }
112 }
113 }
114 }
115
116 // overflow for mBins[2] and mBins[1]
117 return getBinAt(i, j, k);
118 }
119 }
120
121 if (this->mIgnoreOverflows) {
122 // overflow
123 return -1;
124 }
125
126 // overflow for mBins[0] only
127 if constexpr (N > 1) {
128 for (j = 2; j < this->mBins[1].size(); j++) {
129 if (std::get<1>(data) < this->mBins[1][j]) {
130
131 if constexpr (N > 2) {
132 for (k = 2; k < this->mBins[2].size(); k++) {
133 if (std::get<2>(data) < this->mBins[2][k]) {
134 return getBinAt(i, j, k);
135 }
136 }
137 }
138
139 // overflow for mBins[0] and mBins[2]
140 return getBinAt(i, j, k);
141 }
142 }
143 }
144
145 // overflow for mBins[0] and mBins[1]
146 if constexpr (N > 2) {
147 for (k = 2; k < this->mBins[2].size(); k++) {
148 if (std::get<2>(data) < this->mBins[2][k]) {
149 return getBinAt(i, j, k);
150 }
151 }
152 }
153
154 // overflow for all bins
155 return getBinAt(i, j, k);
156 }
157
158 // Note: Overflow / underflow bin -1 is not included
159 int getXBinsCount() const
160 {
161 return getBinsCount(mBins[0]);
162 }
163
164 // Note: Overflow / underflow bin -1 is not included
165 int getYBinsCount() const
166 {
167 if constexpr (N == 1) {
168 return 0;
169 }
170 return getBinsCount(mBins[1]);
171 }
172
173 // Note: Overflow / underflow bin -1 is not included
174 int getZBinsCount() const
175 {
176 if constexpr (N < 3) {
177 return 0;
178 }
179 return getBinsCount(mBins[2]);
180 }
181
182 // Note: Overflow / underflow bin -1 is not included
183 int getAllBinsCount() const
184 {
185 if constexpr (N == 1) {
186 return getXBinsCount();
187 }
188 if constexpr (N == 2) {
189 return getXBinsCount() * getYBinsCount();
190 }
191 if constexpr (N == 2) {
193 }
194 return -1;
195 }
196
197 std::array<std::vector<double>, N> mBins;
199
200 private:
201 // We substract 1 to account for VARIABLE_WIDTH in the bins vector
202 // We substract second 1 if we omit values below minima (underflow, mapped to -1)
203 // Otherwise we add 1 and we get the number of bins including those below and over the outer edges
204 int getBinAt(unsigned int iRaw, unsigned int jRaw, unsigned int kRaw) const
205 {
206 int shiftBinsWithoutOverflow = getOverflowShift();
207 unsigned int i = iRaw - 1 - shiftBinsWithoutOverflow;
208 unsigned int j = jRaw - 1 - shiftBinsWithoutOverflow;
209 unsigned int k = kRaw - 1 - shiftBinsWithoutOverflow;
210 auto xBinsCount = getXBinsCount();
211 if constexpr (N == 1) {
212 return i;
213 } else if constexpr (N == 2) {
214 return i + j * xBinsCount;
215 } else if constexpr (N == 3) {
216 return i + j * xBinsCount + k * xBinsCount * getYBinsCount();
217 } else {
218 return -1;
219 }
220 }
221
222 int getOverflowShift() const
223 {
224 return mIgnoreOverflows ? 1 : -1;
225 }
226
227 // Note: Overflow / underflow bin -1 is not included
228 int getBinsCount(std::vector<double> const& bins) const
229 {
230 return bins.size() - 1 - getOverflowShift();
231 }
232};
233
234template <typename, typename...>
236
237template <typename... Ts, typename... Ls>
238struct FlexibleBinningPolicy<std::tuple<Ls...>, Ts...> : BinningPolicyBase<sizeof...(Ts)> {
239 FlexibleBinningPolicy(std::tuple<Ls...> const& lambdaPtrs, std::array<std::vector<double>, sizeof...(Ts)> bins, bool ignoreOverflows = true) : BinningPolicyBase<sizeof...(Ts)>(bins, ignoreOverflows), mBinningFunctions{lambdaPtrs}
240 {
241 }
242
243 template <typename T, typename T2>
244 auto getBinningValue(T& rowIterator, arrow::Table* table, uint64_t ci = -1, uint64_t ai = -1, uint64_t globalIndex = -1) const
245 {
246 if constexpr (has_type<T2>(pack<Ls...>{})) {
247 if (globalIndex != -1) {
248 rowIterator.setCursor(globalIndex);
249 }
250 return std::get<T2>(mBinningFunctions)(rowIterator);
251 } else {
252 return soa::row_helpers::getSingleRowData<T, T2>(table, rowIterator, ci, ai, globalIndex);
253 }
254 }
255
256 template <typename T>
257 auto getBinningValues(T& rowIterator, arrow::Table* table, uint64_t ci = -1, uint64_t ai = -1, uint64_t globalIndex = -1) const
258 {
259 return std::make_tuple(getBinningValue<T, Ts>(rowIterator, table, ci, ai, globalIndex)...);
260 }
261
262 template <typename T>
263 auto getBinningValues(typename T::iterator rowIterator, T& table, uint64_t ci = -1, uint64_t ai = -1, uint64_t globalIndex = -1) const
264 {
265 return getBinningValues(rowIterator, table.asArrowTable().get(), ci, ai, globalIndex);
266 }
267
268 template <typename... T2s>
269 int getBin(std::tuple<T2s...> const& data) const
270 {
271 return BinningPolicyBase<sizeof...(Ts)>::template getBin<T2s...>(data);
272 }
273
275
276 private:
277 std::tuple<Ls...> mBinningFunctions;
278};
279
280template <typename... Ts>
281struct ColumnBinningPolicy : BinningPolicyBase<sizeof...(Ts)> {
282 ColumnBinningPolicy(std::array<std::vector<double>, sizeof...(Ts)> bins, bool ignoreOverflows = true) : BinningPolicyBase<sizeof...(Ts)>(bins, ignoreOverflows)
283 {
284 }
285
286 template <typename T>
287 auto getBinningValues(T& rowIterator, arrow::Table* table, uint64_t ci = -1, uint64_t ai = -1, uint64_t globalIndex = -1) const
288 {
289 return std::make_tuple(soa::row_helpers::getSingleRowData<T, Ts>(table, rowIterator, ci, ai, globalIndex)...);
290 }
291
292 template <typename T>
293 auto getBinningValues(typename T::iterator rowIterator, T& table, uint64_t ci = -1, uint64_t ai = -1, uint64_t globalIndex = -1) const
294 {
295 return getBinningValues(rowIterator, table.asArrowTable().get(), ci, ai, globalIndex);
296 }
297
298 int getBin(std::tuple<typename Ts::type...> const& data) const
299 {
300 return BinningPolicyBase<sizeof...(Ts)>::template getBin<typename Ts::type...>(data);
301 }
302
304};
305
306template <typename C>
308 // Just take the bin number from the column data
309 NoBinningPolicy() = default;
310
311 template <typename T>
312 auto getBinningValues(T& rowIterator, arrow::Table* table, uint64_t ci = -1, uint64_t ai = -1, uint64_t globalIndex = -1) const
313 {
314 return std::make_tuple(soa::row_helpers::getSingleRowData<T, C>(table, rowIterator, ci, ai, globalIndex));
315 }
316
317 template <typename T>
318 auto getBinningValues(typename T::iterator rowIterator, T& table, uint64_t ci = -1, uint64_t ai = -1, uint64_t globalIndex = -1) const
319 {
320 return getBinningValues(rowIterator, table.asArrowTable().get(), ci, ai, globalIndex);
321 }
322
323 int getBin(std::tuple<typename C::type> const& data) const
324 {
325 return std::get<0>(data);
326 }
327
329};
330
331} // namespace o2::framework
332#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:192
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