Skip to content

Commit 828216a

Browse files
authored
DPL: improve HistogramRegistry.h (#13863)
- Use concepts to determine which fill operation applies to a given kind of histograms. - Make sure we out of line invalid filling operations.
1 parent 240fad5 commit 828216a

File tree

2 files changed

+93
-34
lines changed

2 files changed

+93
-34
lines changed

Framework/Core/include/Framework/HistogramRegistry.h

Lines changed: 88 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,10 @@
2626
#include <TDataMember.h>
2727
#include <TDataType.h>
2828
#include <TArrayL.h>
29+
#include <TProfile2D.h>
30+
#include <fmt/core.h>
2931

32+
#include <concepts>
3033
#include <deque>
3134

3235
class TList;
@@ -43,11 +46,58 @@ namespace o2::framework
4346
template <typename T>
4447
concept FillValue = std::is_integral_v<T> || std::is_floating_point_v<T> || std::is_enum_v<T>;
4548

49+
template <typename T, int dimensions>
50+
concept ValidTH3 = std::same_as<T, TH3> && (dimensions == 3 || dimensions == 4);
51+
52+
template <typename T, int dimensions>
53+
concept ValidTH2 = std::same_as<T, TH2> && (dimensions == 2 || dimensions == 3);
54+
55+
template <typename T, int dimensions>
56+
concept ValidTH1 = std::same_as<T, TH1> && (dimensions == 1 || dimensions == 2);
57+
58+
template <typename T, int dimensions>
59+
concept ValidTProfile3D = std::same_as<T, TProfile3D> && (dimensions == 4 || dimensions == 5);
60+
61+
template <typename T, int dimensions>
62+
concept ValidTProfile2D = std::same_as<T, TProfile2D> && (dimensions == 3 || dimensions == 4);
63+
64+
template <typename T, int dimensions>
65+
concept ValidTProfile = std::same_as<T, TProfile> && (dimensions == 2 || dimensions == 3);
66+
67+
template <typename T, int D>
68+
concept ValidSimpleFill = ValidTH1<T, D> || ValidTH2<T, D> || ValidTH3<T, D> || ValidTProfile<T, D> || ValidTProfile2D<T, D> || ValidTProfile3D<T, D>;
69+
70+
template <typename T, int D>
71+
concept ValidComplexFill = std::is_base_of_v<THnBase, T>;
72+
73+
template <typename T, int D>
74+
concept ValidComplexFillStep = std::is_base_of_v<StepTHn, T>;
75+
76+
template <typename T, int D>
77+
concept ValidFill = ValidSimpleFill<T, D> || ValidComplexFill<T, D> || ValidComplexFillStep<T, D>;
78+
4679
struct HistFiller {
4780
// fill any type of histogram (if weight was requested it must be the last argument)
4881
template <typename T, typename... Ts>
4982
static void fillHistAny(std::shared_ptr<T> hist, Ts... positionAndWeight)
50-
requires(FillValue<Ts> && ...);
83+
requires ValidSimpleFill<T, sizeof...(Ts)> && (FillValue<Ts> && ...);
84+
85+
template <typename T, typename... Ts>
86+
static void fillHistAny(std::shared_ptr<T> hist, Ts... positionAndWeight)
87+
requires ValidComplexFill<T, sizeof...(Ts)> && (FillValue<Ts> && ...);
88+
89+
template <typename T, typename... Ts>
90+
static void fillHistAny(std::shared_ptr<T> hist, Ts... positionAndWeight)
91+
requires ValidComplexFillStep<T, sizeof...(Ts)> && (FillValue<Ts> && ...);
92+
93+
// This applies only for the non-viable cases
94+
template <typename T, typename... Ts>
95+
static void fillHistAny(std::shared_ptr<T> hist, Ts... positionAndWeight);
96+
97+
// fill any type of histogram with columns (Cs) of a filtered table (if weight is requested it must reside the last specified column)
98+
template <typename... Cs, typename R, typename T>
99+
static void fillHistAny(std::shared_ptr<R> hist, const T& table, const o2::framework::expressions::Filter& filter)
100+
requires(!ValidComplexFillStep<R, sizeof...(Cs)>) && requires(T t) { t.asArrowTable(); };
51101

52102
// fill any type of histogram with columns (Cs) of a filtered table (if weight is requested it must reside the last specified column)
53103
template <typename... Cs, typename R, typename T>
@@ -67,6 +117,8 @@ struct HistFiller {
67117

68118
template <typename B, typename T>
69119
static int getBaseElementSize(T* ptr);
120+
121+
static void badHistogramFill(char const* name);
70122
};
71123

72124
//**************************************************************************************************
@@ -203,58 +255,60 @@ class HistogramRegistry
203255
// Implementation of HistFiller template functions.
204256
//--------------------------------------------------------------------------------------------------
205257
//--------------------------------------------------------------------------------------------------
258+
template <typename T, typename... Ts>
259+
void HistFiller::fillHistAny(std::shared_ptr<T> hist, Ts... positionAndWeight)
260+
requires ValidSimpleFill<T, sizeof...(Ts)> && (FillValue<Ts> && ...)
261+
{
262+
hist->Fill(static_cast<double>(positionAndWeight)...);
263+
}
206264

207265
template <typename T, typename... Ts>
208266
void HistFiller::fillHistAny(std::shared_ptr<T> hist, Ts... positionAndWeight)
209-
requires(FillValue<Ts> && ...)
267+
requires ValidComplexFill<T, sizeof...(Ts)> && (FillValue<Ts> && ...)
210268
{
211269
constexpr int nArgs = sizeof...(Ts);
212270

213-
constexpr bool validTH3 = (std::is_same_v<TH3, T> && (nArgs == 3 || nArgs == 4));
214-
constexpr bool validTH2 = (std::is_same_v<TH2, T> && (nArgs == 2 || nArgs == 3));
215-
constexpr bool validTH1 = (std::is_same_v<TH1, T> && (nArgs == 1 || nArgs == 2));
216-
constexpr bool validTProfile3D = (std::is_same_v<TProfile3D, T> && (nArgs == 4 || nArgs == 5));
217-
constexpr bool validTProfile2D = (std::is_same_v<TProfile2D, T> && (nArgs == 3 || nArgs == 4));
218-
constexpr bool validTProfile = (std::is_same_v<TProfile, T> && (nArgs == 2 || nArgs == 3));
219-
220-
constexpr bool validSimpleFill = validTH1 || validTH2 || validTH3 || validTProfile || validTProfile2D || validTProfile3D;
221-
// unfortunately we dont know at compile the dimension of THn(Sparse)
222-
constexpr bool validComplexFill = std::is_base_of_v<THnBase, T>;
223-
constexpr bool validComplexFillStep = std::is_base_of_v<StepTHn, T>;
224-
225-
if constexpr (validSimpleFill) {
226-
hist->Fill(static_cast<double>(positionAndWeight)...);
227-
} else if constexpr (validComplexFillStep) {
228-
hist->Fill(positionAndWeight...); // first argument in pack is iStep, dimension check is done in StepTHn itself
229-
} else if constexpr (validComplexFill) {
230-
double tempArray[] = {static_cast<double>(positionAndWeight)...};
231-
double weight{1.};
232-
constexpr int nArgsMinusOne = nArgs - 1;
233-
if (hist->GetNdimensions() == nArgsMinusOne) {
234-
weight = tempArray[nArgsMinusOne];
235-
} else if (hist->GetNdimensions() != nArgs) {
236-
LOGF(fatal, "The number of arguments in fill function called for histogram %s is incompatible with histogram dimensions.", hist->GetName());
237-
}
238-
hist->Fill(tempArray, weight);
239-
} else {
240-
LOGF(fatal, "The number of arguments in fill function called for histogram %s is incompatible with histogram dimensions.", hist->GetName());
271+
double tempArray[] = {static_cast<double>(positionAndWeight)...};
272+
double weight{1.};
273+
constexpr int nArgsMinusOne = nArgs - 1;
274+
if (hist->GetNdimensions() == nArgsMinusOne) {
275+
weight = tempArray[nArgsMinusOne];
276+
} else if (hist->GetNdimensions() != nArgs) {
277+
badHistogramFill(hist->GetName());
241278
}
279+
hist->Fill(tempArray, weight);
280+
}
281+
282+
template <typename T, typename... Ts>
283+
void HistFiller::fillHistAny(std::shared_ptr<T> hist, Ts... positionAndWeight)
284+
requires ValidComplexFillStep<T, sizeof...(Ts)> && (FillValue<Ts> && ...)
285+
{
286+
hist->Fill(positionAndWeight...); // first argument in pack is iStep, dimension check is done in StepTHn itself
287+
}
288+
289+
template <typename T, typename... Ts>
290+
void HistFiller::fillHistAny(std::shared_ptr<T> hist, Ts... positionAndWeight)
291+
{
292+
HistFiller::badHistogramFill(hist->GetName());
242293
}
243294

244295
template <typename... Cs, typename R, typename T>
245296
void HistFiller::fillHistAny(std::shared_ptr<R> hist, const T& table, const o2::framework::expressions::Filter& filter)
297+
requires(!ValidComplexFillStep<R, sizeof...(Cs)>) && requires(T t) { t.asArrowTable(); }
246298
{
247-
if constexpr (std::is_base_of_v<StepTHn, T>) {
248-
LOGF(fatal, "Table filling is not (yet?) supported for StepTHn.");
249-
return;
250-
}
251299
auto s = o2::framework::expressions::createSelection(table.asArrowTable(), filter);
252300
auto filtered = o2::soa::Filtered<T>{{table.asArrowTable()}, s};
253301
for (auto& t : filtered) {
254302
fillHistAny(hist, (*(static_cast<Cs>(t).getIterator()))...);
255303
}
256304
}
257305

306+
template <typename... Cs, typename R, typename T>
307+
void HistFiller::fillHistAny(std::shared_ptr<R> hist, const T& table, const o2::framework::expressions::Filter& filter)
308+
{
309+
HistFiller::badHistogramFill(hist->GetName());
310+
}
311+
258312
template <typename T>
259313
double HistFiller::getSize(std::shared_ptr<T> hist, double fillFraction)
260314
{

Framework/Core/src/HistogramRegistry.cxx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,4 +409,9 @@ void HistogramRegistry::registerName(const std::string& name)
409409
mRegisteredNames.push_back(name);
410410
}
411411

412+
void HistFiller::badHistogramFill(char const* name)
413+
{
414+
LOGF(fatal, "The number of arguments in fill function called for histogram %s is incompatible with histogram dimensions.", name);
415+
}
416+
412417
} // namespace o2::framework

0 commit comments

Comments
 (0)