11 #ifndef ROOT_RDF_TINTERFACE
12 #define ROOT_RDF_TINTERFACE
37 #include <initializer_list>
43 #include <type_traits>
51 void DisableImplicitMT();
52 bool IsImplicitMTEnabled();
53 void EnableImplicitMT(UInt_t numthreads);
57 class GraphCreatorHelper;
62 std::string printValue(ROOT::RDataFrame *tdf);
67 namespace RDFDetail = ROOT::Detail::RDF;
68 namespace RDFInternal = ROOT::Internal::RDF;
69 namespace TTraits = ROOT::TypeTraits;
71 template <
typename Proxied,
typename DataSource>
74 using RNode = RInterface<::ROOT::Detail::RDF::RNodeBase, void>;
88 template <
typename Proxied,
typename DataSource =
void>
90 using DS_t = DataSource;
91 using ColumnNames_t = RDFDetail::ColumnNames_t;
92 using RFilterBase = RDFDetail::RFilterBase;
93 using RRangeBase = RDFDetail::RRangeBase;
94 using RLoopManager = RDFDetail::RLoopManager;
95 friend std::string cling::printValue(::ROOT::RDataFrame *tdf);
96 friend class RDFInternal::GraphDrawing::GraphCreatorHelper;
98 template <
typename T,
typename W>
99 friend class RInterface;
101 std::shared_ptr<Proxied> fProxiedPtr;
103 RLoopManager *fLoopManager;
105 RDataSource *fDataSource =
nullptr;
108 RDFInternal::RBookedCustomColumns fCustomColumns;
113 RInterface &operator=(
const RInterface &) =
default;
117 RInterface(
const RInterface &) =
default;
121 RInterface(RInterface &&) =
default;
125 template <typename T = Proxied, typename std::enable_if<std::is_same<T, RLoopManager>::value,
int>::type = 0>
126 RInterface(
const std::shared_ptr<Proxied> &proxied)
127 : fProxiedPtr(proxied), fLoopManager(proxied.get()), fDataSource(proxied->GetDataSource())
150 operator RNode()
const
152 return RNode(std::static_pointer_cast<::ROOT::Detail::RDF::RNodeBase>(fProxiedPtr), *fLoopManager, fCustomColumns,
185 template <typename F, typename std::enable_if<!std::is_convertible<F, std::string>::value,
int>::type = 0>
186 RInterface<RDFDetail::RFilter<F, Proxied>, DS_t>
187 Filter(F f,
const ColumnNames_t &columns = {}, std::string_view name =
"")
189 RDFInternal::CheckFilter(f);
190 using ColTypes_t =
typename TTraits::CallableTraits<F>::arg_types;
191 constexpr
auto nColumns = ColTypes_t::list_size;
192 const auto validColumnNames = GetValidatedColumnNames(nColumns, columns);
193 const auto newColumns =
194 CheckAndFillDSColumns(validColumnNames, std::make_index_sequence<nColumns>(), ColTypes_t());
196 using F_t = RDFDetail::RFilter<F, Proxied>;
198 auto filterPtr = std::make_shared<F_t>(std::move(f), validColumnNames, fProxiedPtr, newColumns, name);
199 fLoopManager->Book(filterPtr.get());
200 return RInterface<F_t, DS_t>(std::move(filterPtr), *fLoopManager, newColumns, fDataSource);
211 template <typename F, typename std::enable_if<!std::is_convertible<F, std::string>::value,
int>::type = 0>
212 RInterface<RDFDetail::RFilter<F, Proxied>, DS_t> Filter(F f, std::string_view name)
216 return Filter(f, {}, name);
227 template <
typename F>
228 RInterface<RDFDetail::RFilter<F, Proxied>, DS_t> Filter(F f,
const std::initializer_list<std::string> &columns)
230 return Filter(f, ColumnNames_t{columns});
248 RInterface<RDFDetail::RJittedFilter, DS_t> Filter(std::string_view expression, std::string_view name =
"")
251 auto upcastNodeOnHeap = RDFInternal::MakeSharedOnHeap(RDFInternal::UpcastNode(fProxiedPtr));
252 using BaseNodeType_t =
typename std::remove_pointer<decltype(upcastNodeOnHeap)>::type::element_type;
253 RInterface<BaseNodeType_t> upcastInterface(*upcastNodeOnHeap, *fLoopManager, fCustomColumns, fDataSource);
254 const auto jittedFilter = std::make_shared<RDFDetail::RJittedFilter>(fLoopManager, name);
256 RDFInternal::BookFilterJit(jittedFilter.get(), upcastNodeOnHeap, name, expression, fLoopManager->GetAliasMap(),
257 fLoopManager->GetBranchNames(), fCustomColumns, fLoopManager->GetTree(), fDataSource,
258 fLoopManager->GetID());
260 fLoopManager->Book(jittedFilter.get());
261 return RInterface<RDFDetail::RJittedFilter, DS_t>(std::move(jittedFilter), *fLoopManager, fCustomColumns,
294 template <typename F, typename std::enable_if<!std::is_convertible<F, std::string>::value,
int>::type = 0>
295 RInterface<Proxied, DS_t> Define(std::string_view name, F expression,
const ColumnNames_t &columns = {})
297 return DefineImpl<F, RDFDetail::CustomColExtraArgs::None>(name, std::move(expression), columns);
323 template <
typename F>
324 RInterface<Proxied, DS_t> DefineSlot(std::string_view name, F expression,
const ColumnNames_t &columns = {})
326 return DefineImpl<F, RDFDetail::CustomColExtraArgs::Slot>(name, std::move(expression), columns);
353 template <
typename F>
354 RInterface<Proxied, DS_t> DefineSlotEntry(std::string_view name, F expression,
const ColumnNames_t &columns = {})
356 return DefineImpl<F, RDFDetail::CustomColExtraArgs::SlotAndEntry>(name, std::move(expression), columns);
371 RInterface<Proxied, DS_t> Define(std::string_view name, std::string_view expression)
374 RDFInternal::CheckCustomColumn(name, fLoopManager->GetTree(), fCustomColumns.GetNames(),
375 fLoopManager->GetAliasMap(),
376 fDataSource ? fDataSource->GetColumnNames() : ColumnNames_t{});
378 auto jittedCustomColumn =
379 std::make_shared<RDFDetail::RJittedCustomColumn>(fLoopManager, name, fLoopManager->GetNSlots());
381 RDFInternal::BookDefineJit(name, expression, *fLoopManager, fDataSource, jittedCustomColumn, fCustomColumns,
382 fLoopManager->GetBranchNames());
384 RDFInternal::RBookedCustomColumns newCols(fCustomColumns);
385 newCols.AddName(name);
386 newCols.AddColumn(jittedCustomColumn, name);
388 fLoopManager->RegisterCustomColumn(jittedCustomColumn.get());
390 RInterface<Proxied, DS_t> newInterface(fProxiedPtr, *fLoopManager, std::move(newCols), fDataSource);
407 RInterface<Proxied, DS_t> Alias(std::string_view alias, std::string_view columnName)
414 auto &dsColumnNames = fDataSource ? fDataSource->GetColumnNames() : ColumnNames_t{};
417 RDFInternal::CheckCustomColumn(alias, fLoopManager->GetTree(), fCustomColumns.GetNames(),
418 fLoopManager->GetAliasMap(), dsColumnNames);
420 const auto validColumnName = GetValidatedColumnNames(1, {std::string(columnName)})[0];
422 fLoopManager->AddColumnAlias(std::string(alias), validColumnName);
424 RDFInternal::RBookedCustomColumns newCols(fCustomColumns);
426 newCols.AddName(alias);
427 RInterface<Proxied, DS_t> newInterface(fProxiedPtr, *fLoopManager, std::move(newCols), fDataSource);
463 template <
typename... ColumnTypes>
464 RResultPtr<RInterface<RLoopManager>>
465 Snapshot(std::string_view treename, std::string_view filename,
const ColumnNames_t &columnList,
466 const RSnapshotOptions &options = RSnapshotOptions())
468 return SnapshotImpl<ColumnTypes...>(treename, filename, columnList, options);
483 RResultPtr<RInterface<RLoopManager>> Snapshot(std::string_view treename, std::string_view filename,
484 const ColumnNames_t &columnList,
485 const RSnapshotOptions &options = RSnapshotOptions())
489 if (columnList.empty()) {
490 auto nEntries = *this->Count();
491 auto snapshotRDF = std::make_shared<RInterface<RLoopManager>>(std::make_shared<RLoopManager>(nEntries));
492 return MakeResultPtr(snapshotRDF, *fLoopManager,
nullptr);
494 auto tree = fLoopManager->GetTree();
495 const auto nsID = fLoopManager->GetID();
496 std::stringstream snapCall;
497 auto upcastNode = RDFInternal::UpcastNode(fProxiedPtr);
498 RInterface<TTraits::TakeFirstParameter_t<decltype(upcastNode)>> upcastInterface(fProxiedPtr, *fLoopManager,
499 fCustomColumns, fDataSource);
503 RResultPtr<RInterface<RLoopManager>> resPtr;
504 snapCall <<
"*reinterpret_cast<ROOT::RDF::RResultPtr<ROOT::RDF::RInterface<ROOT::Detail::RDF::RLoopManager>>*>("
505 << RDFInternal::PrettyPrintAddr(&resPtr)
506 <<
") = reinterpret_cast<ROOT::RDF::RInterface<ROOT::Detail::RDF::RNodeBase>*>("
507 << RDFInternal::PrettyPrintAddr(&upcastInterface) <<
")->Snapshot<";
509 const auto &customCols = fCustomColumns.GetNames();
510 const auto dontConvertVector =
false;
512 const auto validColumnNames = GetValidatedColumnNames(columnList.size(), columnList);
514 for (
auto &c : validColumnNames) {
515 const auto isCustom = std::find(customCols.begin(), customCols.end(), c) != customCols.end();
516 const auto customColID = isCustom ? fCustomColumns.GetColumns().at(c)->GetID() : 0;
517 snapCall << RDFInternal::ColumnName2ColumnTypeName(c, nsID, tree, fDataSource, isCustom, dontConvertVector,
521 if (!columnList.empty())
522 snapCall.seekp(-2, snapCall.cur);
523 snapCall <<
">(\"" << treename <<
"\", \"" << filename <<
"\", "
524 <<
"*reinterpret_cast<std::vector<std::string>*>("
525 << RDFInternal::PrettyPrintAddr(&columnList) <<
"),"
526 <<
"*reinterpret_cast<ROOT::RDF::RSnapshotOptions*>(" << RDFInternal::PrettyPrintAddr(&options) <<
"));";
528 fLoopManager->JitDeclarations();
529 RDFInternal::InterpreterCalc(snapCall.str(),
"Snapshot");
546 RResultPtr<RInterface<RLoopManager>> Snapshot(std::string_view treename, std::string_view filename,
547 std::string_view columnNameRegexp =
"",
548 const RSnapshotOptions &options = RSnapshotOptions())
550 auto selectedColumns = RDFInternal::ConvertRegexToColumns(fCustomColumns,
551 fLoopManager->GetTree(),
555 return Snapshot(treename, filename, selectedColumns, options);
572 RResultPtr<RInterface<RLoopManager>> Snapshot(std::string_view treename, std::string_view filename,
573 std::initializer_list<std::string> columnList,
574 const RSnapshotOptions &options = RSnapshotOptions())
576 ColumnNames_t selectedColumns(columnList);
577 return Snapshot(treename, filename, selectedColumns, options);
610 template <
typename... ColumnTypes>
611 RInterface<RLoopManager> Cache(
const ColumnNames_t &columnList)
613 auto staticSeq = std::make_index_sequence<
sizeof...(ColumnTypes)>();
614 return CacheImpl<ColumnTypes...>(columnList, staticSeq);
623 RInterface<RLoopManager> Cache(
const ColumnNames_t &columnList)
627 if (columnList.empty()) {
628 auto nEntries = *this->Count();
629 RInterface<RLoopManager> emptyRDF(std::make_shared<RLoopManager>(nEntries));
633 auto tree = fLoopManager->GetTree();
634 const auto nsID = fLoopManager->GetID();
635 std::stringstream cacheCall;
636 auto upcastNode = RDFInternal::UpcastNode(fProxiedPtr);
637 RInterface<TTraits::TakeFirstParameter_t<decltype(upcastNode)>> upcastInterface(fProxiedPtr, *fLoopManager,
638 fCustomColumns, fDataSource);
641 RInterface<RLoopManager> resRDF(std::make_shared<ROOT::Detail::RDF::RLoopManager>(0));
642 cacheCall <<
"*reinterpret_cast<ROOT::RDF::RInterface<ROOT::Detail::RDF::RLoopManager>*>("
643 << RDFInternal::PrettyPrintAddr(&resRDF)
644 <<
") = reinterpret_cast<ROOT::RDF::RInterface<ROOT::Detail::RDF::RNodeBase>*>("
645 << RDFInternal::PrettyPrintAddr(&upcastInterface) <<
")->Cache<";
647 const auto &customCols = fCustomColumns.GetNames();
648 for (
auto &c : columnList) {
649 const auto isCustom = std::find(customCols.begin(), customCols.end(), c) != customCols.end();
650 const auto customColID = isCustom ? fCustomColumns.GetColumns().at(c)->GetID() : 0;
651 cacheCall << RDFInternal::ColumnName2ColumnTypeName(c, nsID, tree, fDataSource, isCustom,
655 if (!columnList.empty())
656 cacheCall.seekp(-2, cacheCall.cur);
657 cacheCall <<
">(*reinterpret_cast<std::vector<std::string>*>("
658 << RDFInternal::PrettyPrintAddr(&columnList) <<
"));";
660 fLoopManager->JitDeclarations();
661 RDFInternal::InterpreterCalc(cacheCall.str(),
"Cache");
672 RInterface<RLoopManager> Cache(std::string_view columnNameRegexp =
"")
675 auto selectedColumns = RDFInternal::ConvertRegexToColumns(fCustomColumns, fLoopManager->GetTree(), fDataSource,
676 columnNameRegexp,
"Cache");
677 return Cache(selectedColumns);
686 RInterface<RLoopManager> Cache(std::initializer_list<std::string> columnList)
688 ColumnNames_t selectedColumns(columnList);
689 return Cache(selectedColumns);
710 RInterface<RDFDetail::RRange<Proxied>, DS_t> Range(
unsigned int begin,
unsigned int end,
unsigned int stride = 1)
713 if (stride == 0 || (end != 0 && end < begin))
714 throw std::runtime_error(
"Range: stride must be strictly greater than 0 and end must be greater than begin.");
715 CheckIMTDisabled(
"Range");
717 using Range_t = RDFDetail::RRange<Proxied>;
718 auto rangePtr = std::make_shared<Range_t>(begin, end, stride, fProxiedPtr);
719 fLoopManager->Book(rangePtr.get());
720 RInterface<RDFDetail::RRange<Proxied>> tdf_r(std::move(rangePtr), *fLoopManager, fCustomColumns, fDataSource);
732 RInterface<RDFDetail::RRange<Proxied>, DS_t> Range(
unsigned int end) {
return Range(0, end, 1); }
751 template <
typename F>
752 void Foreach(F f,
const ColumnNames_t &columns = {})
754 using arg_types =
typename TTraits::CallableTraits<decltype(f)>::arg_types_nodecay;
755 using ret_type =
typename TTraits::CallableTraits<decltype(f)>::ret_type;
756 ForeachSlot(RDFInternal::AddSlotParameter<ret_type>(f, arg_types()), columns);
781 template <
typename F>
782 void ForeachSlot(F f,
const ColumnNames_t &columns = {})
784 using ColTypes_t = TypeTraits::RemoveFirstParameter_t<typename TTraits::CallableTraits<F>::arg_types>;
785 constexpr
auto nColumns = ColTypes_t::list_size;
787 const auto validColumnNames = GetValidatedColumnNames(nColumns, columns);
789 auto newColumns = CheckAndFillDSColumns(validColumnNames, std::make_index_sequence<nColumns>(), ColTypes_t());
791 using Helper_t = RDFInternal::ForeachSlotHelper<F>;
792 using Action_t = RDFInternal::RAction<Helper_t, Proxied>;
795 std::make_unique<Action_t>(Helper_t(std::move(f)), validColumnNames, fProxiedPtr, std::move(newColumns));
796 fLoopManager->Book(action.get());
831 template <typename F, typename T = typename TTraits::CallableTraits<F>::ret_type>
832 RResultPtr<T> Reduce(F f, std::string_view columnName =
"")
835 std::is_default_constructible<T>::value,
836 "reduce object cannot be default-constructed. Please provide an initialisation value (redIdentity)");
837 return Reduce(std::move(f), columnName, T());
854 template <typename F, typename T = typename TTraits::CallableTraits<F>::ret_type>
855 RResultPtr<T> Reduce(F f, std::string_view columnName,
const T &redIdentity)
857 return Aggregate(f, f, columnName, redIdentity);
873 RResultPtr<ULong64_t> Count()
875 const auto nSlots = fLoopManager->GetNSlots();
876 auto cSPtr = std::make_shared<ULong64_t>(0);
877 using Helper_t = RDFInternal::CountHelper;
878 using Action_t = RDFInternal::RAction<Helper_t, Proxied>;
880 std::make_unique<Action_t>(Helper_t(cSPtr, nSlots), ColumnNames_t({}), fProxiedPtr, std::move(fCustomColumns));
881 fLoopManager->Book(action.get());
882 return MakeResultPtr(cSPtr, *fLoopManager, std::move(action));
905 template <
typename T,
typename COLL = std::vector<T>>
906 RResultPtr<COLL> Take(std::string_view column =
"")
908 const auto columns = column.empty() ? ColumnNames_t() : ColumnNames_t({std::string(column)});
910 const auto validColumnNames = GetValidatedColumnNames(1, columns);
912 auto newColumns = CheckAndFillDSColumns(validColumnNames, std::make_index_sequence<1>(), TTraits::TypeList<T>());
914 using Helper_t = RDFInternal::TakeHelper<T, T, COLL>;
915 using Action_t = RDFInternal::RAction<Helper_t, Proxied>;
916 auto valuesPtr = std::make_shared<COLL>();
917 const auto nSlots = fLoopManager->GetNSlots();
920 std::make_unique<Action_t>(Helper_t(valuesPtr, nSlots), validColumnNames, fProxiedPtr, std::move(newColumns));
921 fLoopManager->Book(action.get());
922 return MakeResultPtr(valuesPtr, *fLoopManager, std::move(action));
947 template <
typename V = RDFDetail::RInferredType>
948 RResultPtr<::TH1D> Histo1D(
const TH1DModel &model = {
"",
"", 128u, 0., 0.}, std::string_view vName =
"")
950 const auto userColumns = vName.empty() ? ColumnNames_t() : ColumnNames_t({std::string(vName)});
952 const auto validatedColumns = GetValidatedColumnNames(1, userColumns);
954 std::shared_ptr<::TH1D> h(
nullptr);
956 ROOT::Internal::RDF::RIgnoreErrorLevelRAII iel(kError);
957 h = model.GetHistogram();
958 h->SetDirectory(
nullptr);
961 if (h->GetXaxis()->GetXmax() == h->GetXaxis()->GetXmin())
962 RDFInternal::HistoUtils<::TH1D>::SetCanExtendAllAxes(*h);
963 return CreateAction<RDFInternal::ActionTags::Histo1D, V>(validatedColumns, h);
984 template <
typename V = RDFDetail::RInferredType>
985 RResultPtr<::TH1D> Histo1D(std::string_view vName)
987 const auto h_name = std::string(vName);
988 const auto h_title = h_name +
";" + h_name +
";count";
989 return Histo1D<V>({h_name.c_str(), h_title.c_str(), 128u, 0., 0.}, vName);
1011 template <
typename V = RDFDetail::RInferredType,
typename W = RDFDetail::RInferredType>
1012 RResultPtr<::TH1D> Histo1D(
const TH1DModel &model, std::string_view vName, std::string_view wName)
1014 const std::vector<std::string_view> columnViews = {vName, wName};
1015 const auto userColumns = RDFInternal::AtLeastOneEmptyString(columnViews)
1017 : ColumnNames_t(columnViews.begin(), columnViews.end());
1018 std::shared_ptr<::TH1D> h(
nullptr);
1020 ROOT::Internal::RDF::RIgnoreErrorLevelRAII iel(kError);
1021 h = model.GetHistogram();
1023 return CreateAction<RDFInternal::ActionTags::Histo1D, V, W>(userColumns, h);
1046 template <
typename V = RDFDetail::RInferredType,
typename W = RDFDetail::RInferredType>
1047 RResultPtr<::TH1D> Histo1D(std::string_view vName, std::string_view wName)
1050 std::string str_vName{vName};
1051 std::string str_wName{wName};
1052 const auto h_name = str_vName +
"_weighted_" + str_wName;
1053 const auto h_title = str_vName +
", weights: " + str_wName +
";" + str_vName +
";count * " + str_wName;
1054 return Histo1D<V, W>({h_name.c_str(), h_title.c_str(), 128u, 0., 0.}, vName, wName);
1066 template <
typename V,
typename W>
1067 RResultPtr<::TH1D> Histo1D(
const TH1DModel &model = {
"",
"", 128u, 0., 0.})
1069 return Histo1D<V, W>(model,
"",
"");
1096 template <
typename V1 = RDFDetail::RInferredType,
typename V2 = RDFDetail::RInferredType>
1097 RResultPtr<::TH2D> Histo2D(
const TH2DModel &model, std::string_view v1Name =
"", std::string_view v2Name =
"")
1099 std::shared_ptr<::TH2D> h(
nullptr);
1101 ROOT::Internal::RDF::RIgnoreErrorLevelRAII iel(kError);
1102 h = model.GetHistogram();
1104 if (!RDFInternal::HistoUtils<::TH2D>::HasAxisLimits(*h)) {
1105 throw std::runtime_error(
"2D histograms with no axes limits are not supported yet.");
1107 const std::vector<std::string_view> columnViews = {v1Name, v2Name};
1108 const auto userColumns = RDFInternal::AtLeastOneEmptyString(columnViews)
1110 : ColumnNames_t(columnViews.begin(), columnViews.end());
1111 return CreateAction<RDFInternal::ActionTags::Histo2D, V1, V2>(userColumns, h);
1137 template <
typename V1 = RDFDetail::RInferredType,
typename V2 = RDFDetail::RInferredType,
1138 typename W = RDFDetail::RInferredType>
1140 Histo2D(
const TH2DModel &model, std::string_view v1Name, std::string_view v2Name, std::string_view wName)
1142 std::shared_ptr<::TH2D> h(
nullptr);
1144 ROOT::Internal::RDF::RIgnoreErrorLevelRAII iel(kError);
1145 h = model.GetHistogram();
1147 if (!RDFInternal::HistoUtils<::TH2D>::HasAxisLimits(*h)) {
1148 throw std::runtime_error(
"2D histograms with no axes limits are not supported yet.");
1150 const std::vector<std::string_view> columnViews = {v1Name, v2Name, wName};
1151 const auto userColumns = RDFInternal::AtLeastOneEmptyString(columnViews)
1153 : ColumnNames_t(columnViews.begin(), columnViews.end());
1154 return CreateAction<RDFInternal::ActionTags::Histo2D, V1, V2, W>(userColumns, h);
1157 template <
typename V1,
typename V2,
typename W>
1158 RResultPtr<::TH2D> Histo2D(
const TH2DModel &model)
1160 return Histo2D<V1, V2, W>(model,
"",
"",
"");
1187 template <
typename V1 = RDFDetail::RInferredType,
typename V2 = RDFDetail::RInferredType,
1188 typename V3 = RDFDetail::RInferredType>
1189 RResultPtr<::TH3D> Histo3D(
const TH3DModel &model, std::string_view v1Name =
"", std::string_view v2Name =
"",
1190 std::string_view v3Name =
"")
1192 std::shared_ptr<::TH3D> h(
nullptr);
1194 ROOT::Internal::RDF::RIgnoreErrorLevelRAII iel(kError);
1195 h = model.GetHistogram();
1197 if (!RDFInternal::HistoUtils<::TH3D>::HasAxisLimits(*h)) {
1198 throw std::runtime_error(
"3D histograms with no axes limits are not supported yet.");
1200 const std::vector<std::string_view> columnViews = {v1Name, v2Name, v3Name};
1201 const auto userColumns = RDFInternal::AtLeastOneEmptyString(columnViews)
1203 : ColumnNames_t(columnViews.begin(), columnViews.end());
1204 return CreateAction<RDFInternal::ActionTags::Histo3D, V1, V2, V3>(userColumns, h);
1234 template <
typename V1 = RDFDetail::RInferredType,
typename V2 = RDFDetail::RInferredType,
1235 typename V3 = RDFDetail::RInferredType,
typename W = RDFDetail::RInferredType>
1236 RResultPtr<::TH3D> Histo3D(
const TH3DModel &model, std::string_view v1Name, std::string_view v2Name,
1237 std::string_view v3Name, std::string_view wName)
1239 std::shared_ptr<::TH3D> h(
nullptr);
1241 ROOT::Internal::RDF::RIgnoreErrorLevelRAII iel(kError);
1242 h = model.GetHistogram();
1244 if (!RDFInternal::HistoUtils<::TH3D>::HasAxisLimits(*h)) {
1245 throw std::runtime_error(
"3D histograms with no axes limits are not supported yet.");
1247 const std::vector<std::string_view> columnViews = {v1Name, v2Name, v3Name, wName};
1248 const auto userColumns = RDFInternal::AtLeastOneEmptyString(columnViews)
1250 : ColumnNames_t(columnViews.begin(), columnViews.end());
1251 return CreateAction<RDFInternal::ActionTags::Histo3D, V1, V2, V3, W>(userColumns, h);
1254 template <
typename V1,
typename V2,
typename V3,
typename W>
1255 RResultPtr<::TH3D> Histo3D(
const TH3DModel &model)
1257 return Histo3D<V1, V2, V3, W>(model,
"",
"",
"",
"");
1285 template <
typename V1 = RDFDetail::RInferredType,
typename V2 = RDFDetail::RInferredType>
1286 RResultPtr<::TGraph> Graph(std::string_view v1Name =
"", std::string_view v2Name =
"")
1288 auto graph = std::make_shared<::TGraph>();
1289 const std::vector<std::string_view> columnViews = {v1Name, v2Name};
1290 const auto userColumns = RDFInternal::AtLeastOneEmptyString(columnViews)
1292 : ColumnNames_t(columnViews.begin(), columnViews.end());
1294 const auto validatedColumns = GetValidatedColumnNames(2, userColumns);
1297 if (!(validatedColumns[0].empty() && validatedColumns[1].empty())) {
1298 const auto g_name = std::string(v1Name) +
"_vs_" + std::string(v2Name);
1299 const auto g_title = std::string(v1Name) +
" vs " + std::string(v2Name);
1300 graph->SetNameTitle(g_name.c_str(), g_title.c_str());
1301 graph->GetXaxis()->SetTitle(std::string(v1Name).c_str());
1302 graph->GetYaxis()->SetTitle(std::string(v2Name).c_str());
1305 return CreateAction<RDFInternal::ActionTags::Graph, V1, V2>(validatedColumns, graph);
1328 template <
typename V1 = RDFDetail::RInferredType,
typename V2 = RDFDetail::RInferredType>
1329 RResultPtr<::TProfile>
1330 Profile1D(
const TProfile1DModel &model, std::string_view v1Name =
"", std::string_view v2Name =
"")
1332 std::shared_ptr<::TProfile> h(
nullptr);
1334 ROOT::Internal::RDF::RIgnoreErrorLevelRAII iel(kError);
1335 h = model.GetProfile();
1338 if (!RDFInternal::HistoUtils<::TProfile>::HasAxisLimits(*h)) {
1339 throw std::runtime_error(
"Profiles with no axes limits are not supported yet.");
1341 const std::vector<std::string_view> columnViews = {v1Name, v2Name};
1342 const auto userColumns = RDFInternal::AtLeastOneEmptyString(columnViews)
1344 : ColumnNames_t(columnViews.begin(), columnViews.end());
1345 return CreateAction<RDFInternal::ActionTags::Profile1D, V1, V2>(userColumns, h);
1371 template <
typename V1 = RDFDetail::RInferredType,
typename V2 = RDFDetail::RInferredType,
1372 typename W = RDFDetail::RInferredType>
1373 RResultPtr<::TProfile>
1374 Profile1D(
const TProfile1DModel &model, std::string_view v1Name, std::string_view v2Name, std::string_view wName)
1376 std::shared_ptr<::TProfile> h(
nullptr);
1378 ROOT::Internal::RDF::RIgnoreErrorLevelRAII iel(kError);
1379 h = model.GetProfile();
1382 if (!RDFInternal::HistoUtils<::TProfile>::HasAxisLimits(*h)) {
1383 throw std::runtime_error(
"Profile histograms with no axes limits are not supported yet.");
1385 const std::vector<std::string_view> columnViews = {v1Name, v2Name, wName};
1386 const auto userColumns = RDFInternal::AtLeastOneEmptyString(columnViews)
1388 : ColumnNames_t(columnViews.begin(), columnViews.end());
1389 return CreateAction<RDFInternal::ActionTags::Profile1D, V1, V2, W>(userColumns, h);
1392 template <
typename V1,
typename V2,
typename W>
1393 RResultPtr<::TProfile> Profile1D(
const TProfile1DModel &model)
1395 return Profile1D<V1, V2, W>(model,
"",
"",
"");
1422 template <
typename V1 = RDFDetail::RInferredType,
typename V2 = RDFDetail::RInferredType,
1423 typename V3 = RDFDetail::RInferredType>
1424 RResultPtr<::TProfile2D> Profile2D(
const TProfile2DModel &model, std::string_view v1Name =
"",
1425 std::string_view v2Name =
"", std::string_view v3Name =
"")
1427 std::shared_ptr<::TProfile2D> h(
nullptr);
1429 ROOT::Internal::RDF::RIgnoreErrorLevelRAII iel(kError);
1430 h = model.GetProfile();
1433 if (!RDFInternal::HistoUtils<::TProfile2D>::HasAxisLimits(*h)) {
1434 throw std::runtime_error(
"2D profiles with no axes limits are not supported yet.");
1436 const std::vector<std::string_view> columnViews = {v1Name, v2Name, v3Name};
1437 const auto userColumns = RDFInternal::AtLeastOneEmptyString(columnViews)
1439 : ColumnNames_t(columnViews.begin(), columnViews.end());
1440 return CreateAction<RDFInternal::ActionTags::Profile2D, V1, V2, V3>(userColumns, h);
1469 template <
typename V1 = RDFDetail::RInferredType,
typename V2 = RDFDetail::RInferredType,
1470 typename V3 = RDFDetail::RInferredType,
typename W = RDFDetail::RInferredType>
1471 RResultPtr<::TProfile2D> Profile2D(
const TProfile2DModel &model, std::string_view v1Name, std::string_view v2Name,
1472 std::string_view v3Name, std::string_view wName)
1474 std::shared_ptr<::TProfile2D> h(
nullptr);
1476 ROOT::Internal::RDF::RIgnoreErrorLevelRAII iel(kError);
1477 h = model.GetProfile();
1480 if (!RDFInternal::HistoUtils<::TProfile2D>::HasAxisLimits(*h)) {
1481 throw std::runtime_error(
"2D profiles with no axes limits are not supported yet.");
1483 const std::vector<std::string_view> columnViews = {v1Name, v2Name, v3Name, wName};
1484 const auto userColumns = RDFInternal::AtLeastOneEmptyString(columnViews)
1486 : ColumnNames_t(columnViews.begin(), columnViews.end());
1487 return CreateAction<RDFInternal::ActionTags::Profile2D, V1, V2, V3, W>(userColumns, h);
1490 template <
typename V1,
typename V2,
typename V3,
typename W>
1491 RResultPtr<::TProfile2D> Profile2D(
const TProfile2DModel &model)
1493 return Profile2D<V1, V2, V3, W>(model,
"",
"",
"",
"");
1520 template <
typename FirstColumn,
typename... OtherColumns,
typename T>
1521 RResultPtr<T> Fill(T &&model,
const ColumnNames_t &columnList)
1523 auto h = std::make_shared<T>(std::forward<T>(model));
1524 if (!RDFInternal::HistoUtils<T>::HasAxisLimits(*h)) {
1525 throw std::runtime_error(
"The absence of axes limits is not supported yet.");
1527 return CreateAction<RDFInternal::ActionTags::Fill, FirstColumn, OtherColumns...>(columnList, h);
1549 template <
typename T>
1550 RResultPtr<T> Fill(T &&model,
const ColumnNames_t &bl)
1552 auto h = std::make_shared<T>(std::forward<T>(model));
1553 if (!RDFInternal::HistoUtils<T>::HasAxisLimits(*h)) {
1554 throw std::runtime_error(
"The absence of axes limits is not supported yet.");
1556 return CreateAction<RDFInternal::ActionTags::Fill, RDFDetail::RInferredType>(bl, h, bl.size());
1574 template<
typename V = RDFDetail::RInferredType>
1575 RResultPtr<TStatistic> Stats(std::string_view value =
"")
1577 ColumnNames_t columns;
1578 if (!value.empty()) {
1579 columns.emplace_back(std::string(value));
1581 const auto validColumnNames = GetValidatedColumnNames(1, columns);
1582 if (std::is_same<V, RDFDetail::RInferredType>::value) {
1583 return Fill(TStatistic(), validColumnNames);
1586 return Fill<V>(TStatistic(), validColumnNames);
1607 template<
typename V = RDFDetail::RInferredType,
typename W = RDFDetail::RInferredType>
1608 RResultPtr<TStatistic> Stats(std::string_view value, std::string_view weight)
1610 ColumnNames_t columns {std::string(value), std::string(weight)};
1611 constexpr
auto vIsInferred = std::is_same<V, RDFDetail::RInferredType>::value;
1612 constexpr
auto wIsInferred = std::is_same<W, RDFDetail::RInferredType>::value;
1613 const auto validColumnNames = GetValidatedColumnNames(2, columns);
1618 if (vIsInferred && wIsInferred) {
1619 return Fill(TStatistic(), validColumnNames);
1620 }
else if (vIsInferred != wIsInferred) {
1621 std::string error(
"The ");
1622 error += vIsInferred ?
"value " :
"weight ";
1623 error +=
"column type is explicit, while the ";
1624 error += vIsInferred ?
"weight " :
"value ";
1625 error +=
" is specified to be inferred. This case is not supported: please specify both types or none.";
1626 throw std::runtime_error(error);
1628 return Fill<V, W>(TStatistic(), validColumnNames);
1653 template <
typename T = RDFDetail::RInferredType>
1654 RResultPtr<RDFDetail::MinReturnType_t<T>> Min(std::string_view columnName =
"")
1656 const auto userColumns = columnName.empty() ? ColumnNames_t() : ColumnNames_t({std::string(columnName)});
1657 using RetType_t = RDFDetail::MinReturnType_t<T>;
1658 auto minV = std::make_shared<RetType_t>(std::numeric_limits<RetType_t>::max());
1659 return CreateAction<RDFInternal::ActionTags::Min, T>(userColumns, minV);
1683 template <
typename T = RDFDetail::RInferredType>
1684 RResultPtr<RDFDetail::MaxReturnType_t<T>> Max(std::string_view columnName =
"")
1686 const auto userColumns = columnName.empty() ? ColumnNames_t() : ColumnNames_t({std::string(columnName)});
1687 using RetType_t = RDFDetail::MaxReturnType_t<T>;
1688 auto maxV = std::make_shared<RetType_t>(std::numeric_limits<RetType_t>::lowest());
1689 return CreateAction<RDFInternal::ActionTags::Max, T>(userColumns, maxV);
1712 template <
typename T = RDFDetail::RInferredType>
1713 RResultPtr<double> Mean(std::string_view columnName =
"")
1715 const auto userColumns = columnName.empty() ? ColumnNames_t() : ColumnNames_t({std::string(columnName)});
1716 auto meanV = std::make_shared<double>(0);
1717 return CreateAction<RDFInternal::ActionTags::Mean, T>(userColumns, meanV);
1740 template <
typename T = RDFDetail::RInferredType>
1741 RResultPtr<double> StdDev(std::string_view columnName =
"")
1743 const auto userColumns = columnName.empty() ? ColumnNames_t() : ColumnNames_t({std::string(columnName)});
1744 auto stdDeviationV = std::make_shared<double>(0);
1745 return CreateAction<RDFInternal::ActionTags::StdDev, T>(userColumns, stdDeviationV);
1771 template <
typename T = RDFDetail::RInferredType>
1772 RResultPtr<RDFDetail::SumReturnType_t<T>>
1773 Sum(std::string_view columnName =
"",
1774 const RDFDetail::SumReturnType_t<T> &initValue = RDFDetail::SumReturnType_t<T>{})
1776 const auto userColumns = columnName.empty() ? ColumnNames_t() : ColumnNames_t({std::string(columnName)});
1777 auto sumV = std::make_shared<RDFDetail::SumReturnType_t<T>>(initValue);
1778 return CreateAction<RDFInternal::ActionTags::Sum, T>(userColumns, sumV);
1806 RResultPtr<RCutFlowReport> Report()
1808 bool returnEmptyReport =
false;
1814 if (std::is_same<Proxied, RLoopManager>::value && fCustomColumns.GetNames().size() > 4)
1815 returnEmptyReport =
true;
1817 auto rep = std::make_shared<RCutFlowReport>();
1818 using Helper_t = RDFInternal::ReportHelper<Proxied>;
1819 using Action_t = RDFInternal::RAction<Helper_t, Proxied>;
1821 auto action = std::make_unique<Action_t>(Helper_t(rep, fProxiedPtr, returnEmptyReport), ColumnNames_t({}),
1822 fProxiedPtr, RDFInternal::RBookedCustomColumns(fCustomColumns));
1824 fLoopManager->Book(action.get());
1825 return MakeResultPtr(rep, *fLoopManager, std::move(action));
1841 ColumnNames_t GetColumnNames()
1843 ColumnNames_t allColumns;
1845 auto addIfNotInternal = [&allColumns](std::string_view colName) {
1846 if (!RDFInternal::IsInternalColumn(colName))
1847 allColumns.emplace_back(colName);
1850 auto columnNames = fCustomColumns.GetNames();
1852 std::for_each(columnNames.begin(), columnNames.end(), addIfNotInternal);
1854 auto tree = fLoopManager->GetTree();
1856 auto branchNames = RDFInternal::GetBranchNames(*tree,
false);
1857 allColumns.insert(allColumns.end(), branchNames.begin(), branchNames.end());
1861 auto &dsColNames = fDataSource->GetColumnNames();
1862 allColumns.insert(allColumns.end(), dsColNames.begin(), dsColNames.end());
1881 std::string GetColumnType(std::string_view column)
1883 const auto &customCols = fCustomColumns.GetNames();
1884 const bool convertVector2RVec =
true;
1885 const auto isCustom = std::find(customCols.begin(), customCols.end(), column) != customCols.end();
1887 return RDFInternal::ColumnName2ColumnTypeName(std::string(column), fLoopManager->GetID(),
1888 fLoopManager->GetTree(), fLoopManager->GetDataSource(), isCustom,
1889 convertVector2RVec);
1892 const auto colID = std::to_string(fCustomColumns.GetColumns().at(std::string(column))->GetID());
1893 const auto call =
"ROOT::Internal::RDF::TypeID2TypeName(typeid(__rdf" + std::to_string(fLoopManager->GetID()) +
1894 "::" + std::string(column) + colID +
"_type))";
1895 fLoopManager->JitDeclarations();
1896 const auto calcRes = RDFInternal::InterpreterCalc(call);
1897 return *
reinterpret_cast<std::string *
>(calcRes);
1915 std::vector<std::string> GetFilterNames() {
return RDFInternal::GetFilterNames(fProxiedPtr); }
1932 ColumnNames_t GetDefinedColumnNames()
1934 ColumnNames_t definedColumns;
1936 auto columns = fCustomColumns.GetColumns();
1938 for (
auto column : columns) {
1939 if (!RDFInternal::IsInternalColumn(column.first) && !column.second->IsDataSourceColumn())
1940 definedColumns.emplace_back(column.first);
1943 return definedColumns;
1960 bool HasColumn(std::string_view columnName)
1962 if (fCustomColumns.HasName(columnName))
1965 if (
auto tree = fLoopManager->GetTree()) {
1966 const auto &branchNames = fLoopManager->GetBranchNames();
1967 const auto branchNamesEnd = branchNames.end();
1968 if (branchNamesEnd != std::find(branchNames.begin(), branchNamesEnd, columnName))
1972 if (fDataSource && fDataSource->HasColumn(columnName))
1990 unsigned int GetNSlots()
const {
return fLoopManager->GetNSlots(); }
2037 template <typename AccFun, typename MergeFun, typename R = typename TTraits::CallableTraits<AccFun>::ret_type,
2038 typename ArgTypes =
typename TTraits::CallableTraits<AccFun>::arg_types,
2039 typename ArgTypesNoDecay =
typename TTraits::CallableTraits<AccFun>::arg_types_nodecay,
2040 typename U = TTraits::TakeFirstParameter_t<ArgTypes>,
2041 typename T = TTraits::TakeFirstParameter_t<TTraits::RemoveFirstParameter_t<ArgTypes>>>
2042 RResultPtr<U> Aggregate(AccFun aggregator, MergeFun merger, std::string_view columnName,
const U &aggIdentity)
2044 RDFInternal::CheckAggregate<R, MergeFun>(ArgTypesNoDecay());
2045 const auto columns = columnName.empty() ? ColumnNames_t() : ColumnNames_t({std::string(columnName)});
2046 constexpr
auto nColumns = ArgTypes::list_size;
2048 const auto validColumnNames = GetValidatedColumnNames(1, columns);
2050 auto newColumns = CheckAndFillDSColumns(validColumnNames, std::make_index_sequence<nColumns>(), ArgTypes());
2052 auto accObjPtr = std::make_shared<U>(aggIdentity);
2053 using Helper_t = RDFInternal::AggregateHelper<AccFun, MergeFun, R, T, U>;
2054 using Action_t =
typename RDFInternal::RAction<Helper_t, Proxied>;
2055 auto action = std::make_unique<Action_t>(
2056 Helper_t(std::move(aggregator), std::move(merger), accObjPtr, fLoopManager->GetNSlots()), validColumnNames,
2057 fProxiedPtr, std::move(newColumns));
2058 fLoopManager->Book(action.get());
2059 return MakeResultPtr(accObjPtr, *fLoopManager, std::move(action));
2075 template <typename AccFun, typename MergeFun, typename R = typename TTraits::CallableTraits<AccFun>::ret_type,
2076 typename ArgTypes =
typename TTraits::CallableTraits<AccFun>::arg_types,
2077 typename U = TTraits::TakeFirstParameter_t<ArgTypes>,
2078 typename T = TTraits::TakeFirstParameter_t<TTraits::RemoveFirstParameter_t<ArgTypes>>>
2079 RResultPtr<U> Aggregate(AccFun aggregator, MergeFun merger, std::string_view columnName =
"")
2082 std::is_default_constructible<U>::value,
2083 "aggregated object cannot be default-constructed. Please provide an initialisation value (aggIdentity)");
2084 return Aggregate(std::move(aggregator), std::move(merger), columnName, U());
2121 template <
typename... ColumnTypes,
typename Helper>
2122 RResultPtr<typename Helper::Result_t> Book(Helper &&helper,
const ColumnNames_t &columns = {})
2124 constexpr
auto nColumns =
sizeof...(ColumnTypes);
2125 RDFInternal::CheckTypesAndPars(
sizeof...(ColumnTypes), columns.size());
2127 const auto validColumnNames = GetValidatedColumnNames(nColumns, columns);
2130 using AH = RDFDetail::RActionImpl<Helper>;
2131 static_assert(std::is_base_of<AH, Helper>::value && std::is_convertible<Helper *, AH *>::value,
2132 "Action helper of type T must publicly inherit from ROOT::Detail::RDF::RActionImpl<T>");
2134 using Action_t =
typename RDFInternal::RAction<Helper, Proxied, TTraits::TypeList<ColumnTypes...>>;
2135 auto resPtr = helper.GetResultPtr();
2137 auto newColumns = CheckAndFillDSColumns(validColumnNames, std::make_index_sequence<nColumns>(),
2138 RDFInternal::TypeList<ColumnTypes...>());
2140 auto action = std::make_unique<Action_t>(Helper(std::forward<Helper>(helper)), validColumnNames, fProxiedPtr,
2141 RDFInternal::RBookedCustomColumns(newColumns));
2142 fLoopManager->Book(action.get());
2143 return MakeResultPtr(resPtr, *fLoopManager, std::move(action));
2169 template <
typename... ColumnTypes>
2170 RResultPtr<RDisplay> Display(
const ColumnNames_t &columnList,
const int &nRows = 5)
2172 CheckIMTDisabled(
"Display");
2174 auto displayer = std::make_shared<RDFInternal::RDisplay>(columnList, GetColumnTypeNamesList(columnList), nRows);
2175 return CreateAction<RDFInternal::ActionTags::Display, ColumnTypes...>(columnList, displayer);
2186 RResultPtr<RDisplay> Display(
const ColumnNames_t &columnList,
const int &nRows = 5)
2188 CheckIMTDisabled(
"Display");
2189 auto displayer = std::make_shared<RDFInternal::RDisplay>(columnList, GetColumnTypeNamesList(columnList), nRows);
2190 return CreateAction<RDFInternal::ActionTags::Display, RDFDetail::RInferredType>(columnList, displayer,
2203 RResultPtr<RDisplay> Display(std::string_view columnNameRegexp =
"",
const int &nRows = 5)
2205 auto selectedColumns = RDFInternal::ConvertRegexToColumns(fCustomColumns, fLoopManager->GetTree(), fDataSource,
2206 columnNameRegexp,
"Display");
2207 return Display(selectedColumns, nRows);
2217 RResultPtr<RDisplay> Display(std::initializer_list<std::string> columnList,
const int &nRows = 5)
2219 ColumnNames_t selectedColumns(columnList);
2220 return Display(selectedColumns, nRows);
2224 void AddDefaultColumns()
2226 RDFInternal::RBookedCustomColumns newCols;
2229 const auto entryColName =
"rdfentry_";
2230 auto entryColGen = [](
unsigned int, ULong64_t entry) {
return entry; };
2231 using NewColEntry_t =
2232 RDFDetail::RCustomColumn<decltype(entryColGen), RDFDetail::CustomColExtraArgs::SlotAndEntry>;
2234 auto entryColumn = std::make_shared<NewColEntry_t>(fLoopManager, entryColName, std::move(entryColGen),
2235 ColumnNames_t{}, fLoopManager->GetNSlots(), newCols);
2236 newCols.AddName(entryColName);
2237 newCols.AddColumn(entryColumn, entryColName);
2239 fLoopManager->RegisterCustomColumn(entryColumn.get());
2242 auto retTypeDeclaration =
"namespace __rdf" + std::to_string(fLoopManager->GetID()) +
" { using " + entryColName +
2243 std::to_string(entryColumn->GetID()) +
"_type = ULong64_t; }";
2244 fLoopManager->ToJitDeclare(retTypeDeclaration);
2247 const auto slotColName =
"rdfslot_";
2248 auto slotColGen = [](
unsigned int slot) {
return slot; };
2249 using NewColSlot_t = RDFDetail::RCustomColumn<decltype(slotColGen), RDFDetail::CustomColExtraArgs::Slot>;
2251 auto slotColumn = std::make_shared<NewColSlot_t>(fLoopManager, slotColName, std::move(slotColGen),
2252 ColumnNames_t{}, fLoopManager->GetNSlots(), newCols);
2254 newCols.AddName(slotColName);
2255 newCols.AddColumn(slotColumn, slotColName);
2257 fLoopManager->RegisterCustomColumn(slotColumn.get());
2259 fCustomColumns = std::move(newCols);
2262 retTypeDeclaration =
"namespace __rdf" + std::to_string(fLoopManager->GetID()) +
" { using " + slotColName +
2263 std::to_string(slotColumn->GetID()) +
"_type = unsigned int; }";
2264 fLoopManager->ToJitDeclare(retTypeDeclaration);
2266 fLoopManager->AddColumnAlias(
"tdfentry_", entryColName);
2267 fCustomColumns.AddName(
"tdfentry_");
2268 fLoopManager->AddColumnAlias(
"tdfslot_", slotColName);
2269 fCustomColumns.AddName(
"tdfslot_");
2272 std::vector<std::string> GetColumnTypeNamesList(
const ColumnNames_t &columnList)
2274 std::vector<std::string> types;
2276 for (
auto column : columnList) {
2277 types.push_back(GetColumnType(column));
2282 void CheckIMTDisabled(std::string_view callerName)
2284 if (ROOT::IsImplicitMTEnabled()) {
2285 std::string error(callerName);
2286 error +=
" was called with ImplicitMT enabled, but multi-thread is not supported.";
2287 throw std::runtime_error(error);
2292 template <
typename ActionTag,
typename... BranchTypes,
typename ActionResultType,
2293 typename std::enable_if<!RDFInternal::TNeedJitting<BranchTypes...>::value,
int>::type = 0>
2294 RResultPtr<ActionResultType> CreateAction(
const ColumnNames_t &columns,
const std::shared_ptr<ActionResultType> &r)
2296 constexpr
auto nColumns =
sizeof...(BranchTypes);
2298 const auto validColumnNames = GetValidatedColumnNames(nColumns, columns);
2300 auto newColumns = CheckAndFillDSColumns(validColumnNames, std::make_index_sequence<nColumns>(),
2301 RDFInternal::TypeList<BranchTypes...>());
2303 const auto nSlots = fLoopManager->GetNSlots();
2305 auto action = RDFInternal::BuildAction<BranchTypes...>(validColumnNames, r, nSlots, fProxiedPtr, ActionTag{},
2306 std::move(newColumns));
2307 fLoopManager->Book(action.get());
2308 return MakeResultPtr(r, *fLoopManager, std::move(action));
2314 template <
typename ActionTag,
typename... BranchTypes,
typename ActionResultType,
2315 typename std::enable_if<RDFInternal::TNeedJitting<BranchTypes...>::value,
int>::type = 0>
2316 RResultPtr<ActionResultType>
2317 CreateAction(
const ColumnNames_t &columns,
const std::shared_ptr<ActionResultType> &r,
const int nColumns = -1)
2319 auto realNColumns = (nColumns > -1 ? nColumns :
sizeof...(BranchTypes));
2321 const auto validColumnNames = GetValidatedColumnNames(realNColumns, columns);
2322 const unsigned int nSlots = fLoopManager->GetNSlots();
2324 auto tree = fLoopManager->GetTree();
2325 auto rOnHeap = RDFInternal::MakeSharedOnHeap(r);
2327 auto upcastNodeOnHeap = RDFInternal::MakeSharedOnHeap(RDFInternal::UpcastNode(fProxiedPtr));
2328 using BaseNodeType_t =
typename std::remove_pointer<decltype(upcastNodeOnHeap)>::type::element_type;
2329 RInterface<BaseNodeType_t> upcastInterface(*upcastNodeOnHeap, *fLoopManager, fCustomColumns, fDataSource);
2331 auto jittedActionOnHeap =
2332 RDFInternal::MakeSharedOnHeap(std::make_shared<RDFInternal::RJittedAction>(*fLoopManager));
2334 auto toJit = RDFInternal::JitBuildAction(
2335 validColumnNames, upcastNodeOnHeap,
typeid(std::shared_ptr<ActionResultType>),
typeid(ActionTag), rOnHeap,
2336 tree, nSlots, fCustomColumns, fDataSource, jittedActionOnHeap, fLoopManager->GetID());
2337 fLoopManager->Book(jittedActionOnHeap->get());
2338 fLoopManager->ToJitExec(toJit);
2339 return MakeResultPtr(r, *fLoopManager, *jittedActionOnHeap);
2342 template <typename F, typename CustomColumnType, typename RetType = typename TTraits::CallableTraits<F>::ret_type>
2343 typename std::enable_if<std::is_default_constructible<RetType>::value, RInterface<Proxied, DS_t>>::type
2344 DefineImpl(std::string_view name, F &&expression,
const ColumnNames_t &columns)
2346 RDFInternal::CheckCustomColumn(name, fLoopManager->GetTree(), fCustomColumns.GetNames(),
2347 fLoopManager->GetAliasMap(),
2348 fDataSource ? fDataSource->GetColumnNames() : ColumnNames_t{});
2350 using ArgTypes_t =
typename TTraits::CallableTraits<F>::arg_types;
2351 using ColTypesTmp_t =
typename RDFInternal::RemoveFirstParameterIf<
2352 std::is_same<CustomColumnType, RDFDetail::CustomColExtraArgs::Slot>::value, ArgTypes_t>::type;
2353 using ColTypes_t =
typename RDFInternal::RemoveFirstTwoParametersIf<
2354 std::is_same<CustomColumnType, RDFDetail::CustomColExtraArgs::SlotAndEntry>::value, ColTypesTmp_t>::type;
2356 constexpr
auto nColumns = ColTypes_t::list_size;
2358 const auto validColumnNames = GetValidatedColumnNames(nColumns, columns);
2360 auto newColumns = CheckAndFillDSColumns(validColumnNames, std::make_index_sequence<nColumns>(), ColTypes_t());
2362 using NewCol_t = RDFDetail::RCustomColumn<F, CustomColumnType>;
2363 RDFInternal::RBookedCustomColumns newCols(newColumns);
2364 auto newColumn = std::make_shared<NewCol_t>(fLoopManager, name, std::forward<F>(expression), validColumnNames,
2365 fLoopManager->GetNSlots(), newCols);
2368 auto retTypeName = RDFInternal::TypeID2TypeName(
typeid(RetType));
2369 if (retTypeName.empty()) {
2373 const auto demangledType = RDFInternal::DemangleTypeIdName(
typeid(RetType));
2374 retTypeName =
"void /* The type of column \"" + std::string(name) +
"\" (" + demangledType +
2375 ") is not known to the interpreter. */";
2377 const auto retTypeDeclaration =
"namespace __rdf" + std::to_string(fLoopManager->GetID()) +
2378 " { " + +
" using " + std::string(name) + std::to_string(newColumn->GetID()) +
2379 "_type = " + retTypeName +
"; }";
2380 fLoopManager->ToJitDeclare(retTypeDeclaration);
2382 fLoopManager->RegisterCustomColumn(newColumn.get());
2383 newCols.AddName(name);
2384 newCols.AddColumn(newColumn, name);
2386 RInterface<Proxied> newInterface(fProxiedPtr, *fLoopManager, std::move(newCols), fDataSource);
2388 return newInterface;
2394 template <typename F, typename CustomColumnType, typename RetType = typename TTraits::CallableTraits<F>::ret_type,
2395 bool IsFStringConv = std::is_convertible<F, std::string>::value,
2396 bool IsRetTypeDefConstr = std::is_default_constructible<RetType>::value>
2397 typename std::enable_if<!IsFStringConv && !IsRetTypeDefConstr, RInterface<Proxied, DS_t>>::type
2398 DefineImpl(std::string_view, F,
const ColumnNames_t &)
2400 static_assert(std::is_default_constructible<
typename TTraits::CallableTraits<F>::ret_type>::value,
2401 "Error in `Define`: type returned by expression is not default-constructible");
2415 template <
typename... ColumnTypes>
2416 RResultPtr<RInterface<RLoopManager>> SnapshotImpl(std::string_view treename, std::string_view filename,
2417 const ColumnNames_t &columnList,
const RSnapshotOptions &options)
2419 RDFInternal::CheckTypesAndPars(
sizeof...(ColumnTypes), columnList.size());
2421 const auto validCols = GetValidatedColumnNames(columnList.size(), columnList);
2423 auto newColumns = CheckAndFillDSColumns(validCols, std::index_sequence_for<ColumnTypes...>(),
2424 TTraits::TypeList<ColumnTypes...>());
2426 const std::string fullTreename(treename);
2428 const auto lastSlash = treename.rfind(
'/');
2429 std::string_view dirname =
"";
2430 if (std::string_view::npos != lastSlash) {
2431 dirname = treename.substr(0, lastSlash);
2432 treename = treename.substr(lastSlash + 1, treename.size());
2436 std::unique_ptr<RDFInternal::RActionBase> actionPtr;
2437 if (!ROOT::IsImplicitMTEnabled()) {
2439 using Helper_t = RDFInternal::SnapshotHelper<ColumnTypes...>;
2440 using Action_t = RDFInternal::RAction<Helper_t, Proxied>;
2441 actionPtr.reset(
new Action_t(Helper_t(filename, dirname, treename, validCols, columnList, options), validCols,
2442 fProxiedPtr, std::move(newColumns)));
2445 using Helper_t = RDFInternal::SnapshotHelperMT<ColumnTypes...>;
2446 using Action_t = RDFInternal::RAction<Helper_t, Proxied>;
2447 actionPtr.reset(
new Action_t(
2448 Helper_t(fLoopManager->GetNSlots(), filename, dirname, treename, validCols, columnList, options), validCols,
2449 fProxiedPtr, std::move(newColumns)));
2452 fLoopManager->Book(actionPtr.get());
2454 return RDFInternal::CreateSnapshotRDF(validCols, fullTreename, filename, options.fLazy, *fLoopManager,
2455 std::move(actionPtr));
2460 template <
typename... BranchTypes, std::size_t... S>
2461 RInterface<RLoopManager> CacheImpl(
const ColumnNames_t &columnList, std::index_sequence<S...> s)
2464 constexpr
bool areCopyConstructible =
2465 RDFInternal::TEvalAnd<std::is_copy_constructible<BranchTypes>::value...>::value;
2466 static_assert(areCopyConstructible,
"Columns of a type which is not copy constructible cannot be cached yet.");
2470 RDFInternal::CheckTypesAndPars(
sizeof...(BranchTypes), columnList.size());
2472 auto colHolders = std::make_tuple(Take<BranchTypes>(columnList[S])...);
2473 auto ds = std::make_unique<RLazyDS<BranchTypes...>>(std::make_pair(columnList[S], std::get<S>(colHolders))...);
2475 RInterface<RLoopManager> cachedRDF(std::make_shared<RLoopManager>(std::move(ds), columnList));
2483 RInterface(
const std::shared_ptr<Proxied> &proxied, RLoopManager &lm,
2484 const RDFInternal::RBookedCustomColumns &columns, RDataSource *ds)
2485 : fProxiedPtr(proxied), fLoopManager(&lm), fDataSource(ds), fCustomColumns(columns)
2489 RLoopManager *GetLoopManager()
const {
return fLoopManager; }
2491 const std::shared_ptr<Proxied> &GetProxiedPtr()
const {
return fProxiedPtr; }
2495 ColumnNames_t GetValidatedColumnNames(
const unsigned int nColumns,
const ColumnNames_t &columns)
2497 return RDFInternal::GetValidatedColumnNames(*fLoopManager, nColumns, columns, fCustomColumns.GetNames(),
2501 template <
typename... ColumnTypes, std::size_t... S>
2502 RDFInternal::RBookedCustomColumns
2503 CheckAndFillDSColumns(ColumnNames_t validCols, std::index_sequence<S...>, TTraits::TypeList<ColumnTypes...>)
2506 ? RDFInternal::AddDSColumns(*fLoopManager, validCols, fCustomColumns, *fDataSource,
2507 fLoopManager->GetNSlots(), std::index_sequence_for<ColumnTypes...>(),
2508 TTraits::TypeList<ColumnTypes...>())
2517 #endif // ROOT_RDF_INTERFACE