11 #ifndef ROOT_RDF_TINTERFACE_UTILS
12 #define ROOT_RDF_TINTERFACE_UTILS
36 #include <type_traits>
51 template<
typename T,
typename V>
53 using RNode = RInterface<::ROOT::Detail::RDF::RNodeBase, void>;
64 using namespace ROOT::Detail::RDF;
65 using namespace ROOT::RDF;
66 namespace TTraits = ROOT::TypeTraits;
67 namespace RDFInternal = ROOT::Internal::RDF;
69 using HeadNode_t = ::ROOT::RDF::RResultPtr<RInterface<RLoopManager, void>>;
70 HeadNode_t CreateSnapshotRDF(
const ColumnNames_t &validCols,
71 std::string_view treeName,
72 std::string_view fileName,
74 RLoopManager &loopManager,
75 std::unique_ptr<RDFInternal::RActionBase> actionPtr);
77 std::string DemangleTypeIdName(
const std::type_info &typeInfo);
79 ColumnNames_t ConvertRegexToColumns(
const RDFInternal::RBookedCustomColumns &customColumns, TTree *tree,
80 ROOT::RDF::RDataSource *dataSource, std::string_view columnNameRegexp,
81 std::string_view callerName);
84 class RIgnoreErrorLevelRAII {
86 int fCurIgnoreErrorLevel = gErrorIgnoreLevel;
89 RIgnoreErrorLevelRAII(
int errorIgnoreLevel) { gErrorIgnoreLevel = errorIgnoreLevel; }
90 RIgnoreErrorLevelRAII() { gErrorIgnoreLevel = fCurIgnoreErrorLevel; }
97 namespace ActionTags {
114 template <typename T, bool ISV6HISTO = std::is_base_of<TH1, T>::value>
116 static void SetCanExtendAllAxes(T &h) { h.SetCanExtend(::TH1::kAllAxes); }
117 static bool HasAxisLimits(T &h)
119 auto xaxis = h.GetXaxis();
120 return !(xaxis->GetXmin() == 0. && xaxis->GetXmax() == 0.);
124 template <
typename T>
125 struct HistoUtils<T, false> {
126 static void SetCanExtendAllAxes(T &) {}
127 static bool HasAxisLimits(T &) {
return true; }
131 template <
typename... BranchTypes,
typename ActionTag,
typename ActionResultType,
typename PrevNodeType>
132 std::unique_ptr<RActionBase>
133 BuildAction(
const ColumnNames_t &bl,
const std::shared_ptr<ActionResultType> &h,
const unsigned int nSlots,
134 std::shared_ptr<PrevNodeType> prevNode, ActionTag, RDFInternal::RBookedCustomColumns &&customColumns)
136 using Helper_t = FillParHelper<ActionResultType>;
137 using Action_t = RAction<Helper_t, PrevNodeType, TTraits::TypeList<BranchTypes...>>;
138 return std::make_unique<Action_t>(Helper_t(h, nSlots), bl, std::move(prevNode), std::move(customColumns));
142 template <
typename... BranchTypes,
typename PrevNodeType>
143 std::unique_ptr<RActionBase> BuildAction(
const ColumnNames_t &bl,
const std::shared_ptr<::TH1D> &h,
144 const unsigned int nSlots, std::shared_ptr<PrevNodeType> prevNode,
145 ActionTags::Histo1D, RDFInternal::RBookedCustomColumns &&customColumns)
147 auto hasAxisLimits = HistoUtils<::TH1D>::HasAxisLimits(*h);
150 using Helper_t = FillParHelper<::TH1D>;
151 using Action_t = RAction<Helper_t, PrevNodeType, TTraits::TypeList<BranchTypes...>>;
152 return std::make_unique<Action_t>(Helper_t(h, nSlots), bl, std::move(prevNode), std::move(customColumns));
154 using Helper_t = FillHelper;
155 using Action_t = RAction<Helper_t, PrevNodeType, TTraits::TypeList<BranchTypes...>>;
156 return std::make_unique<Action_t>(Helper_t(h, nSlots), bl, std::move(prevNode), std::move(customColumns));
160 template <
typename... BranchTypes,
typename PrevNodeType>
161 std::unique_ptr<RActionBase> BuildAction(
const ColumnNames_t &bl,
const std::shared_ptr<TGraph> &g,
162 const unsigned int nSlots, std::shared_ptr<PrevNodeType> prevNode,
163 ActionTags::Graph, RDFInternal::RBookedCustomColumns &&customColumns)
165 using Helper_t = FillTGraphHelper;
166 using Action_t = RAction<Helper_t, PrevNodeType, TTraits::TypeList<BranchTypes...>>;
167 return std::make_unique<Action_t>(Helper_t(g, nSlots), bl, std::move(prevNode), std::move(customColumns));
171 template <
typename BranchType,
typename PrevNodeType,
typename ActionResultType>
172 std::unique_ptr<RActionBase> BuildAction(
const ColumnNames_t &bl,
const std::shared_ptr<ActionResultType> &minV,
173 const unsigned int nSlots, std::shared_ptr<PrevNodeType> prevNode,
174 ActionTags::Min, RDFInternal::RBookedCustomColumns &&customColumns)
176 using Helper_t = MinHelper<ActionResultType>;
177 using Action_t = RAction<Helper_t, PrevNodeType, TTraits::TypeList<BranchType>>;
178 return std::make_unique<Action_t>(Helper_t(minV, nSlots), bl, std::move(prevNode), std::move(customColumns));
182 template <
typename BranchType,
typename PrevNodeType,
typename ActionResultType>
183 std::unique_ptr<RActionBase> BuildAction(
const ColumnNames_t &bl,
const std::shared_ptr<ActionResultType> &maxV,
184 const unsigned int nSlots, std::shared_ptr<PrevNodeType> prevNode,
185 ActionTags::Max, RDFInternal::RBookedCustomColumns &&customColumns)
187 using Helper_t = MaxHelper<ActionResultType>;
188 using Action_t = RAction<Helper_t, PrevNodeType, TTraits::TypeList<BranchType>>;
189 return std::make_unique<Action_t>(Helper_t(maxV, nSlots), bl, std::move(prevNode), std::move(customColumns));
193 template <
typename BranchType,
typename PrevNodeType,
typename ActionResultType>
194 std::unique_ptr<RActionBase> BuildAction(
const ColumnNames_t &bl,
const std::shared_ptr<ActionResultType> &sumV,
195 const unsigned int nSlots, std::shared_ptr<PrevNodeType> prevNode,
196 ActionTags::Sum, RDFInternal::RBookedCustomColumns &&customColumns)
198 using Helper_t = SumHelper<ActionResultType>;
199 using Action_t = RAction<Helper_t, PrevNodeType, TTraits::TypeList<BranchType>>;
200 return std::make_unique<Action_t>(Helper_t(sumV, nSlots), bl, std::move(prevNode), std::move(customColumns));
204 template <
typename BranchType,
typename PrevNodeType>
205 std::unique_ptr<RActionBase> BuildAction(
const ColumnNames_t &bl,
const std::shared_ptr<double> &meanV,
206 const unsigned int nSlots, std::shared_ptr<PrevNodeType> prevNode,
207 ActionTags::Mean, RDFInternal::RBookedCustomColumns &&customColumns)
209 using Helper_t = MeanHelper;
210 using Action_t = RAction<Helper_t, PrevNodeType, TTraits::TypeList<BranchType>>;
211 return std::make_unique<Action_t>(Helper_t(meanV, nSlots), bl, std::move(prevNode), std::move(customColumns));
215 template <
typename BranchType,
typename PrevNodeType>
216 std::unique_ptr<RActionBase> BuildAction(
const ColumnNames_t &bl,
const std::shared_ptr<double> &stdDeviationV,
217 const unsigned int nSlots, std::shared_ptr<PrevNodeType> prevNode,
218 ActionTags::StdDev, RDFInternal::RBookedCustomColumns &&customColumns)
220 using Helper_t = StdDevHelper;
221 using Action_t = RAction<Helper_t, PrevNodeType, TTraits::TypeList<BranchType>>;
222 return std::make_unique<Action_t>(Helper_t(stdDeviationV, nSlots), bl, prevNode, std::move(customColumns));
226 template <
typename... BranchTypes,
typename PrevNodeType>
227 std::unique_ptr<RActionBase> BuildAction(
const ColumnNames_t &bl,
const std::shared_ptr<RDisplay> &d,
228 const unsigned int, std::shared_ptr<PrevNodeType> prevNode,
229 ActionTags::Display, RDFInternal::RBookedCustomColumns &&customColumns)
231 using Helper_t = DisplayHelper<PrevNodeType>;
232 using Action_t = RAction<Helper_t, PrevNodeType, TTraits::TypeList<BranchTypes...>>;
233 return std::make_unique<Action_t>(Helper_t(d, prevNode), bl, prevNode, std::move(customColumns));
238 template <
typename Filter>
239 void CheckFilter(Filter &)
241 using FilterRet_t =
typename RDF::CallableTraits<Filter>::ret_type;
242 static_assert(std::is_convertible<FilterRet_t, bool>::value,
243 "filter expression returns a type that is not convertible to bool");
246 void CheckCustomColumn(std::string_view definedCol, TTree *treePtr,
const ColumnNames_t &customCols,
247 const std::map<std::string, std::string> &aliasMap,
const ColumnNames_t &dataSourceColumns);
249 std::string PrettyPrintAddr(
const void *
const addr);
251 void BookFilterJit(RJittedFilter *jittedFilter,
void *prevNodeOnHeap, std::string_view name,
252 std::string_view expression,
const std::map<std::string, std::string> &aliasMap,
253 const ColumnNames_t &branches,
const RDFInternal::RBookedCustomColumns &customCols, TTree *tree,
254 RDataSource *ds,
unsigned int namespaceID);
256 void BookDefineJit(std::string_view name, std::string_view expression, RLoopManager &lm, RDataSource *ds,
257 const std::shared_ptr<RJittedCustomColumn> &jittedCustomColumn,
258 const RDFInternal::RBookedCustomColumns &customCols,
const ColumnNames_t &branches);
260 std::string JitBuildAction(
const ColumnNames_t &bl,
void *prevNode,
const std::type_info &art,
const std::type_info &at,
261 void *r, TTree *tree,
const unsigned int nSlots,
262 const RDFInternal::RBookedCustomColumns &customColumns, RDataSource *ds,
263 std::shared_ptr<RJittedAction> *jittedActionOnHeap,
unsigned int namespaceID);
271 template <
typename T>
272 std::shared_ptr<T> *MakeSharedOnHeap(
const std::shared_ptr<T> &shPtr)
274 return new std::shared_ptr<T>(shPtr);
277 bool AtLeastOneEmptyString(
const std::vector<std::string_view> strings);
281 std::shared_ptr<RNodeBase> UpcastNode(std::shared_ptr<RNodeBase> ptr);
283 ColumnNames_t GetValidatedColumnNames(RLoopManager &lm,
const unsigned int nColumns,
const ColumnNames_t &columns,
284 const ColumnNames_t &validCustomColumns, RDataSource *ds);
286 std::vector<bool> FindUndefinedDSColumns(
const ColumnNames_t &requestedCols,
const ColumnNames_t &definedDSCols);
288 using ColumnNames_t = ROOT::Detail::RDF::ColumnNames_t;
290 template <
typename T>
291 void AddDSColumnsHelper(RLoopManager &lm, std::string_view name, RDFInternal::RBookedCustomColumns ¤tCols,
292 RDataSource &ds,
unsigned int nSlots)
294 auto readers = ds.GetColumnReaders<T>(name);
295 auto getValue = [readers](
unsigned int slot) {
return *readers[slot]; };
296 using NewCol_t = RCustomColumn<decltype(getValue), CustomColExtraArgs::Slot>;
298 auto newCol = std::make_shared<NewCol_t>(&lm, name, std::move(getValue), ColumnNames_t{}, nSlots, currentCols,
301 lm.RegisterCustomColumn(newCol.get());
302 currentCols.AddName(name);
303 currentCols.AddColumn(newCol, name);
308 template <
typename... ColumnTypes, std::size_t... S>
309 RDFInternal::RBookedCustomColumns
310 AddDSColumns(RLoopManager &lm,
const std::vector<std::string> &requiredCols,
311 const RDFInternal::RBookedCustomColumns ¤tCols, RDataSource &ds,
unsigned int nSlots,
312 std::index_sequence<S...>, TTraits::TypeList<ColumnTypes...>)
315 const auto mustBeDefined = FindUndefinedDSColumns(requiredCols, currentCols.GetNames());
316 if (std::none_of(mustBeDefined.begin(), mustBeDefined.end(), [](
bool b) {
return b; })) {
320 auto newColumns(currentCols);
323 int expander[] = {(mustBeDefined[S] ? AddDSColumnsHelper<ColumnTypes>(lm, requiredCols[S], newColumns, ds, nSlots)
334 template <
typename F,
typename PrevNode>
335 void JitFilterHelper(F &&f,
const ColumnNames_t &cols, std::string_view name, RJittedFilter *jittedFilter,
336 std::shared_ptr<PrevNode> *prevNodeOnHeap, RDFInternal::RBookedCustomColumns *customColumns)
339 using F_t = RFilter<F, PrevNode>;
340 using ColTypes_t =
typename TTraits::CallableTraits<F>::arg_types;
341 constexpr
auto nColumns = ColTypes_t::list_size;
342 RDFInternal::CheckFilter(f);
344 auto &lm = *jittedFilter->GetLoopManagerUnchecked();
345 auto ds = lm.GetDataSource();
347 auto newColumns = ds ? RDFInternal::AddDSColumns(lm, cols, *customColumns, *ds, lm.GetNSlots(),
348 std::make_index_sequence<nColumns>(), ColTypes_t())
353 delete customColumns;
355 jittedFilter->SetFilter(std::make_unique<F_t>(std::move(f), cols, *prevNodeOnHeap, newColumns, name));
356 delete prevNodeOnHeap;
359 template <
typename F>
360 void JitDefineHelper(F &&f,
const ColumnNames_t &cols, std::string_view name, RLoopManager *lm,
361 RJittedCustomColumn &jittedCustomCol, RDFInternal::RBookedCustomColumns *customColumns)
363 using NewCol_t = RCustomColumn<F, CustomColExtraArgs::None>;
364 using ColTypes_t =
typename TTraits::CallableTraits<F>::arg_types;
365 constexpr
auto nColumns = ColTypes_t::list_size;
367 auto ds = lm->GetDataSource();
368 auto newColumns = ds ? RDFInternal::AddDSColumns(*lm, cols, *customColumns, *ds, lm->GetNSlots(),
369 std::make_index_sequence<nColumns>(), ColTypes_t())
374 delete customColumns;
376 jittedCustomCol.SetCustomColumn(
377 std::make_unique<NewCol_t>(lm, name, std::move(f), cols, lm->GetNSlots(), newColumns));
381 template <
typename ActionTag,
typename... BranchTypes,
typename PrevNodeType,
typename ActionResultType>
382 void CallBuildAction(std::shared_ptr<PrevNodeType> *prevNodeOnHeap,
const ColumnNames_t &bl,
const unsigned int nSlots,
383 const std::shared_ptr<ActionResultType> *rOnHeap,
384 std::shared_ptr<RJittedAction> *jittedActionOnHeap,
385 RDFInternal::RBookedCustomColumns *customColumns)
388 auto &prevNodePtr = *prevNodeOnHeap;
389 auto &loopManager = *prevNodePtr->GetLoopManagerUnchecked();
390 using ColTypes_t = TypeList<BranchTypes...>;
391 constexpr
auto nColumns = ColTypes_t::list_size;
392 auto ds = loopManager.GetDataSource();
393 auto newColumns = ds ? RDFInternal::AddDSColumns(loopManager, bl, *customColumns, *ds, loopManager.GetNSlots(),
394 std::make_index_sequence<nColumns>(), ColTypes_t())
398 BuildAction<BranchTypes...>(bl, *rOnHeap, nSlots, std::move(prevNodePtr), ActionTag{}, std::move(newColumns));
399 (*jittedActionOnHeap)->SetAction(std::move(actionPtr));
403 delete customColumns;
406 delete prevNodeOnHeap;
407 delete jittedActionOnHeap;
411 template <typename T, bool Container = TTraits::IsContainer<T>::value && !std::is_same<T, std::string>::value>
412 struct TMinReturnType {
417 struct TMinReturnType<RInferredType, false> {
421 template <
typename T>
422 struct TMinReturnType<T, true> {
423 using type = TTraits::TakeFirstParameter_t<T>;
427 template <
typename R,
typename F,
typename... Args>
428 std::function<R(
unsigned int, Args...)> AddSlotParameter(F &f, TypeList<Args...>)
430 return [f](
unsigned int, Args... a) -> R {
return f(a...); };
433 template <
typename BranchType,
typename... Rest>
434 struct TNeedJitting {
435 static constexpr
bool value = TNeedJitting<Rest...>::value;
438 template <
typename... Rest>
439 struct TNeedJitting<RInferredType, Rest...> {
440 static constexpr
bool value =
true;
443 template <
typename T>
444 struct TNeedJitting<T> {
445 static constexpr
bool value =
false;
449 struct TNeedJitting<RInferredType> {
450 static constexpr
bool value =
true;
453 ColumnNames_t GetTopLevelBranchNames(TTree &t);
459 template <typename R, typename Merge, typename U, typename T, typename decayedU = typename std::decay<U>::type,
460 typename mergeArgsNoDecay_t =
typename CallableTraits<Merge>::arg_types_nodecay,
461 typename mergeArgs_t =
typename CallableTraits<Merge>::arg_types,
462 typename mergeRet_t =
typename CallableTraits<Merge>::ret_type>
463 void CheckAggregate(TypeList<U, T>)
465 constexpr
bool isAggregatorOk =
466 (std::is_same<R, decayedU>::value) || (std::is_same<R, void>::value && std::is_lvalue_reference<U>::value);
467 static_assert(isAggregatorOk,
"aggregator function must have signature `U(U,T)` or `void(U&,T)`");
468 constexpr
bool isMergeOk =
469 (std::is_same<TypeList<decayedU, decayedU>, mergeArgs_t>::value && std::is_same<decayedU, mergeRet_t>::value) ||
470 (std::is_same<TypeList<std::vector<decayedU> &>, mergeArgsNoDecay_t>::value &&
471 std::is_same<void, mergeRet_t>::value);
472 static_assert(isMergeOk,
"merge function must have signature `U(U,U)` or `void(std::vector<U>&)`");
477 template <
typename R,
typename T>
478 void CheckAggregate(T)
480 static_assert(
sizeof(T) == 0,
"aggregator function must take exactly two arguments");
485 void CheckTypesAndPars(
unsigned int nTemplateParams,
unsigned int nColumnNames);
488 const ColumnNames_t SelectColumns(
unsigned int nArgs,
const ColumnNames_t &bl,
const ColumnNames_t &defBl);
491 ColumnNames_t FindUnknownColumns(
const ColumnNames_t &requiredCols,
const ColumnNames_t &datasetColumns,
492 const ColumnNames_t &definedCols,
const ColumnNames_t &dataSourceColumns);
494 bool IsInternalColumn(std::string_view colName);
497 std::vector<std::string> GetFilterNames(
const std::shared_ptr<RLoopManager> &loopManager);
500 template <
typename NodeType>
501 std::vector<std::string> GetFilterNames(
const std::shared_ptr<NodeType> &node)
503 std::vector<std::string> filterNames;
504 node->AddFilterName(filterNames);
512 template <
bool... bs>
513 using IsTrueForAllImpl_t =
typename std::is_same<TBoolPack<bs...,
true>, TBoolPack<
true, bs...>>;
515 template <
bool... Conditions>
517 static constexpr
bool value = IsTrueForAllImpl_t<Conditions...>::value;
524 struct IsList_t : std::false_type {};
526 template <
typename T>
527 struct IsList_t<std::list<T>> : std::true_type {};
530 struct IsDeque_t : std::false_type {};
532 template <
typename T>
533 struct IsDeque_t<std::deque<T>> : std::true_type {};
543 template <
typename T>
544 using MinReturnType_t =
typename RDFInternal::TMinReturnType<T>::type;
546 template <
typename T>
547 using MaxReturnType_t = MinReturnType_t<T>;
549 template <
typename T>
550 using SumReturnType_t = MinReturnType_t<T>;