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 
31 #include <deque>
32 #include <functional>
33 #include <map>
34 #include <memory>
35 #include <string>
36 #include <type_traits>
37 #include <typeinfo>
38 #include <vector>
39 #include <unordered_map>
40 
41 class TObjArray;
42 class TTree;
43 namespace ROOT {
44 namespace Detail {
45 namespace RDF {
46 class RNodeBase;
47 }
48 }
49 namespace RDF {
50 template <typename T>
51 class RResultPtr;
52 template<typename T, typename V>
53 class RInterface;
55 class RDataSource;
56 } // namespace RDF
57 
58 } // namespace ROOT
59 
60 /// \cond HIDDEN_SYMBOLS
61 
62 namespace ROOT {
63 namespace Internal {
64 namespace RDF {
65 using namespace ROOT::Detail::RDF;
66 using namespace ROOT::RDF;
67 namespace TTraits = ROOT::TypeTraits;
69 
71 
73 HeadNode_t CreateSnapshotRDF(const ColumnNames_t &validCols,
74  std::string_view treeName,
75  std::string_view fileName,
76  bool isLazy,
77  RLoopManager &loopManager,
78  std::unique_ptr<RDFInternal::RActionBase> actionPtr);
79 
80 std::string DemangleTypeIdName(const std::type_info &typeInfo);
81 
83 ConvertRegexToColumns(const ColumnNames_t &colNames, std::string_view columnNameRegexp, std::string_view callerName);
84 
85 /// An helper object that sets and resets gErrorIgnoreLevel via RAII.
86 class RIgnoreErrorLevelRAII {
87 private:
88  int fCurIgnoreErrorLevel = gErrorIgnoreLevel;
89 
90 public:
91  RIgnoreErrorLevelRAII(int errorIgnoreLevel) { gErrorIgnoreLevel = errorIgnoreLevel; }
92  RIgnoreErrorLevelRAII() { gErrorIgnoreLevel = fCurIgnoreErrorLevel; }
93 };
94 
95 /****** BuildAction overloads *******/
96 
97 // clang-format off
98 /// This namespace defines types to be used for tag dispatching in RInterface.
99 namespace ActionTags {
100 struct Histo1D{};
101 struct Histo2D{};
102 struct Histo3D{};
103 struct Graph{};
104 struct Profile1D{};
105 struct Profile2D{};
106 struct Min{};
107 struct Max{};
108 struct Sum{};
109 struct Mean{};
110 struct Fill{};
111 struct StdDev{};
112 struct Display{};
113 }
114 // clang-format on
115 
116 template <typename T, bool ISV6HISTO = std::is_base_of<TH1, T>::value>
117 struct HistoUtils {
118  static void SetCanExtendAllAxes(T &h) { h.SetCanExtend(::TH1::kAllAxes); }
119  static bool HasAxisLimits(T &h)
120  {
121  auto xaxis = h.GetXaxis();
122  return !(xaxis->GetXmin() == 0. && xaxis->GetXmax() == 0.);
123  }
124 };
125 
126 template <typename T>
127 struct HistoUtils<T, false> {
128  static void SetCanExtendAllAxes(T &) {}
129  static bool HasAxisLimits(T &) { return true; }
130 };
131 
132 // Generic filling (covers Histo2D, Histo3D, Profile1D and Profile2D actions, with and without weights)
133 template <typename... ColTypes, typename ActionTag, typename ActionResultType, typename PrevNodeType>
134 std::unique_ptr<RActionBase>
135 BuildAction(const ColumnNames_t &bl, const std::shared_ptr<ActionResultType> &h, const unsigned int nSlots,
136  std::shared_ptr<PrevNodeType> prevNode, ActionTag, const RDFInternal::RBookedDefines &defines)
137 {
138  using Helper_t = FillParHelper<ActionResultType>;
139  using Action_t = RAction<Helper_t, PrevNodeType, TTraits::TypeList<ColTypes...>>;
140  return std::make_unique<Action_t>(Helper_t(h, nSlots), bl, std::move(prevNode), std::move(defines));
141 }
142 
143 // Histo1D filling (must handle the special case of distinguishing FillParHelper and FillHelper
144 template <typename... ColTypes, typename PrevNodeType>
145 std::unique_ptr<RActionBase> BuildAction(const ColumnNames_t &bl, const std::shared_ptr<::TH1D> &h,
146  const unsigned int nSlots, std::shared_ptr<PrevNodeType> prevNode,
147  ActionTags::Histo1D, const RDFInternal::RBookedDefines &defines)
148 {
149  auto hasAxisLimits = HistoUtils<::TH1D>::HasAxisLimits(*h);
150 
151  if (hasAxisLimits) {
152  using Helper_t = FillParHelper<::TH1D>;
153  using Action_t = RAction<Helper_t, PrevNodeType, TTraits::TypeList<ColTypes...>>;
154  return std::make_unique<Action_t>(Helper_t(h, nSlots), bl, std::move(prevNode), std::move(defines));
155  } else {
156  using Helper_t = FillHelper;
157  using Action_t = RAction<Helper_t, PrevNodeType, TTraits::TypeList<ColTypes...>>;
158  return std::make_unique<Action_t>(Helper_t(h, nSlots), bl, std::move(prevNode), std::move(defines));
159  }
160 }
161 
162 template <typename... ColTypes, typename PrevNodeType>
163 std::unique_ptr<RActionBase> BuildAction(const ColumnNames_t &bl, const std::shared_ptr<TGraph> &g,
164  const unsigned int nSlots, std::shared_ptr<PrevNodeType> prevNode,
165  ActionTags::Graph, const RDFInternal::RBookedDefines &defines)
166 {
167  using Helper_t = FillTGraphHelper;
168  using Action_t = RAction<Helper_t, PrevNodeType, TTraits::TypeList<ColTypes...>>;
169  return std::make_unique<Action_t>(Helper_t(g, nSlots), bl, std::move(prevNode), std::move(defines));
170 }
171 
172 // Min action
173 template <typename ColType, typename PrevNodeType, typename ActionResultType>
174 std::unique_ptr<RActionBase> BuildAction(const ColumnNames_t &bl, const std::shared_ptr<ActionResultType> &minV,
175  const unsigned int nSlots, std::shared_ptr<PrevNodeType> prevNode,
177 {
178  using Helper_t = MinHelper<ActionResultType>;
179  using Action_t = RAction<Helper_t, PrevNodeType, TTraits::TypeList<ColType>>;
180  return std::make_unique<Action_t>(Helper_t(minV, nSlots), bl, std::move(prevNode), std::move(defines));
181 }
182 
183 // Max action
184 template <typename ColType, typename PrevNodeType, typename ActionResultType>
185 std::unique_ptr<RActionBase> BuildAction(const ColumnNames_t &bl, const std::shared_ptr<ActionResultType> &maxV,
186  const unsigned int nSlots, std::shared_ptr<PrevNodeType> prevNode,
188 {
189  using Helper_t = MaxHelper<ActionResultType>;
190  using Action_t = RAction<Helper_t, PrevNodeType, TTraits::TypeList<ColType>>;
191  return std::make_unique<Action_t>(Helper_t(maxV, nSlots), bl, std::move(prevNode), std::move(defines));
192 }
193 
194 // Sum action
195 template <typename ColType, typename PrevNodeType, typename ActionResultType>
196 std::unique_ptr<RActionBase> BuildAction(const ColumnNames_t &bl, const std::shared_ptr<ActionResultType> &sumV,
197  const unsigned int nSlots, std::shared_ptr<PrevNodeType> prevNode,
199 {
200  using Helper_t = SumHelper<ActionResultType>;
201  using Action_t = RAction<Helper_t, PrevNodeType, TTraits::TypeList<ColType>>;
202  return std::make_unique<Action_t>(Helper_t(sumV, nSlots), bl, std::move(prevNode), std::move(defines));
203 }
204 
205 // Mean action
206 template <typename ColType, typename PrevNodeType>
207 std::unique_ptr<RActionBase> BuildAction(const ColumnNames_t &bl, const std::shared_ptr<double> &meanV,
208  const unsigned int nSlots, std::shared_ptr<PrevNodeType> prevNode,
210 {
211  using Helper_t = MeanHelper;
212  using Action_t = RAction<Helper_t, PrevNodeType, TTraits::TypeList<ColType>>;
213  return std::make_unique<Action_t>(Helper_t(meanV, nSlots), bl, std::move(prevNode), std::move(defines));
214 }
215 
216 // Standard Deviation action
217 template <typename ColType, typename PrevNodeType>
218 std::unique_ptr<RActionBase> BuildAction(const ColumnNames_t &bl, const std::shared_ptr<double> &stdDeviationV,
219  const unsigned int nSlots, std::shared_ptr<PrevNodeType> prevNode,
221 {
222  using Helper_t = StdDevHelper;
223  using Action_t = RAction<Helper_t, PrevNodeType, TTraits::TypeList<ColType>>;
224  return std::make_unique<Action_t>(Helper_t(stdDeviationV, nSlots), bl, prevNode, std::move(defines));
225 }
226 
227 // Display action
228 template <typename... ColTypes, typename PrevNodeType>
229 std::unique_ptr<RActionBase> BuildAction(const ColumnNames_t &bl, const std::shared_ptr<RDisplay> &d,
230  const unsigned int, std::shared_ptr<PrevNodeType> prevNode,
231  ActionTags::Display, const RDFInternal::RBookedDefines &defines)
232 {
233  using Helper_t = DisplayHelper<PrevNodeType>;
234  using Action_t = RAction<Helper_t, PrevNodeType, TTraits::TypeList<ColTypes...>>;
235  return std::make_unique<Action_t>(Helper_t(d, prevNode), bl, prevNode, std::move(defines));
236 }
237 
238 /****** end BuildAndBook ******/
239 
240 template <typename Filter>
241 void CheckFilter(Filter &)
242 {
243  using FilterRet_t = typename RDF::CallableTraits<Filter>::ret_type;
244  static_assert(std::is_convertible<FilterRet_t, bool>::value,
245  "filter expression returns a type that is not convertible to bool");
246 }
247 
248 void CheckDefine(std::string_view definedCol, TTree *treePtr, const ColumnNames_t &customCols,
249  const std::map<std::string, std::string> &aliasMap, const ColumnNames_t &dataSourceColumns);
250 
251 std::string PrettyPrintAddr(const void *const addr);
252 
253 void BookFilterJit(const std::shared_ptr<RJittedFilter> &jittedFilter, std::shared_ptr<RNodeBase> *prevNodeOnHeap,
255  const std::map<std::string, std::string> &aliasMap, const ColumnNames_t &branches,
256  const RDFInternal::RBookedDefines &customCols, TTree *tree, RDataSource *ds);
257 
258 std::shared_ptr<RJittedDefine> BookDefineJit(std::string_view name, std::string_view expression, RLoopManager &lm,
259  RDataSource *ds, const RDFInternal::RBookedDefines &customCols,
260  const ColumnNames_t &branches,
261  std::shared_ptr<RNodeBase> *prevNodeOnHeap);
262 
263 std::string JitBuildAction(const ColumnNames_t &bl, std::shared_ptr<RDFDetail::RNodeBase> *prevNode,
264  const std::type_info &art, const std::type_info &at, void *rOnHeap, TTree *tree,
265  const unsigned int nSlots, const RDFInternal::RBookedDefines &defines,
266  RDataSource *ds, std::weak_ptr<RJittedAction> *jittedActionOnHeap);
267 
268 // Allocate a weak_ptr on the heap, return a pointer to it. The user is responsible for deleting this weak_ptr.
269 // This function is meant to be used by RInterface's methods that book code for jitting.
270 // The problem it solves is that we generate code to be lazily jitted with the addresses of certain objects in them,
271 // and we need to check those objects are still alive when the generated code is finally jitted and executed.
272 // So we pass addresses to weak_ptrs allocated on the heap to the jitted code, which is then responsible for
273 // the deletion of the weak_ptr object.
274 template <typename T>
275 std::weak_ptr<T> *MakeWeakOnHeap(const std::shared_ptr<T> &shPtr)
276 {
277  return new std::weak_ptr<T>(shPtr);
278 }
279 
280 // Same as MakeWeakOnHeap, but create a shared_ptr that makes sure the object is definitely kept alive.
281 template <typename T>
282 std::shared_ptr<T> *MakeSharedOnHeap(const std::shared_ptr<T> &shPtr)
283 {
284  return new std::shared_ptr<T>(shPtr);
285 }
286 
287 bool AtLeastOneEmptyString(const std::vector<std::string_view> strings);
288 
289 /// Take a shared_ptr<AnyNodeType> and return a shared_ptr<RNodeBase>.
290 /// This works for RLoopManager nodes as well as filters and ranges.
291 std::shared_ptr<RNodeBase> UpcastNode(std::shared_ptr<RNodeBase> ptr);
292 
293 ColumnNames_t GetValidatedColumnNames(RLoopManager &lm, const unsigned int nColumns, const ColumnNames_t &columns,
294  const ColumnNames_t &validDefines, RDataSource *ds);
295 
296 std::vector<std::string> GetValidatedArgTypes(const ColumnNames_t &colNames, const RBookedDefines &defines,
297  TTree *tree, RDataSource *ds, const std::string &context,
298  bool vector2rvec);
299 
300 std::vector<bool> FindUndefinedDSColumns(const ColumnNames_t &requestedCols, const ColumnNames_t &definedDSCols);
301 
303 
304 template <typename T>
305 void AddDSColumnsHelper(const std::string &colName, RLoopManager &lm, RDataSource &ds)
306 {
307  if (!ds.HasColumn(colName) || lm.HasDSValuePtrs(colName))
308  return;
309 
310  const auto valuePtrs = ds.GetColumnReaders<T>(colName);
311  std::vector<void*> typeErasedValuePtrs(valuePtrs.begin(), valuePtrs.end());
312  lm.AddDSValuePtrs(colName, std::move(typeErasedValuePtrs));
313 }
314 
315 /// Take list of column names that must be defined, current map of custom columns, current list of defined column names,
316 /// and return a new map of custom columns (with the new datasource columns added to it)
317 template <typename... ColumnTypes>
318 void AddDSColumns(const std::vector<std::string> &requiredCols, RLoopManager &lm, RDataSource &ds,
320 {
321  // hack to expand a template parameter pack without c++17 fold expressions.
322  using expander = int[];
323  int i = 0;
324  (void)expander{(AddDSColumnsHelper<ColumnTypes>(requiredCols[i], lm, ds), ++i)..., 0};
325 }
326 
327 // this function is meant to be called by the jitted code generated by BookFilterJit
328 template <typename F, typename PrevNode>
329 void JitFilterHelper(F &&f, const ColumnNames_t &cols, std::string_view name,
330  std::weak_ptr<RJittedFilter> *wkJittedFilter, std::shared_ptr<PrevNode> *prevNodeOnHeap,
332 {
333  if (wkJittedFilter->expired()) {
334  // The branch of the computation graph that needed this jitted code went out of scope between the type
335  // jitting was booked and the time jitting actually happened. Nothing to do other than cleaning up.
336  delete wkJittedFilter;
337  // defines must be deleted before prevNodeOnHeap because their dtor needs the RLoopManager to be alive
338  // and prevNodeOnHeap is what keeps it alive if the rest of the computation graph is already out of scope
339  delete defines;
340  delete prevNodeOnHeap;
341  return;
342  }
343 
344  const auto jittedFilter = wkJittedFilter->lock();
345 
346  // mock Filter logic -- validity checks and Define-ition of RDataSource columns
347  using Callable_t = typename std::decay<F>::type;
348  using F_t = RFilter<Callable_t, PrevNode>;
349  using ColTypes_t = typename TTraits::CallableTraits<Callable_t>::arg_types;
350  constexpr auto nColumns = ColTypes_t::list_size;
351  RDFInternal::CheckFilter(f);
352 
353  auto &lm = *jittedFilter->GetLoopManagerUnchecked(); // RLoopManager must exist at this time
354  auto ds = lm.GetDataSource();
355 
356  if (ds != nullptr)
357  RDFInternal::AddDSColumns(cols, lm, *ds, ColTypes_t());
358 
359  jittedFilter->SetFilter(
360  std::unique_ptr<RFilterBase>(new F_t(std::forward<F>(f), cols, *prevNodeOnHeap, *defines, name)));
361  // defines points to the columns structure in the heap, created before the jitted call so that the jitter can
362  // share data after it has lazily compiled the code. Here the data has been used and the memory can be freed.
363  delete defines;
364  delete prevNodeOnHeap;
365  delete wkJittedFilter;
366 }
367 
368 template <typename F>
369 void JitDefineHelper(F &&f, const ColumnNames_t &cols, std::string_view name, RLoopManager *lm,
370  std::weak_ptr<RJittedDefine> *wkJittedDefine,
371  RDFInternal::RBookedDefines *defines, std::shared_ptr<RNodeBase> *prevNodeOnHeap)
372 {
373  if (wkJittedDefine->expired()) {
374  // The branch of the computation graph that needed this jitted code went out of scope between the type
375  // jitting was booked and the time jitting actually happened. Nothing to do other than cleaning up.
376  delete wkJittedDefine;
377  // defines must be deleted before prevNodeOnHeap because their dtor needs the RLoopManager to be alive
378  // and prevNodeOnHeap is what keeps it alive if the rest of the computation graph is already out of scope
379  delete defines;
380  delete prevNodeOnHeap;
381  return;
382  }
383 
384  auto jittedDefine = wkJittedDefine->lock();
385 
386  using Callable_t = typename std::decay<F>::type;
388  using ColTypes_t = typename TTraits::CallableTraits<Callable_t>::arg_types;
389  constexpr auto nColumns = ColTypes_t::list_size;
390 
391  auto ds = lm->GetDataSource();
392  if (ds != nullptr)
393  RDFInternal::AddDSColumns(cols, *lm, *ds, ColTypes_t());
394 
395  // will never actually be used (trumped by jittedDefine->GetTypeName()), but we set it to something meaningful
396  // to help devs debugging
397  const auto dummyType = "jittedCol_t";
398  // use unique_ptr<RDefineBase> instead of make_unique<NewCol_t> to reduce jit/compile-times
399  jittedDefine->SetDefine(std::unique_ptr<RDefineBase>(
400  new NewCol_t(name, dummyType, std::forward<F>(f), cols, lm->GetNSlots(), *defines, lm->GetDSValuePtrs())));
401 
402  // defines points to the columns structure in the heap, created before the jitted call so that the jitter can
403  // share data after it has lazily compiled the code. Here the data has been used and the memory can be freed.
404  delete defines;
405  // prevNodeOnHeap only serves the purpose of keeping the RLoopManager alive so it can be accessed by
406  // defines' destructor in case the rest of the computation graph is gone. Can be safely deleted here.
407  delete prevNodeOnHeap;
408  delete wkJittedDefine;
409 }
410 
411 /// Convenience function invoked by jitted code to build action nodes at runtime
412 template <typename ActionTag, typename... ColTypes, typename PrevNodeType, typename ActionResultType>
413 void CallBuildAction(std::shared_ptr<PrevNodeType> *prevNodeOnHeap, const ColumnNames_t &cols,
414  const unsigned int nSlots, std::weak_ptr<ActionResultType> *wkROnHeap,
415  std::weak_ptr<RJittedAction> *wkJittedActionOnHeap,
417 {
418  if (wkROnHeap->expired()) {
419  delete wkROnHeap;
420  delete wkJittedActionOnHeap;
421  // defines must be deleted before prevNodeOnHeap because their dtor needs the RLoopManager to be alive
422  // and prevNodeOnHeap is what keeps it alive if the rest of the computation graph is already out of scope
423  delete defines;
424  delete prevNodeOnHeap;
425  return;
426  }
427 
428  const auto rOnHeap = wkROnHeap->lock();
429  auto jittedActionOnHeap = wkJittedActionOnHeap->lock();
430 
431  // if we are here it means we are jitting, if we are jitting the loop manager must be alive
432  auto &prevNodePtr = *prevNodeOnHeap;
433  auto &loopManager = *prevNodePtr->GetLoopManagerUnchecked();
434  using ColTypes_t = TypeList<ColTypes...>;
435  constexpr auto nColumns = ColTypes_t::list_size;
436  auto ds = loopManager.GetDataSource();
437  if (ds != nullptr)
438  RDFInternal::AddDSColumns(cols, loopManager, *ds, ColTypes_t());
439 
440  auto actionPtr = BuildAction<ColTypes...>(cols, std::move(rOnHeap), nSlots, std::move(prevNodePtr), ActionTag{},
441  *defines);
442  jittedActionOnHeap->SetAction(std::move(actionPtr));
443 
444  // defines points to the columns structure in the heap, created before the jitted call so that the jitter can
445  // share data after it has lazily compiled the code. Here the data has been used and the memory can be freed.
446  delete defines;
447 
448  delete wkROnHeap;
449  delete prevNodeOnHeap;
450  delete wkJittedActionOnHeap;
451 }
452 
453 /// The contained `type` alias is `double` if `T == RInferredType`, `U` if `T == std::container<U>`, `T` otherwise.
454 template <typename T, bool Container = RDFInternal::IsDataContainer<T>::value && !std::is_same<T, std::string>::value>
455 struct RMinReturnType {
456  using type = T;
457 };
458 
459 template <>
460 struct RMinReturnType<RInferredType, false> {
461  using type = double;
462 };
463 
464 template <typename T>
465 struct RMinReturnType<T, true> {
466  using type = TTraits::TakeFirstParameter_t<T>;
467 };
468 
469 // return wrapper around f that prepends an `unsigned int slot` parameter
470 template <typename R, typename F, typename... Args>
471 std::function<R(unsigned int, Args...)> AddSlotParameter(F &f, TypeList<Args...>)
472 {
473  return [f](unsigned int, Args... a) -> R { return f(a...); };
474 }
475 
476 template <typename ColType, typename... Rest>
477 struct RNeedJitting {
478  static constexpr bool value = RNeedJitting<Rest...>::value;
479 };
480 
481 template <typename... Rest>
482 struct RNeedJitting<RInferredType, Rest...> {
483  static constexpr bool value = true;
484 };
485 
486 template <typename T>
487 struct RNeedJitting<T> {
488  static constexpr bool value = false;
489 };
490 
491 template <>
492 struct RNeedJitting<RInferredType> {
493  static constexpr bool value = true;
494 };
495 
496 ///////////////////////////////////////////////////////////////////////////////
497 /// Check preconditions for RInterface::Aggregate:
498 /// - the aggregator callable must have signature `U(U,T)` or `void(U&,T)`.
499 /// - the merge callable must have signature `U(U,U)` or `void(std::vector<U>&)`
501  typename mergeArgsNoDecay_t = typename CallableTraits<Merge>::arg_types_nodecay,
502  typename mergeArgs_t = typename CallableTraits<Merge>::arg_types,
503  typename mergeRet_t = typename CallableTraits<Merge>::ret_type>
504 void CheckAggregate(TypeList<U, T>)
505 {
506  constexpr bool isAggregatorOk =
507  (std::is_same<R, decayedU>::value) || (std::is_same<R, void>::value && std::is_lvalue_reference<U>::value);
508  static_assert(isAggregatorOk, "aggregator function must have signature `U(U,T)` or `void(U&,T)`");
509  constexpr bool isMergeOk =
510  (std::is_same<TypeList<decayedU, decayedU>, mergeArgs_t>::value && std::is_same<decayedU, mergeRet_t>::value) ||
511  (std::is_same<TypeList<std::vector<decayedU> &>, mergeArgsNoDecay_t>::value &&
512  std::is_same<void, mergeRet_t>::value);
513  static_assert(isMergeOk, "merge function must have signature `U(U,U)` or `void(std::vector<U>&)`");
514 }
515 
516 ///////////////////////////////////////////////////////////////////////////////
517 /// This overload of CheckAggregate is called when the aggregator takes more than two arguments
518 template <typename R, typename T>
519 void CheckAggregate(T)
520 {
521  static_assert(sizeof(T) == 0, "aggregator function must take exactly two arguments");
522 }
523 
524 ///////////////////////////////////////////////////////////////////////////////
525 /// Check as many template parameters were passed as the number of column names, throw if this is not the case.
526 void CheckTypesAndPars(unsigned int nTemplateParams, unsigned int nColumnNames);
527 
528 /// Return local BranchNames or default BranchNames according to which one should be used
529 const ColumnNames_t SelectColumns(unsigned int nArgs, const ColumnNames_t &bl, const ColumnNames_t &defBl);
530 
531 /// Check whether column names refer to a valid branch of a TTree or have been `Define`d. Return invalid column names.
532 ColumnNames_t FindUnknownColumns(const ColumnNames_t &requiredCols, const ColumnNames_t &datasetColumns,
533  const ColumnNames_t &definedCols, const ColumnNames_t &dataSourceColumns);
534 
535 /// Returns the list of Filters defined in the whole graph
536 std::vector<std::string> GetFilterNames(const std::shared_ptr<RLoopManager> &loopManager);
537 
538 /// Returns the list of Filters defined in the branch
539 template <typename NodeType>
540 std::vector<std::string> GetFilterNames(const std::shared_ptr<NodeType> &node)
541 {
542  std::vector<std::string> filterNames;
543  node->AddFilterName(filterNames);
544  return filterNames;
545 }
546 
547 // Check if a condition is true for all types
548 template <bool...>
549 struct TBoolPack;
550 
551 template <bool... bs>
552 using IsTrueForAllImpl_t = typename std::is_same<TBoolPack<bs..., true>, TBoolPack<true, bs...>>;
553 
554 template <bool... Conditions>
555 struct TEvalAnd {
556  static constexpr bool value = IsTrueForAllImpl_t<Conditions...>::value;
557 };
558 
559 // Check if a class is a specialisation of stl containers templates
560 // clang-format off
561 
562 template <typename>
563 struct IsList_t : std::false_type {};
564 
565 template <typename T>
566 struct IsList_t<std::list<T>> : std::true_type {};
567 
568 template <typename>
569 struct IsDeque_t : std::false_type {};
570 
571 template <typename T>
572 struct IsDeque_t<std::deque<T>> : std::true_type {};
573 // clang-format on
574 
575 } // namespace RDF
576 } // namespace Internal
577 
578 namespace Detail {
579 namespace RDF {
580 
581 /// The aliased type is `double` if `T == RInferredType`, `U` if `T == container<U>`, `T` otherwise.
582 template <typename T>
583 using MinReturnType_t = typename RDFInternal::RMinReturnType<T>::type;
584 
585 template <typename T>
586 using MaxReturnType_t = MinReturnType_t<T>;
587 
588 template <typename T>
589 using SumReturnType_t = MinReturnType_t<T>;
590 
591 } // namespace RDF
592 } // namespace Detail
593 } // namespace ROOT
594 
595 /// \endcond
596 
597 #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:475
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:360
f
#define f(i)
Definition: RSha256.hxx:104
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:724
ROOT::Internal::RDF::CheckTypesAndPars
void CheckTypesAndPars(unsigned int nTemplateParams, unsigned int nColumnNames)
Definition: RDFInterfaceUtils.cxx:436
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:508
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
ROOT::Internal::RDF::CreateSnapshotRDF
HeadNode_t CreateSnapshotRDF(const ColumnNames_t &validCols, std::string_view treeName, std::string_view fileName, bool isLazy, RLoopManager &loopManager, std::unique_ptr< RDFInternal::RActionBase > actionPtr)
Definition: RDFInterfaceUtils.cxx:332
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:701
ROOT::RDF::RResultPtr
Smart pointer for the return type of actions.
Definition: RResultPtr.hxx:79
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:105
ROOT::Detail::RDF::RLoopManager::GetDSValuePtrs
const std::map< std::string, std::vector< void * > > & GetDSValuePtrs() const
Definition: RLoopManager.hxx:174
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:395
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:319
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:554
h
#define h(i)
Definition: RSha256.hxx:106
ROOT::Internal::RDF::DemangleTypeIdName
std::string DemangleTypeIdName(const std::type_info &typeInfo)
Definition: RDFInterfaceUtils.cxx:350
a
auto * a
Definition: textangle.C:12
RStringView.hxx
ROOT::Internal::RDF::PrettyPrintAddr
std::string PrettyPrintAddr(const void *const addr)
Definition: RDFInterfaceUtils.cxx:500
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:89
TMath::Min
Short_t Min(Short_t a, Short_t b)
Definition: TMathBase.h:180
ROOT::RDF
Definition: RArrowDS.hxx:20
RAction.hxx
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:665
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:700
ROOT::Detail::RDF::RFilter
Definition: RFilter.hxx:52
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:450
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:655
ROOT::Internal::RDF::GetFilterNames
std::vector< std::string > GetFilterNames(const std::shared_ptr< RLoopManager > &loopManager)
Definition: RDFInterfaceUtils.cxx:495
ROOT::Internal::RDF::JitBuildAction
std::string JitBuildAction(const ColumnNames_t &bl, std::shared_ptr< RDFDetail::RNodeBase > *prevNode, const std::type_info &art, const std::type_info &at, void *rOnHeap, TTree *tree, const unsigned int nSlots, const RDFInternal::RBookedDefines &customCols, RDataSource *ds, std::weak_ptr< RJittedAction > *jittedActionOnHeap)
Definition: RDFInterfaceUtils.cxx:598
ROOT::Internal::RDF::AtLeastOneEmptyString
bool AtLeastOneEmptyString(const std::vector< std::string_view > strings)
Definition: RDFInterfaceUtils.cxx:646
RMakeUnique.hxx
TH1::kAllAxes
@ kAllAxes
Definition: TH1.h:75
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
VSD Structures.
Definition: StringConv.hxx:21
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:696
TError.h
g
#define g(i)
Definition: RSha256.hxx:105