Logo ROOT  
Reference Guide
InterfaceUtils.hxx
Go to the documentation of this file.
1 // Author: Enrico Guiraud, Danilo Piparo CERN 02/2018
2 
3 /*************************************************************************
4  * Copyright (C) 1995-2018, Rene Brun and Fons Rademakers. *
5  * All rights reserved. *
6  * *
7  * For the licensing terms see $ROOTSYS/LICENSE. *
8  * For the list of contributors see $ROOTSYS/README/CREDITS. *
9  *************************************************************************/
10 
11 #ifndef ROOT_RDF_TINTERFACE_UTILS
12 #define ROOT_RDF_TINTERFACE_UTILS
13 
14 #include <ROOT/RDF/RAction.hxx>
15 #include <ROOT/RDF/ActionHelpers.hxx> // for BuildAction
17 #include <ROOT/RDF/RDefine.hxx>
18 #include <ROOT/RDF/RFilter.hxx>
19 #include <ROOT/RDF/Utils.hxx>
25 #include <ROOT/RMakeUnique.hxx>
26 #include <ROOT/RStringView.hxx>
27 #include <ROOT/TypeTraits.hxx>
28 #include <TError.h> // gErrorIgnoreLevel
29 #include <TH1.h>
30 #include <TROOT.h> // IsImplicitMTEnabled
31 
32 #include <deque>
33 #include <functional>
34 #include <map>
35 #include <memory>
36 #include <string>
37 #include <type_traits>
38 #include <typeinfo>
39 #include <vector>
40 #include <unordered_map>
41 
42 class TObjArray;
43 class TTree;
44 namespace ROOT {
45 namespace Detail {
46 namespace RDF {
47 class RNodeBase;
48 }
49 }
50 namespace RDF {
51 template <typename T>
52 class RResultPtr;
53 template<typename T, typename V>
54 class RInterface;
56 class RDataSource;
57 } // namespace RDF
58 
59 } // namespace ROOT
60 
61 /// \cond HIDDEN_SYMBOLS
62 
63 namespace ROOT {
64 namespace Internal {
65 namespace RDF {
66 using namespace ROOT::Detail::RDF;
67 using namespace ROOT::RDF;
68 namespace TTraits = ROOT::TypeTraits;
70 
72 
73 std::string DemangleTypeIdName(const std::type_info &typeInfo);
74 
76 ConvertRegexToColumns(const ColumnNames_t &colNames, std::string_view columnNameRegexp, std::string_view callerName);
77 
78 /// An helper object that sets and resets gErrorIgnoreLevel via RAII.
79 class RIgnoreErrorLevelRAII {
80 private:
81  int fCurIgnoreErrorLevel = gErrorIgnoreLevel;
82 
83 public:
84  RIgnoreErrorLevelRAII(int errorIgnoreLevel) { gErrorIgnoreLevel = errorIgnoreLevel; }
85  ~RIgnoreErrorLevelRAII() { gErrorIgnoreLevel = fCurIgnoreErrorLevel; }
86 };
87 
88 /****** BuildAction overloads *******/
89 
90 // clang-format off
91 /// This namespace defines types to be used for tag dispatching in RInterface.
92 namespace ActionTags {
93 struct Histo1D{};
94 struct Histo2D{};
95 struct Histo3D{};
96 struct Graph{};
97 struct Profile1D{};
98 struct Profile2D{};
99 struct Min{};
100 struct Max{};
101 struct Sum{};
102 struct Mean{};
103 struct Fill{};
104 struct StdDev{};
105 struct Display{};
106 struct Snapshot{};
107 }
108 // clang-format on
109 
110 template <typename T, bool ISV6HISTO = std::is_base_of<TH1, T>::value>
111 struct HistoUtils {
112  static void SetCanExtendAllAxes(T &h) { h.SetCanExtend(::TH1::kAllAxes); }
113  static bool HasAxisLimits(T &h)
114  {
115  auto xaxis = h.GetXaxis();
116  return !(xaxis->GetXmin() == 0. && xaxis->GetXmax() == 0.);
117  }
118 };
119 
120 template <typename T>
121 struct HistoUtils<T, false> {
122  static void SetCanExtendAllAxes(T &) {}
123  static bool HasAxisLimits(T &) { return true; }
124 };
125 
126 // Generic filling (covers Histo2D, Histo3D, Profile1D and Profile2D actions, with and without weights)
127 template <typename... ColTypes, typename ActionTag, typename ActionResultType, typename PrevNodeType>
128 std::unique_ptr<RActionBase>
129 BuildAction(const ColumnNames_t &bl, const std::shared_ptr<ActionResultType> &h, const unsigned int nSlots,
130  std::shared_ptr<PrevNodeType> prevNode, ActionTag, const RDFInternal::RBookedDefines &defines)
131 {
132  using Helper_t = FillParHelper<ActionResultType>;
133  using Action_t = RAction<Helper_t, PrevNodeType, TTraits::TypeList<ColTypes...>>;
134  return std::make_unique<Action_t>(Helper_t(h, nSlots), bl, std::move(prevNode), defines);
135 }
136 
137 // Histo1D filling (must handle the special case of distinguishing FillParHelper and FillHelper
138 template <typename... ColTypes, typename PrevNodeType>
139 std::unique_ptr<RActionBase> BuildAction(const ColumnNames_t &bl, const std::shared_ptr<::TH1D> &h,
140  const unsigned int nSlots, std::shared_ptr<PrevNodeType> prevNode,
141  ActionTags::Histo1D, const RDFInternal::RBookedDefines &defines)
142 {
143  auto hasAxisLimits = HistoUtils<::TH1D>::HasAxisLimits(*h);
144 
145  if (hasAxisLimits) {
146  using Helper_t = FillParHelper<::TH1D>;
147  using Action_t = RAction<Helper_t, PrevNodeType, TTraits::TypeList<ColTypes...>>;
148  return std::make_unique<Action_t>(Helper_t(h, nSlots), bl, std::move(prevNode), defines);
149  } else {
150  using Helper_t = FillHelper;
151  using Action_t = RAction<Helper_t, PrevNodeType, TTraits::TypeList<ColTypes...>>;
152  return std::make_unique<Action_t>(Helper_t(h, nSlots), bl, std::move(prevNode), defines);
153  }
154 }
155 
156 template <typename... ColTypes, typename PrevNodeType>
157 std::unique_ptr<RActionBase> BuildAction(const ColumnNames_t &bl, const std::shared_ptr<TGraph> &g,
158  const unsigned int nSlots, std::shared_ptr<PrevNodeType> prevNode,
159  ActionTags::Graph, const RDFInternal::RBookedDefines &defines)
160 {
161  using Helper_t = FillTGraphHelper;
162  using Action_t = RAction<Helper_t, PrevNodeType, TTraits::TypeList<ColTypes...>>;
163  return std::make_unique<Action_t>(Helper_t(g, nSlots), bl, std::move(prevNode), defines);
164 }
165 
166 // Min action
167 template <typename ColType, typename PrevNodeType, typename ActionResultType>
168 std::unique_ptr<RActionBase> BuildAction(const ColumnNames_t &bl, const std::shared_ptr<ActionResultType> &minV,
169  const unsigned int nSlots, std::shared_ptr<PrevNodeType> prevNode,
171 {
172  using Helper_t = MinHelper<ActionResultType>;
173  using Action_t = RAction<Helper_t, PrevNodeType, TTraits::TypeList<ColType>>;
174  return std::make_unique<Action_t>(Helper_t(minV, nSlots), bl, std::move(prevNode), defines);
175 }
176 
177 // Max action
178 template <typename ColType, typename PrevNodeType, typename ActionResultType>
179 std::unique_ptr<RActionBase> BuildAction(const ColumnNames_t &bl, const std::shared_ptr<ActionResultType> &maxV,
180  const unsigned int nSlots, std::shared_ptr<PrevNodeType> prevNode,
182 {
183  using Helper_t = MaxHelper<ActionResultType>;
184  using Action_t = RAction<Helper_t, PrevNodeType, TTraits::TypeList<ColType>>;
185  return std::make_unique<Action_t>(Helper_t(maxV, nSlots), bl, std::move(prevNode), defines);
186 }
187 
188 // Sum action
189 template <typename ColType, typename PrevNodeType, typename ActionResultType>
190 std::unique_ptr<RActionBase> BuildAction(const ColumnNames_t &bl, const std::shared_ptr<ActionResultType> &sumV,
191  const unsigned int nSlots, std::shared_ptr<PrevNodeType> prevNode,
193 {
194  using Helper_t = SumHelper<ActionResultType>;
195  using Action_t = RAction<Helper_t, PrevNodeType, TTraits::TypeList<ColType>>;
196  return std::make_unique<Action_t>(Helper_t(sumV, nSlots), bl, std::move(prevNode), defines);
197 }
198 
199 // Mean action
200 template <typename ColType, typename PrevNodeType>
201 std::unique_ptr<RActionBase> BuildAction(const ColumnNames_t &bl, const std::shared_ptr<double> &meanV,
202  const unsigned int nSlots, std::shared_ptr<PrevNodeType> prevNode,
204 {
205  using Helper_t = MeanHelper;
206  using Action_t = RAction<Helper_t, PrevNodeType, TTraits::TypeList<ColType>>;
207  return std::make_unique<Action_t>(Helper_t(meanV, nSlots), bl, std::move(prevNode), defines);
208 }
209 
210 // Standard Deviation action
211 template <typename ColType, typename PrevNodeType>
212 std::unique_ptr<RActionBase> BuildAction(const ColumnNames_t &bl, const std::shared_ptr<double> &stdDeviationV,
213  const unsigned int nSlots, std::shared_ptr<PrevNodeType> prevNode,
215 {
216  using Helper_t = StdDevHelper;
217  using Action_t = RAction<Helper_t, PrevNodeType, TTraits::TypeList<ColType>>;
218  return std::make_unique<Action_t>(Helper_t(stdDeviationV, nSlots), bl, prevNode, defines);
219 }
220 
221 // Display action
222 template <typename... ColTypes, typename PrevNodeType>
223 std::unique_ptr<RActionBase> BuildAction(const ColumnNames_t &bl, const std::shared_ptr<RDisplay> &d,
224  const unsigned int, std::shared_ptr<PrevNodeType> prevNode,
225  ActionTags::Display, const RDFInternal::RBookedDefines &defines)
226 {
227  using Helper_t = DisplayHelper<PrevNodeType>;
228  using Action_t = RAction<Helper_t, PrevNodeType, TTraits::TypeList<ColTypes...>>;
229  return std::make_unique<Action_t>(Helper_t(d, prevNode), bl, prevNode, defines);
230 }
231 
232 struct SnapshotHelperArgs {
233  std::string fFileName;
234  std::string fDirName;
235  std::string fTreeName;
236  std::vector<std::string> fOutputColNames;
238 };
239 
240 // Snapshot action
241 template <typename... ColTypes, typename PrevNodeType>
242 std::unique_ptr<RActionBase>
243 BuildAction(const ColumnNames_t &colNames, const std::shared_ptr<SnapshotHelperArgs> &snapHelperArgs,
244  const unsigned int nSlots, std::shared_ptr<PrevNodeType> prevNode, ActionTags::Snapshot,
245  const RDFInternal::RBookedDefines &defines)
246 {
247  const auto &filename = snapHelperArgs->fFileName;
248  const auto &dirname = snapHelperArgs->fDirName;
249  const auto &treename = snapHelperArgs->fTreeName;
250  const auto &outputColNames = snapHelperArgs->fOutputColNames;
251  const auto &options = snapHelperArgs->fOptions;
252 
253  std::unique_ptr<RActionBase> actionPtr;
254  if (!ROOT::IsImplicitMTEnabled()) {
255  // single-thread snapshot
256  using Helper_t = SnapshotHelper<ColTypes...>;
257  using Action_t = RAction<Helper_t, PrevNodeType>;
258  actionPtr.reset(new Action_t(Helper_t(filename, dirname, treename, colNames, outputColNames, options), colNames,
259  prevNode, defines));
260  } else {
261  // multi-thread snapshot
262  using Helper_t = SnapshotHelperMT<ColTypes...>;
263  using Action_t = RAction<Helper_t, PrevNodeType>;
264  actionPtr.reset(new Action_t(Helper_t(nSlots, filename, dirname, treename, colNames, outputColNames, options),
265  colNames, prevNode, defines));
266  }
267  return actionPtr;
268 }
269 
270 /****** end BuildAndBook ******/
271 
272 template <typename Filter>
273 void CheckFilter(Filter &)
274 {
275  using FilterRet_t = typename RDF::CallableTraits<Filter>::ret_type;
276  static_assert(std::is_convertible<FilterRet_t, bool>::value,
277  "filter expression returns a type that is not convertible to bool");
278 }
279 
280 void CheckDefine(std::string_view definedCol, TTree *treePtr, const ColumnNames_t &customCols,
281  const std::map<std::string, std::string> &aliasMap, const ColumnNames_t &dataSourceColumns);
282 
283 std::string PrettyPrintAddr(const void *const addr);
284 
285 void BookFilterJit(const std::shared_ptr<RJittedFilter> &jittedFilter, std::shared_ptr<RNodeBase> *prevNodeOnHeap,
287  const std::map<std::string, std::string> &aliasMap, const ColumnNames_t &branches,
288  const RDFInternal::RBookedDefines &customCols, TTree *tree, RDataSource *ds);
289 
290 std::shared_ptr<RJittedDefine> BookDefineJit(std::string_view name, std::string_view expression, RLoopManager &lm,
291  RDataSource *ds, const RDFInternal::RBookedDefines &customCols,
292  const ColumnNames_t &branches,
293  std::shared_ptr<RNodeBase> *prevNodeOnHeap);
294 
295 std::string JitBuildAction(const ColumnNames_t &bl, std::shared_ptr<RDFDetail::RNodeBase> *prevNode,
296  const std::type_info &art, const std::type_info &at, void *rOnHeap, TTree *tree,
297  const unsigned int nSlots, const RDFInternal::RBookedDefines &defines,
298  RDataSource *ds, std::weak_ptr<RJittedAction> *jittedActionOnHeap);
299 
300 // Allocate a weak_ptr on the heap, return a pointer to it. The user is responsible for deleting this weak_ptr.
301 // This function is meant to be used by RInterface's methods that book code for jitting.
302 // The problem it solves is that we generate code to be lazily jitted with the addresses of certain objects in them,
303 // and we need to check those objects are still alive when the generated code is finally jitted and executed.
304 // So we pass addresses to weak_ptrs allocated on the heap to the jitted code, which is then responsible for
305 // the deletion of the weak_ptr object.
306 template <typename T>
307 std::weak_ptr<T> *MakeWeakOnHeap(const std::shared_ptr<T> &shPtr)
308 {
309  return new std::weak_ptr<T>(shPtr);
310 }
311 
312 // Same as MakeWeakOnHeap, but create a shared_ptr that makes sure the object is definitely kept alive.
313 template <typename T>
314 std::shared_ptr<T> *MakeSharedOnHeap(const std::shared_ptr<T> &shPtr)
315 {
316  return new std::shared_ptr<T>(shPtr);
317 }
318 
319 bool AtLeastOneEmptyString(const std::vector<std::string_view> strings);
320 
321 /// Take a shared_ptr<AnyNodeType> and return a shared_ptr<RNodeBase>.
322 /// This works for RLoopManager nodes as well as filters and ranges.
323 std::shared_ptr<RNodeBase> UpcastNode(std::shared_ptr<RNodeBase> ptr);
324 
325 ColumnNames_t GetValidatedColumnNames(RLoopManager &lm, const unsigned int nColumns, const ColumnNames_t &columns,
326  const ColumnNames_t &validDefines, RDataSource *ds);
327 
328 std::vector<std::string> GetValidatedArgTypes(const ColumnNames_t &colNames, const RBookedDefines &defines,
329  TTree *tree, RDataSource *ds, const std::string &context,
330  bool vector2rvec);
331 
332 std::vector<bool> FindUndefinedDSColumns(const ColumnNames_t &requestedCols, const ColumnNames_t &definedDSCols);
333 
335 
336 template <typename T>
337 void AddDSColumnsHelper(const std::string &colName, RLoopManager &lm, RDataSource &ds)
338 {
339  if (!ds.HasColumn(colName) || lm.HasDSValuePtrs(colName))
340  return;
341 
342  const auto valuePtrs = ds.GetColumnReaders<T>(colName);
343  if (!valuePtrs.empty()) {
344  // we are using the old GetColumnReaders mechanism
345  std::vector<void*> typeErasedValuePtrs(valuePtrs.begin(), valuePtrs.end());
346  lm.AddDSValuePtrs(colName, std::move(typeErasedValuePtrs));
347  }
348 }
349 
350 /// Take list of column names that must be defined, current map of custom columns, current list of defined column names,
351 /// and return a new map of custom columns (with the new datasource columns added to it)
352 template <typename... ColumnTypes>
353 void AddDSColumns(const std::vector<std::string> &requiredCols, RLoopManager &lm, RDataSource &ds,
355 {
356  // hack to expand a template parameter pack without c++17 fold expressions.
357  using expander = int[];
358  int i = 0;
359  (void)expander{(AddDSColumnsHelper<ColumnTypes>(requiredCols[i], lm, ds), ++i)..., 0};
360 }
361 
362 // this function is meant to be called by the jitted code generated by BookFilterJit
363 template <typename F, typename PrevNode>
364 void JitFilterHelper(F &&f, const ColumnNames_t &cols, std::string_view name,
365  std::weak_ptr<RJittedFilter> *wkJittedFilter, std::shared_ptr<PrevNode> *prevNodeOnHeap,
367 {
368  if (wkJittedFilter->expired()) {
369  // The branch of the computation graph that needed this jitted code went out of scope between the type
370  // jitting was booked and the time jitting actually happened. Nothing to do other than cleaning up.
371  delete wkJittedFilter;
372  // defines must be deleted before prevNodeOnHeap because their dtor needs the RLoopManager to be alive
373  // and prevNodeOnHeap is what keeps it alive if the rest of the computation graph is already out of scope
374  delete defines;
375  delete prevNodeOnHeap;
376  return;
377  }
378 
379  const auto jittedFilter = wkJittedFilter->lock();
380 
381  // mock Filter logic -- validity checks and Define-ition of RDataSource columns
382  using Callable_t = typename std::decay<F>::type;
383  using F_t = RFilter<Callable_t, PrevNode>;
384  using ColTypes_t = typename TTraits::CallableTraits<Callable_t>::arg_types;
385  constexpr auto nColumns = ColTypes_t::list_size;
386  RDFInternal::CheckFilter(f);
387 
388  auto &lm = *jittedFilter->GetLoopManagerUnchecked(); // RLoopManager must exist at this time
389  auto ds = lm.GetDataSource();
390 
391  if (ds != nullptr)
392  RDFInternal::AddDSColumns(cols, lm, *ds, ColTypes_t());
393 
394  jittedFilter->SetFilter(
395  std::unique_ptr<RFilterBase>(new F_t(std::forward<F>(f), cols, *prevNodeOnHeap, *defines, name)));
396  // defines points to the columns structure in the heap, created before the jitted call so that the jitter can
397  // share data after it has lazily compiled the code. Here the data has been used and the memory can be freed.
398  delete defines;
399  delete prevNodeOnHeap;
400  delete wkJittedFilter;
401 }
402 
403 template <typename F>
404 void JitDefineHelper(F &&f, const ColumnNames_t &cols, std::string_view name, RLoopManager *lm,
405  std::weak_ptr<RJittedDefine> *wkJittedDefine,
406  RDFInternal::RBookedDefines *defines, std::shared_ptr<RNodeBase> *prevNodeOnHeap)
407 {
408  if (wkJittedDefine->expired()) {
409  // The branch of the computation graph that needed this jitted code went out of scope between the type
410  // jitting was booked and the time jitting actually happened. Nothing to do other than cleaning up.
411  delete wkJittedDefine;
412  // defines must be deleted before prevNodeOnHeap because their dtor needs the RLoopManager to be alive
413  // and prevNodeOnHeap is what keeps it alive if the rest of the computation graph is already out of scope
414  delete defines;
415  delete prevNodeOnHeap;
416  return;
417  }
418 
419  auto jittedDefine = wkJittedDefine->lock();
420 
421  using Callable_t = typename std::decay<F>::type;
423  using ColTypes_t = typename TTraits::CallableTraits<Callable_t>::arg_types;
424  constexpr auto nColumns = ColTypes_t::list_size;
425 
426  auto ds = lm->GetDataSource();
427  if (ds != nullptr)
428  RDFInternal::AddDSColumns(cols, *lm, *ds, ColTypes_t());
429 
430  // will never actually be used (trumped by jittedDefine->GetTypeName()), but we set it to something meaningful
431  // to help devs debugging
432  const auto dummyType = "jittedCol_t";
433  // use unique_ptr<RDefineBase> instead of make_unique<NewCol_t> to reduce jit/compile-times
434  jittedDefine->SetDefine(std::unique_ptr<RDefineBase>(
435  new NewCol_t(name, dummyType, std::forward<F>(f), cols, lm->GetNSlots(), *defines, lm->GetDSValuePtrs(), ds)));
436 
437  // defines points to the columns structure in the heap, created before the jitted call so that the jitter can
438  // share data after it has lazily compiled the code. Here the data has been used and the memory can be freed.
439  delete defines;
440  // prevNodeOnHeap only serves the purpose of keeping the RLoopManager alive so it can be accessed by
441  // defines' destructor in case the rest of the computation graph is gone. Can be safely deleted here.
442  delete prevNodeOnHeap;
443  delete wkJittedDefine;
444 }
445 
446 /// Convenience function invoked by jitted code to build action nodes at runtime
447 template <typename ActionTag, typename... ColTypes, typename PrevNodeType, typename HelperArgType>
448 void CallBuildAction(std::shared_ptr<PrevNodeType> *prevNodeOnHeap, const ColumnNames_t &cols,
449  const unsigned int nSlots, std::weak_ptr<HelperArgType> *wkHelperArgOnHeap,
450  std::weak_ptr<RJittedAction> *wkJittedActionOnHeap,
452 {
453  if (wkHelperArgOnHeap->expired()) {
454  delete wkHelperArgOnHeap;
455  delete wkJittedActionOnHeap;
456  // defines must be deleted before prevNodeOnHeap because their dtor needs the RLoopManager to be alive
457  // and prevNodeOnHeap is what keeps it alive if the rest of the computation graph is already out of scope
458  delete defines;
459  delete prevNodeOnHeap;
460  return;
461  }
462 
463  const auto helperArgOnHeap = wkHelperArgOnHeap->lock();
464  auto jittedActionOnHeap = wkJittedActionOnHeap->lock();
465 
466  // if we are here it means we are jitting, if we are jitting the loop manager must be alive
467  auto &prevNodePtr = *prevNodeOnHeap;
468  auto &loopManager = *prevNodePtr->GetLoopManagerUnchecked();
469  using ColTypes_t = TypeList<ColTypes...>;
470  constexpr auto nColumns = ColTypes_t::list_size;
471  auto ds = loopManager.GetDataSource();
472  if (ds != nullptr)
473  RDFInternal::AddDSColumns(cols, loopManager, *ds, ColTypes_t());
474 
475  auto actionPtr =
476  BuildAction<ColTypes...>(cols, std::move(helperArgOnHeap), nSlots, std::move(prevNodePtr), ActionTag{}, *defines);
477  jittedActionOnHeap->SetAction(std::move(actionPtr));
478 
479  // defines points to the columns structure in the heap, created before the jitted call so that the jitter can
480  // share data after it has lazily compiled the code. Here the data has been used and the memory can be freed.
481  delete defines;
482 
483  delete wkHelperArgOnHeap;
484  delete prevNodeOnHeap;
485  delete wkJittedActionOnHeap;
486 }
487 
488 /// The contained `type` alias is `double` if `T == RInferredType`, `U` if `T == std::container<U>`, `T` otherwise.
489 template <typename T, bool Container = RDFInternal::IsDataContainer<T>::value && !std::is_same<T, std::string>::value>
490 struct RMinReturnType {
491  using type = T;
492 };
493 
494 template <>
495 struct RMinReturnType<RInferredType, false> {
496  using type = double;
497 };
498 
499 template <typename T>
500 struct RMinReturnType<T, true> {
501  using type = TTraits::TakeFirstParameter_t<T>;
502 };
503 
504 // return wrapper around f that prepends an `unsigned int slot` parameter
505 template <typename R, typename F, typename... Args>
506 std::function<R(unsigned int, Args...)> AddSlotParameter(F &f, TypeList<Args...>)
507 {
508  return [f](unsigned int, Args... a) -> R { return f(a...); };
509 }
510 
511 template <typename ColType, typename... Rest>
512 struct RNeedJittingHelper {
513  static constexpr bool value = RNeedJittingHelper<Rest...>::value;
514 };
515 
516 template <typename... Rest>
517 struct RNeedJittingHelper<RInferredType, Rest...> {
518  static constexpr bool value = true;
519 };
520 
521 template <typename T>
522 struct RNeedJittingHelper<T> {
523  static constexpr bool value = false;
524 };
525 
526 template <>
527 struct RNeedJittingHelper<RInferredType> {
528  static constexpr bool value = true;
529 };
530 
531 template <typename ...ColTypes>
532 struct RNeedJitting {
533  static constexpr bool value = RNeedJittingHelper<ColTypes...>::value;
534 };
535 
536 template <>
537 struct RNeedJitting<> {
538  static constexpr bool value = false;
539 };
540 
541 ///////////////////////////////////////////////////////////////////////////////
542 /// Check preconditions for RInterface::Aggregate:
543 /// - the aggregator callable must have signature `U(U,T)` or `void(U&,T)`.
544 /// - the merge callable must have signature `U(U,U)` or `void(std::vector<U>&)`
546  typename mergeArgsNoDecay_t = typename CallableTraits<Merge>::arg_types_nodecay,
547  typename mergeArgs_t = typename CallableTraits<Merge>::arg_types,
548  typename mergeRet_t = typename CallableTraits<Merge>::ret_type>
549 void CheckAggregate(TypeList<U, T>)
550 {
551  constexpr bool isAggregatorOk =
552  (std::is_same<R, decayedU>::value) || (std::is_same<R, void>::value && std::is_lvalue_reference<U>::value);
553  static_assert(isAggregatorOk, "aggregator function must have signature `U(U,T)` or `void(U&,T)`");
554  constexpr bool isMergeOk =
555  (std::is_same<TypeList<decayedU, decayedU>, mergeArgs_t>::value && std::is_same<decayedU, mergeRet_t>::value) ||
556  (std::is_same<TypeList<std::vector<decayedU> &>, mergeArgsNoDecay_t>::value &&
557  std::is_same<void, mergeRet_t>::value);
558  static_assert(isMergeOk, "merge function must have signature `U(U,U)` or `void(std::vector<U>&)`");
559 }
560 
561 ///////////////////////////////////////////////////////////////////////////////
562 /// This overload of CheckAggregate is called when the aggregator takes more than two arguments
563 template <typename R, typename T>
564 void CheckAggregate(T)
565 {
566  static_assert(sizeof(T) == 0, "aggregator function must take exactly two arguments");
567 }
568 
569 ///////////////////////////////////////////////////////////////////////////////
570 /// Check as many template parameters were passed as the number of column names, throw if this is not the case.
571 void CheckTypesAndPars(unsigned int nTemplateParams, unsigned int nColumnNames);
572 
573 /// Return local BranchNames or default BranchNames according to which one should be used
574 const ColumnNames_t SelectColumns(unsigned int nArgs, const ColumnNames_t &bl, const ColumnNames_t &defBl);
575 
576 /// Check whether column names refer to a valid branch of a TTree or have been `Define`d. Return invalid column names.
577 ColumnNames_t FindUnknownColumns(const ColumnNames_t &requiredCols, const ColumnNames_t &datasetColumns,
578  const ColumnNames_t &definedCols, const ColumnNames_t &dataSourceColumns);
579 
580 /// Returns the list of Filters defined in the whole graph
581 std::vector<std::string> GetFilterNames(const std::shared_ptr<RLoopManager> &loopManager);
582 
583 /// Returns the list of Filters defined in the branch
584 template <typename NodeType>
585 std::vector<std::string> GetFilterNames(const std::shared_ptr<NodeType> &node)
586 {
587  std::vector<std::string> filterNames;
588  node->AddFilterName(filterNames);
589  return filterNames;
590 }
591 
592 struct ParsedTreePath {
593  std::string fTreeName;
594  std::string fDirName;
595 };
596 
597 ParsedTreePath ParseTreePath(std::string_view fullTreeName);
598 
599 // Check if a condition is true for all types
600 template <bool...>
601 struct TBoolPack;
602 
603 template <bool... bs>
604 using IsTrueForAllImpl_t = typename std::is_same<TBoolPack<bs..., true>, TBoolPack<true, bs...>>;
605 
606 template <bool... Conditions>
607 struct TEvalAnd {
608  static constexpr bool value = IsTrueForAllImpl_t<Conditions...>::value;
609 };
610 
611 // Check if a class is a specialisation of stl containers templates
612 // clang-format off
613 
614 template <typename>
615 struct IsList_t : std::false_type {};
616 
617 template <typename T>
618 struct IsList_t<std::list<T>> : std::true_type {};
619 
620 template <typename>
621 struct IsDeque_t : std::false_type {};
622 
623 template <typename T>
624 struct IsDeque_t<std::deque<T>> : std::true_type {};
625 // clang-format on
626 
627 } // namespace RDF
628 } // namespace Internal
629 
630 namespace Detail {
631 namespace RDF {
632 
633 /// The aliased type is `double` if `T == RInferredType`, `U` if `T == container<U>`, `T` otherwise.
634 template <typename T>
635 using MinReturnType_t = typename RDFInternal::RMinReturnType<T>::type;
636 
637 template <typename T>
638 using MaxReturnType_t = MinReturnType_t<T>;
639 
640 template <typename T>
641 using SumReturnType_t = MinReturnType_t<T>;
642 
643 } // namespace RDF
644 } // namespace Detail
645 } // namespace ROOT
646 
647 /// \endcond
648 
649 #endif
TMath::Mean
Double_t Mean(Long64_t n, const T *a, const Double_t *w=0)
Return the weighted mean of an array a with length n.
Definition: TMath.h:1073
ROOT::TypeTraits
ROOT type_traits extensions.
Definition: TypeTraits.hxx:21
ROOT::Internal::RDF::FindUnknownColumns
ColumnNames_t FindUnknownColumns(const ColumnNames_t &requiredCols, const ColumnNames_t &datasetColumns, const ColumnNames_t &definedCols, const ColumnNames_t &dataSourceColumns)
Definition: RDFInterfaceUtils.cxx:498
TObjArray
An array of TObjects.
Definition: TObjArray.h:37
RJittedFilter.hxx
ROOT::Internal::RDF::ConvertRegexToColumns
ColumnNames_t ConvertRegexToColumns(const ColumnNames_t &colNames, std::string_view columnNameRegexp, std::string_view callerName)
Definition: RDFInterfaceUtils.cxx:383
f
#define f(i)
Definition: RSha256.hxx:104
ROOT::Internal::RDF::ParseTreePath
ParsedTreePath ParseTreePath(std::string_view fullTreeName)
Definition: RDFInterfaceUtils.cxx:523
TMath::Max
Short_t Max(Short_t a, Short_t b)
Definition: TMathBase.h:212
ROOT::Internal::RDF::FindUndefinedDSColumns
std::vector< bool > FindUndefinedDSColumns(const ColumnNames_t &requestedCols, const ColumnNames_t &definedCols)
Return a bitset each element of which indicates whether the corresponding element in selectedColumns ...
Definition: RDFInterfaceUtils.cxx:762
ROOT::Internal::RDF::CheckTypesAndPars
void CheckTypesAndPars(unsigned int nTemplateParams, unsigned int nColumnNames)
Definition: RDFInterfaceUtils.cxx:459
TMath::StdDev
Double_t StdDev(Long64_t n, const T *a, const Double_t *w=0)
Definition: TMath.h:530
F
#define F(x, y, z)
ROOT::Internal::RDF::BookFilterJit
void BookFilterJit(const std::shared_ptr< RJittedFilter > &jittedFilter, std::shared_ptr< RDFDetail::RNodeBase > *prevNodeOnHeap, std::string_view name, std::string_view expression, const std::map< std::string, std::string > &aliasMap, const ColumnNames_t &branches, const RDFInternal::RBookedDefines &customCols, TTree *tree, RDataSource *ds)
Definition: RDFInterfaceUtils.cxx:544
tree
Definition: tree.py:1
RBookedDefines.hxx
ROOT::Detail::RDF::RLoopManager::GetLoopManagerUnchecked
RLoopManager * GetLoopManagerUnchecked() final
Definition: RLoopManager.hxx:147
string_view
basic_string_view< char > string_view
Definition: libcpp_string_view.h:785
TTree
A TTree represents a columnar dataset.
Definition: TTree.h:79
extract_docstrings.ds
ds
Definition: extract_docstrings.py:40
ROOT::TypeTraits::TypeList
Lightweight storage for a collection of types.
Definition: TypeTraits.hxx:25
Utils.hxx
RJittedAction.hxx
ROOT::Internal::RDF::RBookedDefines
Encapsulates the columns defined by the user.
Definition: RBookedDefines.hxx:39
TH1::kAllAxes
@ kAllAxes
Definition: TH1.h:75
ROOT::RDF::RSnapshotOptions
A collection of options to steer the creation of the dataset on file.
Definition: RSnapshotOptions.hxx:22
ActionHelpers.hxx
ROOT::Detail::RDF::RLoopManager::GetDataSource
RDataSource * GetDataSource() const
Definition: RLoopManager.hxx:153
ROOT::Detail::RDF::RLoopManager::AddDSValuePtrs
void AddDSValuePtrs(const std::string &col, const std::vector< void * > ptrs)
Definition: RLoopManager.cxx:828
ROOT::VecOps::Filter
RVec< T > Filter(const RVec< T > &v, F &&f)
Create a new collection with the elements passing the filter expressed by the predicate.
Definition: RVec.hxx:938
ROOT::Detail::RDF
Definition: GraphUtils.hxx:28
ROOT::Detail::RDF::ColumnNames_t
std::vector< std::string > ColumnNames_t
Definition: RLoopManager.hxx:53
ROOT::RDF::RDataSource
RDataSource defines an API that RDataFrame can use to read arbitrary data formats.
Definition: RDataSource.hxx:106
ROOT::Detail::RDF::RLoopManager::GetDSValuePtrs
const std::map< std::string, std::vector< void * > > & GetDSValuePtrs() const
Definition: RLoopManager.hxx:174
TROOT.h
ROOT::Internal::RDF::CheckDefine
void CheckDefine(std::string_view definedCol, TTree *treePtr, const ColumnNames_t &customCols, const std::map< std::string, std::string > &aliasMap, const ColumnNames_t &dataSourceColumns)
Definition: RDFInterfaceUtils.cxx:418
R
#define R(a, b, c, d, e, f, g, h, i)
Definition: RSha256.hxx:110
RIntegerSequence.hxx
ROOT::Internal::RDF::GetTopLevelBranchNames
ColumnNames_t GetTopLevelBranchNames(TTree &t)
Get all the top-level branches names, including the ones of the friend trees.
Definition: RDFInterfaceUtils.cxx:360
RJittedDefine.hxx
ROOT::Internal::RDF::BookDefineJit
std::shared_ptr< RJittedDefine > BookDefineJit(std::string_view name, std::string_view expression, RLoopManager &lm, RDataSource *ds, const RDFInternal::RBookedDefines &customCols, const ColumnNames_t &branches, std::shared_ptr< RNodeBase > *upcastNodeOnHeap)
Definition: RDFInterfaceUtils.cxx:590
h
#define h(i)
Definition: RSha256.hxx:106
ROOT::Internal::RDF::JitBuildAction
std::string JitBuildAction(const ColumnNames_t &bl, std::shared_ptr< RDFDetail::RNodeBase > *prevNode, const std::type_info &helperArgType, const std::type_info &at, void *helperArgOnHeap, TTree *tree, const unsigned int nSlots, const RDFInternal::RBookedDefines &customCols, RDataSource *ds, std::weak_ptr< RJittedAction > *jittedActionOnHeap)
Definition: RDFInterfaceUtils.cxx:634
ROOT::Internal::RDF::DemangleTypeIdName
std::string DemangleTypeIdName(const std::type_info &typeInfo)
Definition: RDFInterfaceUtils.cxx:373
a
auto * a
Definition: textangle.C:12
RStringView.hxx
ROOT::Internal::RDF::PrettyPrintAddr
std::string PrettyPrintAddr(const void *const addr)
Definition: RDFInterfaceUtils.cxx:536
ROOT::R::function
void function(const Char_t *name_, T fun, const Char_t *docstring=0)
Definition: RExports.h:151
TypeTraits.hxx
double
double
Definition: Converters.cxx:921
void
typedef void((*Func_t)())
ROOT::RDF::RInterface
The public interface to the RDataFrame federation of classes.
Definition: RInterface.hxx:90
TMath::Min
Short_t Min(Short_t a, Short_t b)
Definition: TMathBase.h:180
ROOT::RDF
Definition: RArrowDS.hxx:20
RAction.hxx
ROOT::IsImplicitMTEnabled
Bool_t IsImplicitMTEnabled()
Returns true if the implicit multi-threading in ROOT is enabled.
Definition: TROOT.cxx:556
ROOT::Internal::RDF::GetValidatedColumnNames
ColumnNames_t GetValidatedColumnNames(RLoopManager &lm, const unsigned int nColumns, const ColumnNames_t &columns, const ColumnNames_t &validDefines, RDataSource *ds)
Given the desired number of columns and the user-provided list of columns:
Definition: RDFInterfaceUtils.cxx:703
gErrorIgnoreLevel
R__EXTERN Int_t gErrorIgnoreLevel
Definition: TError.h:129
ROOT::Detail::RDF::RDefine
Definition: RDefine.hxx:45
ROOT::Internal::RDF::GetValidatedArgTypes
std::vector< std::string > GetValidatedArgTypes(const ColumnNames_t &colNames, const RBookedDefines &defines, TTree *tree, RDataSource *ds, const std::string &context, bool vector2rvec)
Definition: RDFInterfaceUtils.cxx:738
ROOT::Detail::RDF::RFilter
Definition: RFilter.hxx:53
ROOT::Internal::RDF::SelectColumns
const ColumnNames_t SelectColumns(unsigned int nRequiredNames, const ColumnNames_t &names, const ColumnNames_t &defaultNames)
Choose between local column names or default column names, throw in case of errors.
Definition: RDFInterfaceUtils.cxx:473
ROOT::Internal::RDF
Definition: RArrowDS.hxx:15
ROOT::VecOps::Sum
T Sum(const RVec< T > &v)
Sum elements of an RVec.
Definition: RVec.hxx:758
name
char name[80]
Definition: TGX11.cxx:110
ROOT::Math::Chebyshev::T
double T(double x)
Definition: ChebyshevPol.h:34
d
#define d(i)
Definition: RSha256.hxx:102
ROOT::Internal::RDF::UpcastNode
std::shared_ptr< RNodeBase > UpcastNode(std::shared_ptr< RNodeBase > ptr)
Definition: RDFInterfaceUtils.cxx:693
ROOT::Internal::RDF::GetFilterNames
std::vector< std::string > GetFilterNames(const std::shared_ptr< RLoopManager > &loopManager)
Definition: RDFInterfaceUtils.cxx:518
ROOT::Internal::RDF::AtLeastOneEmptyString
bool AtLeastOneEmptyString(const std::vector< std::string_view > strings)
Definition: RDFInterfaceUtils.cxx:684
RMakeUnique.hxx
RLoopManager.hxx
type
int type
Definition: TGX11.cxx:121
RFilter.hxx
ROOT::Detail::RDF::RLoopManager::GetNSlots
unsigned int GetNSlots() const
Definition: RLoopManager.hxx:161
TH1.h
ROOT
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
Definition: EExecutionPolicy.hxx:4
RDefine.hxx
ROOT::Detail::RDF::RLoopManager
The head node of a RDF computation graph.
Definition: RLoopManager.hxx:57
int
ROOT::Detail::RDF::RLoopManager::HasDSValuePtrs
bool HasDSValuePtrs(const std::string &col) const
Definition: RLoopManager.cxx:823
TError.h
g
#define g(i)
Definition: RSha256.hxx:105