Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
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>
16#include <ROOT/RDF/ActionHelpers.hxx> // for BuildAction
21#include <ROOT/RDF/RDefine.hxx>
23#include <ROOT/RDF/RFilter.hxx>
24#include <ROOT/RDF/Utils.hxx>
30#include <string_view>
32#include <ROOT/TypeTraits.hxx>
33#include <RConfigure.h> // for R__HAS_ROOT7
34#include <TError.h> // gErrorIgnoreLevel
35#include <TH1.h>
36#include <TROOT.h> // IsImplicitMTEnabled
37
38#include <deque>
39#include <functional>
40#include <list>
41#include <memory>
42#include <string>
43#include <type_traits>
44#include <typeinfo>
45#include <vector>
46
47class TTree;
48namespace ROOT {
49namespace Detail {
50namespace RDF {
51class RNodeBase;
52}
53}
54namespace RDF {
55template <typename Proxied>
56class RInterface;
58} // namespace RDF
59
60} // namespace ROOT
61
62/// \cond HIDDEN_SYMBOLS
63
64namespace ROOT {
65namespace Internal {
66namespace RDF {
67using namespace ROOT::Detail::RDF;
68using namespace ROOT::RDF;
69namespace TTraits = ROOT::TypeTraits;
70
71std::string DemangleTypeIdName(const std::type_info &typeInfo);
72
73ColumnNames_t
74ConvertRegexToColumns(const ColumnNames_t &colNames, std::string_view columnNameRegexp, std::string_view callerName);
75
76/// An helper object that sets and resets gErrorIgnoreLevel via RAII.
77class RIgnoreErrorLevelRAII {
78private:
79 int fCurIgnoreErrorLevel = gErrorIgnoreLevel;
80
81public:
82 RIgnoreErrorLevelRAII(int errorIgnoreLevel) { gErrorIgnoreLevel = errorIgnoreLevel; }
83 ~RIgnoreErrorLevelRAII() { gErrorIgnoreLevel = fCurIgnoreErrorLevel; }
84};
85
86/****** BuildAction overloads *******/
87
88// clang-format off
89/// This namespace defines types to be used for tag dispatching in RInterface.
90namespace ActionTags {
91struct Histo1D{};
92struct Histo2D{};
93struct Histo3D{};
94struct HistoND{};
95struct HistoNSparseD{};
96struct Hist{};
97struct HistWithWeight{};
98struct Graph{};
99struct GraphAsymmErrors{};
100struct Profile1D{};
101struct Profile2D{};
102struct Profile{};
103struct ProfileWithWeight{};
104struct Min{};
105struct Max{};
106struct Sum{};
107struct Mean{};
108struct Fill{};
109struct StdDev{};
110struct Median{};
111struct Display{};
112struct Snapshot{};
113struct Book{};
114}
115// clang-format on
116
117template <typename T, bool ISV6HISTO = std::is_base_of<TH1, std::decay_t<T>>::value>
118struct HistoUtils {
119 static bool HasAxisLimits(T &h)
120 {
121 auto xaxis = h.GetXaxis();
122 return !(xaxis->GetXmin() == 0. && xaxis->GetXmax() == 0.);
123 }
124};
125
126template <typename T>
127struct HistoUtils<T, false> {
128 static bool HasAxisLimits(T &) { return true; }
129};
130
131// Generic filling (covers Histo2D, HistoND, HistoNSparseD, Profile1D and Profile2D actions, with and without weights)
132template <typename... ColTypes, typename ActionTag, typename ActionResultType, typename PrevNodeType>
133std::unique_ptr<RActionBase>
134BuildAction(const ColumnNames_t &bl, const std::shared_ptr<ActionResultType> &h, const unsigned int nSlots,
135 std::shared_ptr<PrevNodeType> prevNode, ActionTag, const RColumnRegister &colRegister)
136{
137 using Helper_t = FillHelper<ActionResultType>;
138 using Action_t = RAction<Helper_t, PrevNodeType, TTraits::TypeList<ColTypes...>>;
139 return std::make_unique<Action_t>(Helper_t(h, nSlots), bl, std::move(prevNode), colRegister);
140}
141
142// Histo1D filling (must handle the special case of distinguishing FillHelper and BufferedFillHelper
143template <typename... ColTypes, typename PrevNodeType>
144std::unique_ptr<RActionBase>
145BuildAction(const ColumnNames_t &bl, const std::shared_ptr<::TH1D> &h, const unsigned int nSlots,
146 std::shared_ptr<PrevNodeType> prevNode, ActionTags::Histo1D, const RColumnRegister &colRegister)
147{
148 auto hasAxisLimits = HistoUtils<::TH1D>::HasAxisLimits(*h);
149
150 if (hasAxisLimits || !IsImplicitMTEnabled()) {
151 using Helper_t = FillHelper<::TH1D>;
152 using Action_t = RAction<Helper_t, PrevNodeType, TTraits::TypeList<ColTypes...>>;
153 return std::make_unique<Action_t>(Helper_t(h, nSlots), bl, std::move(prevNode), colRegister);
154 } else {
155 using Helper_t = BufferedFillHelper;
156 using Action_t = RAction<Helper_t, PrevNodeType, TTraits::TypeList<ColTypes...>>;
157 return std::make_unique<Action_t>(Helper_t(h, nSlots), bl, std::move(prevNode), colRegister);
158 }
159}
160
161// Action for Histo3D, where thread safe filling might be supported to save memory
162template <typename... ColTypes, typename ActionResultType, typename PrevNodeType>
163std::unique_ptr<RActionBase>
164BuildAction(const ColumnNames_t &bl, const std::shared_ptr<ActionResultType> &h, const unsigned int nSlots,
165 std::shared_ptr<PrevNodeType> prevNode, ActionTags::Histo3D, const RColumnRegister &colRegister)
166{
167 if (RDFInternal::NThreadPerTH3() <= 1 || nSlots == 1) {
168 using Helper_t = FillHelper<ActionResultType>;
169 using Action_t = RAction<Helper_t, PrevNodeType, TTraits::TypeList<ColTypes...>>;
170 return std::make_unique<Action_t>(Helper_t(h, nSlots), bl, std::move(prevNode), colRegister);
171 } else {
172 using Helper_t = ThreadSafeFillHelper<ActionResultType>;
173 using Action_t = RAction<Helper_t, PrevNodeType, TTraits::TypeList<ColTypes...>>;
174 if constexpr (sizeof...(ColTypes) > 3) {
175 h->Sumw2();
176 }
177 const auto histoSlots = std::max(nSlots / RDFInternal::NThreadPerTH3(), 1u);
178 return std::make_unique<Action_t>(Helper_t(h, histoSlots), bl, std::move(prevNode), colRegister);
179 }
180}
181
182#ifdef R__HAS_ROOT7
183// Action for RHist using RHistConcurrentFiller without weights
184template <typename... ColTypes, typename BinContentType, typename PrevNodeType>
185std::unique_ptr<RActionBase>
186BuildAction(const ColumnNames_t &columnList, const std::shared_ptr<ROOT::Experimental::RHist<BinContentType>> &h,
187 const unsigned int nSlots, std::shared_ptr<PrevNodeType> prevNode, ActionTags::Hist,
188 const RColumnRegister &colRegister)
189{
190 using Helper_t = RHistFillHelper<BinContentType>;
191 using Action_t = RAction<Helper_t, PrevNodeType, TTraits::TypeList<ColTypes...>>;
192 return std::make_unique<Action_t>(Helper_t(h, nSlots), columnList, std::move(prevNode), colRegister);
193}
194
195// Action for RHist using RHistConcurrentFiller with weights
196template <typename... ColTypes, typename BinContentType, typename PrevNodeType>
197std::unique_ptr<RActionBase>
198BuildAction(const ColumnNames_t &columnList, const std::shared_ptr<ROOT::Experimental::RHist<BinContentType>> &h,
199 const unsigned int nSlots, std::shared_ptr<PrevNodeType> prevNode, ActionTags::HistWithWeight,
200 const RColumnRegister &colRegister)
201{
202 using Helper_t = RHistFillHelper<BinContentType, true>;
203 using Action_t = RAction<Helper_t, PrevNodeType, TTraits::TypeList<ColTypes...>>;
204 return std::make_unique<Action_t>(Helper_t(h, nSlots), columnList, std::move(prevNode), colRegister);
205}
206
207// Action for RHistEngine using FillAtomic without weights
208template <typename... ColTypes, typename BinContentType, typename PrevNodeType>
209std::unique_ptr<RActionBase>
210BuildAction(const ColumnNames_t &columnList, const std::shared_ptr<ROOT::Experimental::RHistEngine<BinContentType>> &h,
211 const unsigned int, std::shared_ptr<PrevNodeType> prevNode, ActionTags::Hist,
212 const RColumnRegister &colRegister)
213{
214 using Helper_t = RHistEngineFillHelper<BinContentType>;
215 using Action_t = RAction<Helper_t, PrevNodeType, TTraits::TypeList<ColTypes...>>;
216 return std::make_unique<Action_t>(Helper_t(h), columnList, std::move(prevNode), colRegister);
217}
218
219// Action for RHistEngine using FillAtomic with weights
220template <typename... ColTypes, typename BinContentType, typename PrevNodeType>
221std::unique_ptr<RActionBase>
222BuildAction(const ColumnNames_t &columnList, const std::shared_ptr<ROOT::Experimental::RHistEngine<BinContentType>> &h,
223 const unsigned int, std::shared_ptr<PrevNodeType> prevNode, ActionTags::HistWithWeight,
224 const RColumnRegister &colRegister)
225{
226 using Helper_t = RHistEngineFillHelper<BinContentType, true>;
227 using Action_t = RAction<Helper_t, PrevNodeType, TTraits::TypeList<ColTypes...>>;
228 return std::make_unique<Action_t>(Helper_t(h), columnList, std::move(prevNode), colRegister);
229}
230
231// Action for RProfile using RProfileConcurrentFiller without weights
232template <typename... ColTypes, typename PrevNodeType>
233std::unique_ptr<RActionBase>
234BuildAction(const ColumnNames_t &columnList, const std::shared_ptr<ROOT::Experimental::RProfile> &p,
235 const unsigned int nSlots, std::shared_ptr<PrevNodeType> prevNode, ActionTags::Profile,
236 const RColumnRegister &colRegister)
237{
238 using Helper_t = RProfileFillHelper<>;
239 using Action_t = RAction<Helper_t, PrevNodeType, TTraits::TypeList<ColTypes...>>;
240 return std::make_unique<Action_t>(Helper_t(p, nSlots), columnList, std::move(prevNode), colRegister);
241}
242
243// Action for RProfile using RProfileConcurrentFiller with weights
244template <typename... ColTypes, typename PrevNodeType>
245std::unique_ptr<RActionBase>
246BuildAction(const ColumnNames_t &columnList, const std::shared_ptr<ROOT::Experimental::RProfile> &p,
247 const unsigned int nSlots, std::shared_ptr<PrevNodeType> prevNode, ActionTags::ProfileWithWeight,
248 const RColumnRegister &colRegister)
249{
250 using Helper_t = RProfileFillHelper<true>;
251 using Action_t = RAction<Helper_t, PrevNodeType, TTraits::TypeList<ColTypes...>>;
252 return std::make_unique<Action_t>(Helper_t(p, nSlots), columnList, std::move(prevNode), colRegister);
253}
254#endif
255
256template <typename... ColTypes, typename PrevNodeType>
257std::unique_ptr<RActionBase>
258BuildAction(const ColumnNames_t &bl, const std::shared_ptr<TGraph> &g, const unsigned int nSlots,
259 std::shared_ptr<PrevNodeType> prevNode, ActionTags::Graph, const RColumnRegister &colRegister)
260{
261 using Helper_t = FillTGraphHelper;
262 using Action_t = RAction<Helper_t, PrevNodeType, TTraits::TypeList<ColTypes...>>;
263 return std::make_unique<Action_t>(Helper_t(g, nSlots), bl, std::move(prevNode), colRegister);
264}
265
266template <typename... ColTypes, typename PrevNodeType>
267std::unique_ptr<RActionBase>
268BuildAction(const ColumnNames_t &bl, const std::shared_ptr<TGraphAsymmErrors> &g, const unsigned int nSlots,
269 std::shared_ptr<PrevNodeType> prevNode, ActionTags::GraphAsymmErrors, const RColumnRegister &colRegister)
270{
271 using Helper_t = FillTGraphAsymmErrorsHelper;
272 using Action_t = RAction<Helper_t, PrevNodeType, TTraits::TypeList<ColTypes...>>;
273 return std::make_unique<Action_t>(Helper_t(g, nSlots), bl, std::move(prevNode), colRegister);
274}
275
276// Min action
277template <typename ColType, typename PrevNodeType, typename ActionResultType>
278std::unique_ptr<RActionBase>
279BuildAction(const ColumnNames_t &bl, const std::shared_ptr<ActionResultType> &minV, const unsigned int nSlots,
280 std::shared_ptr<PrevNodeType> prevNode, ActionTags::Min, const RColumnRegister &colRegister)
281{
282 using Helper_t = MinHelper<ActionResultType>;
283 using Action_t = RAction<Helper_t, PrevNodeType, TTraits::TypeList<ColType>>;
284 return std::make_unique<Action_t>(Helper_t(minV, nSlots), bl, std::move(prevNode), colRegister);
285}
286
287// Max action
288template <typename ColType, typename PrevNodeType, typename ActionResultType>
289std::unique_ptr<RActionBase>
290BuildAction(const ColumnNames_t &bl, const std::shared_ptr<ActionResultType> &maxV, const unsigned int nSlots,
291 std::shared_ptr<PrevNodeType> prevNode, ActionTags::Max, const RColumnRegister &colRegister)
292{
293 using Helper_t = MaxHelper<ActionResultType>;
294 using Action_t = RAction<Helper_t, PrevNodeType, TTraits::TypeList<ColType>>;
295 return std::make_unique<Action_t>(Helper_t(maxV, nSlots), bl, std::move(prevNode), colRegister);
296}
297
298// Sum action
299template <typename ColType, typename PrevNodeType, typename ActionResultType>
300std::unique_ptr<RActionBase>
301BuildAction(const ColumnNames_t &bl, const std::shared_ptr<ActionResultType> &sumV, const unsigned int nSlots,
302 std::shared_ptr<PrevNodeType> prevNode, ActionTags::Sum, const RColumnRegister &colRegister)
303{
304 using Helper_t = SumHelper<ActionResultType>;
305 using Action_t = RAction<Helper_t, PrevNodeType, TTraits::TypeList<ColType>>;
306 return std::make_unique<Action_t>(Helper_t(sumV, nSlots), bl, std::move(prevNode), colRegister);
307}
308
309// Mean action
310template <typename ColType, typename PrevNodeType>
311std::unique_ptr<RActionBase>
312BuildAction(const ColumnNames_t &bl, const std::shared_ptr<double> &meanV, const unsigned int nSlots,
313 std::shared_ptr<PrevNodeType> prevNode, ActionTags::Mean, const RColumnRegister &colRegister)
314{
315 using Helper_t = MeanHelper;
316 using Action_t = RAction<Helper_t, PrevNodeType, TTraits::TypeList<ColType>>;
317 return std::make_unique<Action_t>(Helper_t(meanV, nSlots), bl, std::move(prevNode), colRegister);
318}
319
320// Standard Deviation action
321template <typename ColType, typename PrevNodeType>
322std::unique_ptr<RActionBase>
323BuildAction(const ColumnNames_t &bl, const std::shared_ptr<double> &stdDeviationV, const unsigned int nSlots,
324 std::shared_ptr<PrevNodeType> prevNode, ActionTags::StdDev, const RColumnRegister &colRegister)
325{
326 using Helper_t = StdDevHelper;
327 using Action_t = RAction<Helper_t, PrevNodeType, TTraits::TypeList<ColType>>;
328 return std::make_unique<Action_t>(Helper_t(stdDeviationV, nSlots), bl, prevNode, colRegister);
329}
330
331// Median action
332template <typename ColType, typename PrevNodeType>
333std::unique_ptr<RActionBase>
334BuildAction(const ColumnNames_t &bl, const std::shared_ptr<double> &meanV, const unsigned int nSlots,
335 std::shared_ptr<PrevNodeType> prevNode, ActionTags::Median, const RColumnRegister &colRegister)
336{
337 using Helper_t = MedianHelper;
338 using Action_t = RAction<Helper_t, PrevNodeType, TTraits::TypeList<ColType>>;
339 return std::make_unique<Action_t>(Helper_t(meanV, nSlots), bl, std::move(prevNode), colRegister);
340}
341
342using displayHelperArgs_t = std::pair<size_t, std::shared_ptr<ROOT::RDF::RDisplay>>;
343
344// Display action
345template <typename... ColTypes, typename PrevNodeType>
346std::unique_ptr<RActionBase>
347BuildAction(const ColumnNames_t &bl, const std::shared_ptr<displayHelperArgs_t> &helperArgs, const unsigned int,
348 std::shared_ptr<PrevNodeType> prevNode, ActionTags::Display, const RColumnRegister &colRegister)
349{
350 using Helper_t = DisplayHelper<PrevNodeType>;
351 using Action_t = RAction<Helper_t, PrevNodeType, TTraits::TypeList<ColTypes...>>;
352 return std::make_unique<Action_t>(Helper_t(helperArgs->first, helperArgs->second, prevNode), bl, prevNode,
353 colRegister);
354}
355
356struct SnapshotHelperArgs {
357 std::string fFileName;
358 std::string fDirName;
359 std::string fTreeName;
360 std::vector<std::string> fOutputColNames;
362 ROOT::Detail::RDF::RLoopManager *fOutputLoopManager;
363 ROOT::Detail::RDF::RLoopManager *fInputLoopManager;
364 bool fToNTuple;
365 bool fIncludeVariations;
366};
367
368template <typename PrevNodeType>
369std::unique_ptr<RActionBase>
370BuildAction(const ColumnNames_t &colNames, const std::shared_ptr<SnapshotHelperArgs> &snapHelperArgs,
371 const unsigned int nSlots, std::shared_ptr<PrevNodeType> prevNode, const RColumnRegister &colRegister,
372 const std::vector<const std::type_info *> &colTypeIDs)
373{
374 const auto &filename = snapHelperArgs->fFileName;
375 const auto &dirname = snapHelperArgs->fDirName;
376 const auto &treename = snapHelperArgs->fTreeName;
377 const auto &outputColNames = snapHelperArgs->fOutputColNames;
378 const auto &options = snapHelperArgs->fOptions;
379 const auto &outputLM = snapHelperArgs->fOutputLoopManager;
380 const auto &inputLM = snapHelperArgs->fInputLoopManager;
381
382 auto sz = colNames.size();
383 std::vector<bool> isDefine(sz);
384 for (auto i = 0u; i < sz; ++i)
385 isDefine[i] = colRegister.IsDefineOrAlias(colNames[i]);
386
387 std::unique_ptr<RActionBase> actionPtr;
388 if (snapHelperArgs->fToNTuple) {
389 // We use the same helper for single- and multi-thread snapshot.
390 using Helper_t = UntypedSnapshotRNTupleHelper;
391 using Action_t = RActionSnapshot<Helper_t, PrevNodeType>;
392
393 actionPtr.reset(new Action_t(Helper_t(nSlots, filename, dirname, treename, colNames, outputColNames, options,
394 inputLM, outputLM, colTypeIDs),
395 colNames, colTypeIDs, prevNode, colRegister));
396 } else {
398 // single-thread snapshot
399 if (snapHelperArgs->fIncludeVariations) {
400 using Helper_t = SnapshotHelperWithVariations;
401 using Action_t = RActionSnapshot<Helper_t, PrevNodeType>;
402 actionPtr.reset(new Action_t(Helper_t(filename, dirname, treename, colNames, outputColNames, options,
403 std::move(isDefine), outputLM, inputLM, colTypeIDs),
404 colNames, colTypeIDs, prevNode, colRegister));
405 } else {
406 using Helper_t = UntypedSnapshotTTreeHelper;
407 using Action_t = RActionSnapshot<Helper_t, PrevNodeType>;
408 actionPtr.reset(new Action_t(Helper_t(filename, dirname, treename, colNames, outputColNames, options,
409 std::move(isDefine), outputLM, inputLM, colTypeIDs),
410 colNames, colTypeIDs, prevNode, colRegister));
411 }
412 } else {
413 if (snapHelperArgs->fIncludeVariations) {
414 throw std::invalid_argument("Multi-threaded snapshot with variations is not supported yet.");
415 }
416 // multi-thread snapshot
417 using Helper_t = UntypedSnapshotTTreeHelperMT;
418 using Action_t = RActionSnapshot<Helper_t, PrevNodeType>;
419 actionPtr.reset(new Action_t(Helper_t(nSlots, filename, dirname, treename, colNames, outputColNames, options,
420 std::move(isDefine), outputLM, inputLM, colTypeIDs),
421 colNames, colTypeIDs, prevNode, colRegister));
422 }
423 }
424
425 return actionPtr;
426}
427
428template <typename PrevNodeType>
429std::unique_ptr<RActionBase>
430BuildAction(const ColumnNames_t &colNames, const std::vector<const std::type_info *> &colTypeIDs,
431 const std::shared_ptr<ROOT::RVecF> &location, const std::vector<std::size_t> &vecSizes, float vecPadding,
432 std::shared_ptr<PrevNodeType> prevNode, const RColumnRegister &colRegister)
433{
436 return std::make_unique<Action_t>(Helper_t(location, colTypeIDs, vecSizes, vecPadding), colNames, colTypeIDs,
437 prevNode, colRegister);
438}
439
440// Book with custom helper type
441template <typename... ColTypes, typename PrevNodeType, typename Helper_t>
442std::unique_ptr<RActionBase>
443BuildAction(const ColumnNames_t &bl, const std::shared_ptr<Helper_t> &h, const unsigned int /*nSlots*/,
444 std::shared_ptr<PrevNodeType> prevNode, ActionTags::Book, const RColumnRegister &colRegister)
445{
446 using Action_t = RAction<Helper_t, PrevNodeType, TTraits::TypeList<ColTypes...>>;
447 return std::make_unique<Action_t>(Helper_t(std::move(*h)), bl, std::move(prevNode), colRegister);
448}
449
450/****** end BuildAndBook ******/
451
452template <typename Filter>
453void CheckFilter(Filter &)
454{
455 using FilterRet_t = typename RDF::CallableTraits<Filter>::ret_type;
456 static_assert(std::is_convertible<FilterRet_t, bool>::value,
457 "filter expression returns a type that is not convertible to bool");
458}
459
460ColumnNames_t FilterArraySizeColNames(const ColumnNames_t &columnNames, const std::string &action);
461
462void CheckValidCppVarName(std::string_view var, const std::string &where);
463
464void CheckForRedefinition(const std::string &where, std::string_view definedCol, const RColumnRegister &colRegister,
465 const ColumnNames_t &dataSourceColumns);
466
467void CheckForDefinition(const std::string &where, std::string_view definedColView, const RColumnRegister &colRegister,
468 const ColumnNames_t &dataSourceColumns);
469
470void CheckForNoVariations(const std::string &where, std::string_view definedColView,
471 const RColumnRegister &colRegister);
472
473std::string PrettyPrintAddr(const void *const addr);
474
475std::shared_ptr<RJittedFilter> BookFilterJit(std::shared_ptr<RNodeBase> prevNode, std::string_view name,
476 std::string_view expression, const RColumnRegister &colRegister,
477 TTree *tree, RDataSource *ds);
478
479std::shared_ptr<RJittedDefine> BookDefineJit(std::string_view name, std::string_view expression, RLoopManager &lm,
480 RDataSource *ds, const RColumnRegister &colRegister);
481
482std::shared_ptr<RJittedDefine> BookDefinePerSampleJit(std::string_view name, std::string_view expression,
483 RLoopManager &lm, const RColumnRegister &colRegister);
484
485std::shared_ptr<RJittedVariation>
486BookVariationJit(const std::vector<std::string> &colNames, std::string_view variationName,
487 const std::vector<std::string> &variationTags, std::string_view expression, RLoopManager &lm,
488 RDataSource *ds, const RColumnRegister &colRegister, bool isSingleColumn,
489 const std::string &varyColType);
490
491std::string JitBuildAction(const ColumnNames_t &bl, const std::type_info &art, const std::type_info &at, TTree *tree,
492 const unsigned int nSlots, const RColumnRegister &colRegister, RDataSource *ds,
493 const bool vector2RVec = true);
494
495bool AtLeastOneEmptyString(const std::vector<std::string_view> strings);
496
497/// Take a shared_ptr<AnyNodeType> and return a shared_ptr<RNodeBase>.
498/// This works for RLoopManager nodes as well as filters and ranges.
499std::shared_ptr<RNodeBase> UpcastNode(std::shared_ptr<RNodeBase> ptr);
500
501ColumnNames_t GetValidatedColumnNames(RLoopManager &lm, const unsigned int nColumns, const ColumnNames_t &columns,
502 const RColumnRegister &validDefines, RDataSource *ds);
503
504std::vector<std::string> GetValidatedArgTypes(const ColumnNames_t &colNames, const RColumnRegister &colRegister,
505 TTree *tree, RDataSource *ds, const std::string &context,
506 bool vector2RVec);
507
508template <typename T>
509void AddDSColumnsHelper(const std::string &colName, RLoopManager &lm, RDataSource &ds, RColumnRegister &colRegister)
510{
511
512 if (colRegister.IsDefineOrAlias(colName))
513 return;
514
515 if (lm.HasDataSourceColumnReaders(colName, typeid(T)))
516 return;
517
518 if (!ds.HasColumn(colName) &&
520 return;
521
522 const auto nSlots = lm.GetNSlots();
523 std::vector<std::unique_ptr<RColumnReaderBase>> colReaders;
524 colReaders.reserve(nSlots);
525
526 const auto valuePtrs = ds.GetColumnReaders<T>(colName);
527 if (!valuePtrs.empty()) { // we are using the old GetColumnReaders mechanism in this RDataSource
528 for (auto *ptr : valuePtrs)
529 colReaders.emplace_back(new RDSColumnReader<T>(ptr));
530
531 } else { // using the new GetColumnReaders mechanism
532 // TODO consider changing the interface so we return all of these for all slots in one go
533 for (auto slot = 0u; slot < lm.GetNSlots(); ++slot)
534 colReaders.emplace_back(
535 ROOT::Internal::RDF::CreateColumnReader(ds, slot, colName, typeid(T), /*treeReader*/ nullptr));
536 }
537
538 lm.AddDataSourceColumnReaders(colName, std::move(colReaders), typeid(T));
539}
540
541/// Take list of column names that must be defined, current map of custom columns, current list of defined column names,
542/// and return a new map of custom columns (with the new datasource columns added to it)
543template <typename... ColumnTypes>
544void AddDSColumns(const std::vector<std::string> &requiredCols, RLoopManager &lm, RDataSource &ds,
545 TTraits::TypeList<ColumnTypes...>, RColumnRegister &colRegister)
546{
547 // hack to expand a template parameter pack without c++17 fold expressions.
548 using expander = int[];
549 int i = 0;
550 (void)expander{(AddDSColumnsHelper<ColumnTypes>(requiredCols[i], lm, ds, colRegister), ++i)..., 0};
551}
552
553void AddDSColumns(const std::vector<std::string> &requiredCols, ROOT::Detail::RDF::RLoopManager &lm,
554 ROOT::RDF::RDataSource &ds, const std::vector<const std::type_info *> &colTypeIDs,
556
557// this function is meant to be called by the jitted code generated by BookFilterJit
558template <typename F>
559void JitFilterHelper(F &&f, const ColumnNames_t &cols, RColumnRegister &colRegister,
561{
562 if (!jittedFilter) {
563 // The branch of the computation graph that needed this jitted code went out of scope between the type
564 // jitting was booked and the time jitting actually happened. Nothing to do other than cleaning up.
565 return;
566 }
567
568 // mock Filter logic -- validity checks and Define-ition of RDataSource columns
569 using Callable_t = std::decay_t<F>;
570 auto prevNode = jittedFilter->MoveOutPrevNode();
571 using PrevNode_t = typename decltype(prevNode)::element_type;
573 using ColTypes_t = typename TTraits::CallableTraits<Callable_t>::arg_types;
574 constexpr auto nColumns = ColTypes_t::list_size;
575 CheckFilter(f);
576
577 auto ds = lm.GetDataSource();
578
579 if (ds != nullptr && !cols.empty())
580 AddDSColumns(cols, lm, *ds, ColTypes_t(), colRegister);
581
582 jittedFilter->SetFilter(
583 std::unique_ptr<RFilterBase>(new F_t(std::forward<F>(f), cols, prevNode, colRegister, jittedFilter->GetName())));
584}
585
586namespace DefineTypes {
587struct RDefineTag {};
588struct RDefinePerSampleTag {};
589}
590
591template <typename F>
592auto MakeDefineNode(DefineTypes::RDefineTag, std::string_view name, std::string_view dummyType, F &&f,
593 const ColumnNames_t &cols, RColumnRegister &colRegister, RLoopManager &lm)
594{
595 return std::unique_ptr<RDefineBase>(new RDefine<std::decay_t<F>, ExtraArgsForDefine::None>(
596 name, dummyType, std::forward<F>(f), cols, colRegister, lm));
597}
598
599template <typename F>
600auto MakeDefineNode(DefineTypes::RDefinePerSampleTag, std::string_view name, std::string_view dummyType, F &&f,
601 const ColumnNames_t &, RColumnRegister &, RLoopManager &lm)
602{
603 return std::unique_ptr<RDefineBase>(
604 new RDefinePerSample<std::decay_t<F>>(name, dummyType, std::forward<F>(f), lm));
605}
606
607// Build a RDefine or a RDefinePerSample object and attach it to an existing RJittedDefine
608// This function is meant to be called by jitted code right before starting the event loop.
609// If colsPtr is null, build a RDefinePerSample (it has no input columns), otherwise a RDefine.
610template <typename RDefineTypeTag, typename F>
611void JitDefineHelper(F &&f, const ColumnNames_t &cols, RColumnRegister &colRegister,
613{
614
615 if (!jittedDefine) {
616 // The branch of the computation graph that needed this jitted code went out of scope between the type
617 // jitting was booked and the time jitting actually happened. Nothing to do other than cleaning up.
618 return;
619 }
620
621 using Callable_t = std::decay_t<F>;
622 using ColTypes_t = typename TTraits::CallableTraits<Callable_t>::arg_types;
623
624 auto ds = lm.GetDataSource();
625 if (ds != nullptr && !cols.empty())
626 AddDSColumns(cols, lm, *ds, ColTypes_t(), colRegister);
627
628 // will never actually be used (trumped by jittedDefine->GetTypeName()), but we set it to something meaningful
629 // to help devs debugging
630 const auto dummyType = "jittedCol_t";
631 // use unique_ptr<RDefineBase> instead of make_unique<NewCol_t> to reduce jit/compile-times
632 std::unique_ptr<RDefineBase> newCol{
633 MakeDefineNode(RDefineTypeTag{}, jittedDefine->GetName(), dummyType, std::forward<F>(f), cols, colRegister, lm)};
634 jittedDefine->SetDefine(std::move(newCol));
635}
636
637template <bool IsSingleColumn, typename F>
638void JitVariationHelper(F &&f, const ColumnNames_t &inputColNames, RColumnRegister &colRegister,
639 ROOT::Detail::RDF::RLoopManager &lm, RJittedVariation *jittedVariation,
640 const ColumnNames_t &variedColNames, const ColumnNames_t &variationTags) noexcept
641{
642
643 if (!jittedVariation) {
644 // The branch of the computation graph that needed this jitted variation went out of scope between the type
645 // jitting was booked and the time jitting actually happened. Nothing to do other than cleaning up.
646 return;
647 }
648
649 using Callable_t = std::decay_t<F>;
650 using ColTypes_t = typename TTraits::CallableTraits<Callable_t>::arg_types;
651
652 auto ds = lm.GetDataSource();
653 if (ds != nullptr && !inputColNames.empty())
654 AddDSColumns(inputColNames, lm, *ds, ColTypes_t(), colRegister);
655
656 // use unique_ptr<RDefineBase> instead of make_unique<NewCol_t> to reduce jit/compile-times
657 std::unique_ptr<RVariationBase> newVariation{new RVariation<std::decay_t<F>, IsSingleColumn>(
658 variedColNames, jittedVariation->GetVariationName(), std::forward<F>(f), variationTags,
659 jittedVariation->GetTypeName(), colRegister, lm, inputColNames)};
660 jittedVariation->SetVariation(std::move(newVariation));
661}
662
663/// Convenience function invoked by jitted code to build action nodes at runtime
664template <typename ActionTag, typename... ColTypes, typename HelperArgType>
665void CallBuildAction(const ColumnNames_t &cols, RColumnRegister &colRegister, ROOT::Detail::RDF::RLoopManager &lm,
666 RJittedAction *jittedAction, unsigned int nSlots,
667 std::shared_ptr<HelperArgType> *helperArg) noexcept
668{
669 if (!jittedAction) {
670 // The branch of the computation graph that needed this jitted variation went out of scope between the type
671 // jitting was booked and the time jitting actually happened. Nothing to do other than cleaning up.
672 return;
673 }
674
675 using ColTypes_t = TypeList<ColTypes...>;
676 constexpr auto nColumns = ColTypes_t::list_size;
677 auto ds = lm.GetDataSource();
678 if (ds != nullptr && !cols.empty())
679 AddDSColumns(cols, lm, *ds, ColTypes_t(), colRegister);
680
681 auto actionPtr =
682 BuildAction<ColTypes...>(cols, *helperArg, nSlots, jittedAction->MoveOutPrevNode(), ActionTag{}, colRegister);
683 jittedAction->SetAction(std::move(actionPtr));
684}
685
686/// The contained `type` alias is `double` if `T == RInferredType`, `U` if `T == std::container<U>`, `T` otherwise.
687template <typename T, bool Container = IsDataContainer<T>::value && !std::is_same<T, std::string>::value>
688struct RMinReturnType {
689 using type = T;
690};
691
692template <>
693struct RMinReturnType<RInferredType, false> {
694 using type = double;
695};
696
697template <typename T>
698struct RMinReturnType<T, true> {
699 using type = TTraits::TakeFirstParameter_t<T>;
700};
701
702// return wrapper around f that prepends an `unsigned int slot` parameter
703template <typename R, typename F, typename... Args>
704std::function<R(unsigned int, Args...)> AddSlotParameter(F &f, TypeList<Args...>)
705{
706 return [f](unsigned int, Args... a) mutable -> R { return f(a...); };
707}
708
709template <typename ColType, typename... Rest>
710struct RNeedJittingHelper {
711 static constexpr bool value = RNeedJittingHelper<Rest...>::value;
712};
713
714template <typename... Rest>
715struct RNeedJittingHelper<RInferredType, Rest...> {
716 static constexpr bool value = true;
717};
718
719template <typename T>
720struct RNeedJittingHelper<T> {
721 static constexpr bool value = false;
722};
723
724template <>
725struct RNeedJittingHelper<RInferredType> {
726 static constexpr bool value = true;
727};
728
729template <typename ...ColTypes>
730struct RNeedJitting {
731 static constexpr bool value = RNeedJittingHelper<ColTypes...>::value;
732};
733
734template <>
735struct RNeedJitting<> {
736 static constexpr bool value = false;
737};
738
739///////////////////////////////////////////////////////////////////////////////
740/// Check preconditions for RInterface::Aggregate:
741/// - the aggregator callable must have signature `U(U,T)` or `void(U&,T)`.
742/// - the merge callable must have signature `U(U,U)` or `void(std::vector<U>&)`
743template <typename R, typename Merge, typename U, typename T, typename decayedU = std::decay_t<U>,
744 typename mergeArgsNoDecay_t = typename CallableTraits<Merge>::arg_types_nodecay,
745 typename mergeArgs_t = typename CallableTraits<Merge>::arg_types,
746 typename mergeRet_t = typename CallableTraits<Merge>::ret_type>
747void CheckAggregate(TypeList<U, T>)
748{
749 constexpr bool isAggregatorOk =
750 (std::is_same<R, decayedU>::value) || (std::is_same<R, void>::value && std::is_lvalue_reference<U>::value);
751 static_assert(isAggregatorOk, "aggregator function must have signature `U(U,T)` or `void(U&,T)`");
752 constexpr bool isMergeOk =
753 (std::is_same<TypeList<decayedU, decayedU>, mergeArgs_t>::value && std::is_same<decayedU, mergeRet_t>::value) ||
754 (std::is_same<TypeList<std::vector<decayedU> &>, mergeArgsNoDecay_t>::value &&
755 std::is_same<void, mergeRet_t>::value);
756 static_assert(isMergeOk, "merge function must have signature `U(U,U)` or `void(std::vector<U>&)`");
757}
758
759///////////////////////////////////////////////////////////////////////////////
760/// This overload of CheckAggregate is called when the aggregator takes more than two arguments
761template <typename R, typename T>
762void CheckAggregate(T)
763{
764 static_assert(sizeof(T) == 0, "aggregator function must take exactly two arguments");
765}
766
767///////////////////////////////////////////////////////////////////////////////
768/// Check as many template parameters were passed as the number of column names, throw if this is not the case.
769void CheckTypesAndPars(unsigned int nTemplateParams, unsigned int nColumnNames);
770
771/// Return local BranchNames or default BranchNames according to which one should be used
772const ColumnNames_t SelectColumns(unsigned int nArgs, const ColumnNames_t &bl, const ColumnNames_t &defBl);
773
774/// Check whether column names refer to a valid branch of a TTree or have been `Define`d. Return invalid column names.
775ColumnNames_t FindUnknownColumns(const ColumnNames_t &requiredCols, const RColumnRegister &definedCols,
776 const ColumnNames_t &dataSourceColumns);
777
778/// Returns the list of Filters defined in the whole graph
779std::vector<std::string> GetFilterNames(const std::shared_ptr<RLoopManager> &loopManager);
780
781/// Returns the list of Filters defined in the branch
782template <typename NodeType>
783std::vector<std::string> GetFilterNames(const std::shared_ptr<NodeType> &node)
784{
785 std::vector<std::string> filterNames;
786 node->AddFilterName(filterNames);
787 return filterNames;
788}
789
790struct ParsedTreePath {
791 std::string fTreeName;
792 std::string fDirName;
793};
794
795ParsedTreePath ParseTreePath(std::string_view fullTreeName);
796
797// Check if a condition is true for all types
798template <bool...>
799struct TBoolPack;
800
801template <bool... bs>
802using IsTrueForAllImpl_t = typename std::is_same<TBoolPack<bs..., true>, TBoolPack<true, bs...>>;
803
804template <bool... Conditions>
805struct TEvalAnd {
806 static constexpr bool value = IsTrueForAllImpl_t<Conditions...>::value;
807};
808
809// Check if a class is a specialisation of stl containers templates
810// clang-format off
811
812template <typename>
813struct IsList_t : std::false_type {};
814
815template <typename T>
816struct IsList_t<std::list<T>> : std::true_type {};
817
818template <typename>
819struct IsDeque_t : std::false_type {};
820
821template <typename T>
822struct IsDeque_t<std::deque<T>> : std::true_type {};
823// clang-format on
824
825void CheckForDuplicateSnapshotColumns(const ColumnNames_t &cols);
826
827void CheckSnapshotOptionsFormatCompatibility(const ROOT::RDF::RSnapshotOptions &opts);
828
829template <typename T>
830struct InnerValueType {
831 using type = T; // fallback for when T is not a nested RVec
832};
833
834template <typename Elem>
835struct InnerValueType<ROOT::VecOps::RVec<ROOT::VecOps::RVec<Elem>>> {
836 using type = Elem;
837};
838
839template <typename T>
840using InnerValueType_t = typename InnerValueType<T>::type;
841
842std::pair<std::vector<std::string>, std::vector<std::string>>
843AddSizeBranches(ROOT::RDF::RDataSource *ds, std::vector<std::string> &&colsWithoutAliases,
844 std::vector<std::string> &&colsWithAliases);
845
846void RemoveDuplicates(ColumnNames_t &columnNames);
847void RemoveRNTupleSubfields(ColumnNames_t &columnNames);
848
849} // namespace RDF
850} // namespace Internal
851
852namespace Detail {
853namespace RDF {
854
855/// The aliased type is `double` if `T == RInferredType`, `U` if `T == container<U>`, `T` otherwise.
856template <typename T>
857using MinReturnType_t = typename RDFInternal::RMinReturnType<T>::type;
858
859template <typename T>
860using MaxReturnType_t = MinReturnType_t<T>;
861
862template <typename T>
863using SumReturnType_t = MinReturnType_t<T>;
864
865} // namespace RDF
866} // namespace Detail
867} // namespace ROOT
868
869/// \endcond
870
871#endif
#define f(i)
Definition RSha256.hxx:104
#define g(i)
Definition RSha256.hxx:105
#define a(i)
Definition RSha256.hxx:99
#define h(i)
Definition RSha256.hxx:106
#define R(a, b, c, d, e, f, g, h, i)
Definition RSha256.hxx:110
Int_t gErrorIgnoreLevel
errors with level below this value will be ignored. Default is kUnset.
Definition TError.cxx:33
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char filename
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t type
char name[80]
Definition TGX11.cxx:142
std::string GetName() const
std::string GetName() const
A wrapper around a concrete RDefine, which forwards all calls to it RJittedDefine is a placeholder th...
void SetDefine(std::unique_ptr< RDefineBase > c)
A wrapper around a concrete RFilter, which forwards all calls to it RJittedFilter is the type of the ...
std::shared_ptr< RNodeBase > MoveOutPrevNode()
void SetFilter(std::unique_ptr< RFilterBase > f)
The head node of a RDF computation graph.
const std::set< std::string > & GetSuppressErrorsForMissingBranches() const
void AddDataSourceColumnReaders(std::string_view col, std::vector< std::unique_ptr< RColumnReaderBase > > &&readers, const std::type_info &ti)
RDataSource * GetDataSource() const
bool HasDataSourceColumnReaders(std::string_view col, const std::type_info &ti) const
Return true if AddDataSourceColumnReaders was called for column name col.
A histogram data structure to bin data along multiple dimensions.
A histogram for aggregation of data along multiple dimensions.
Definition RHist.hxx:66
A binder for user-defined columns, variations and aliases.
RDataSource defines an API that RDataFrame can use to read arbitrary data formats.
virtual bool HasColumn(std::string_view colName) const =0
Checks if the dataset has a certain column.
std::vector< T ** > GetColumnReaders(std::string_view columnName)
Called at most once per column by RDF.
The public interface to the RDataFrame federation of classes.
A "std::vector"-like collection of values implementing handy operation to analyse them.
Definition RVec.hxx:1509
A TTree represents a columnar dataset.
Definition TTree.h:95
std::string PrettyPrintAddr(const void *const addr)
std::unique_ptr< ROOT::Detail::RDF::RColumnReaderBase > CreateColumnReader(ROOT::RDF::RDataSource &ds, unsigned int slot, std::string_view col, const std::type_info &tid, TTreeReader *treeReader)
Definition RDFUtils.cxx:720
unsigned int & NThreadPerTH3()
Obtain or set the number of threads that will share a clone of a thread-safe 3D histogram.
Definition RDFUtils.cxx:88
ROOT type_traits extensions.
Bool_t IsImplicitMTEnabled()
Returns true if the implicit multi-threading in ROOT is enabled.
Definition TROOT.cxx:673
A collection of options to steer the creation of the dataset on disk through Snapshot().
Lightweight storage for a collection of types.