39#pragma GCC diagnostic push
40#pragma GCC diagnostic ignored "-Woverloaded-virtual"
41#pragma GCC diagnostic ignored "-Wshadow"
45#pragma GCC diagnostic pop
60#include <unordered_map>
61#include <unordered_set>
84struct ParsedExpression {
89 ColumnNames_t fUsedCols;
91 ColumnNames_t fVarNames;
95std::pair<ColumnNames_t, ColumnNames_t>
96FindUsedColsAndAliases(
const std::string &expr,
const ColumnNames_t &treeBranchNames,
97 const ROOT::Internal::RDF::RColumnRegister &colRegister,
const ColumnNames_t &dataSourceColNames)
99 lexertk::generator tokens;
100 const auto tokensOk = tokens.process(expr);
102 const auto msg =
"Failed to tokenize expression:\n" + expr +
"\n\nMake sure it is valid C++.";
103 throw std::runtime_error(msg);
106 std::unordered_set<std::string> usedCols;
107 std::unordered_set<std::string> usedAliases;
110 const auto nTokens = tokens.size();
111 const auto kSymbol = lexertk::token::e_symbol;
112 for (
auto i = 0u;
i < nTokens; ++
i) {
113 const auto &tok = tokens[
i];
115 if (tok.type != kSymbol || tok.value ==
"&" || tok.value ==
"|") {
123 auto dotChainKeepsGoing = [&](
unsigned int _i) {
124 return _i + 2 <= nTokens && tokens[_i + 1].value ==
"." && tokens[_i + 2].type == kSymbol;
126 while (dotChainKeepsGoing(
i)) {
127 potentialColNames.emplace_back(potentialColNames.back() +
"." + tokens[
i + 2].value);
133 const auto maybeAnAlias = potentialColNames[0];
134 const auto &resolvedAlias = colRegister.
ResolveAlias(maybeAnAlias);
135 if (resolvedAlias != maybeAnAlias) {
136 usedAliases.insert(maybeAnAlias);
137 for (
auto &s : potentialColNames)
138 s.replace(0, maybeAnAlias.size(), resolvedAlias);
143 auto isRDFColumn = [&](
const std::string &col) {
149 const auto longestRDFColMatch = std::find_if(potentialColNames.crbegin(), potentialColNames.crend(), isRDFColumn);
150 if (longestRDFColMatch != potentialColNames.crend())
151 usedCols.insert(*longestRDFColMatch);
154 return {{usedCols.begin(), usedCols.end()}, {usedAliases.begin(), usedAliases.end()}};
158std::string EscapeDots(
const std::string &s)
162 dot.Substitute(out,
"\\.",
"g");
163 return std::string(std::move(out));
166TString ResolveAliases(
const TString &expr,
const ColumnNames_t &usedAliases,
167 const ROOT::Internal::RDF::RColumnRegister &colRegister)
171 for (
const auto &alias : usedAliases) {
173 TPRegexp replacer(
"\\b" + EscapeDots(alias) +
"\\b");
174 replacer.Substitute(out, col.data(),
"g");
180ParsedExpression ParseRDFExpression(std::string_view expr,
const ColumnNames_t &treeBranchNames,
181 const ROOT::Internal::RDF::RColumnRegister &colRegister,
182 const ColumnNames_t &dataSourceColNames)
185 TString preProcessedExpr(expr);
198 TPRegexp colSizeReplacer(
199 R
"REGEX(#(?!(ifdef|ifndef|if|else|elif|endif|pragma|define|undef|include|line))([a-zA-Z_][a-zA-Z0-9_]*)(?=(?:[^"]*"[^"]*")*[^"]*$))REGEX");
200 colSizeReplacer.Substitute(preProcessedExpr, "R_rdf_sizeof_$2",
"g");
204 std::tie(usedCols, usedAliases) =
205 FindUsedColsAndAliases(std::string(preProcessedExpr), treeBranchNames, colRegister, dataSourceColNames);
207 const auto exprNoAliases = ResolveAliases(preProcessedExpr, usedAliases, colRegister);
211 TString exprWithVars(exprNoAliases);
214 for (
auto i = 0u;
i < varNames.size(); ++
i)
215 varNames[
i] =
"var" + std::to_string(
i);
222 std::sort(usedCols.begin(), usedCols.end(),
223 [](
const std::string &
a,
const std::string &
b) { return a.size() > b.size(); });
224 for (
const auto &col : usedCols) {
225 const auto varIdx = std::distance(usedCols.begin(), std::find(usedCols.begin(), usedCols.end(), col));
226 TPRegexp replacer(
"\\b" + EscapeDots(col) +
"\\b");
227 replacer.Substitute(exprWithVars, varNames[varIdx],
"g");
230 return ParsedExpression{std::string(std::move(exprWithVars)), std::move(usedCols), std::move(varNames)};
240std::unordered_map<std::string, std::string> &GetJittedExprs() {
241 static std::unordered_map<std::string, std::string> jittedExpressions;
242 return jittedExpressions;
246BuildFunctionString(
const std::string &expr,
const ColumnNames_t &vars,
const ColumnNames_t &varTypes)
248 assert(vars.size() == varTypes.size());
250 TPRegexp re(R
"(\breturn\b)");
251 const bool hasReturnStmt = re.MatchB(expr);
253 static const std::vector<std::string> fundamentalTypes = {
286 std::stringstream ss;
288 for (
auto i = 0u;
i < vars.size(); ++
i) {
289 std::string fullType;
290 const auto &
type = varTypes[
i];
291 if (std::find(fundamentalTypes.begin(), fundamentalTypes.end(),
type) != fundamentalTypes.end()) {
293 fullType =
"const " +
type +
" ";
297 fullType =
type +
"& ";
299 ss << fullType << vars[
i] <<
", ";
302 ss.seekp(-2, ss.cur);
308 ss << expr <<
"\n;}";
315std::string DeclareFunction(
const std::string &expr,
const ColumnNames_t &vars,
const ColumnNames_t &varTypes)
319 const auto funcCode = BuildFunctionString(expr, vars, varTypes);
320 auto &exprMap = GetJittedExprs();
321 const auto exprIt = exprMap.find(funcCode);
322 if (exprIt != exprMap.end()) {
324 const auto funcName = exprIt->second;
329 const auto funcBaseName =
"func" + std::to_string(exprMap.size());
330 const auto funcFullName =
"R_rdf::" + funcBaseName;
332 const auto toDeclare =
"namespace R_rdf {\nauto " + funcBaseName + funcCode +
"\nusing " + funcBaseName +
333 "_ret_t = typename ROOT::TypeTraits::CallableTraits<decltype(" + funcBaseName +
338 exprMap.insert({funcCode, funcFullName});
345std::string RetTypeOfFunc(
const std::string &funcName)
347 const auto dt =
gROOT->GetType((funcName +
"_ret_t").c_str());
349 const auto type = dt->GetFullTypeName();
354ThrowJitBuildActionHelperTypeError(
const std::string &actionTypeNameBase,
const std::type_info &helperArgType)
358 std::string actionHelperTypeName =
cname;
361 actionHelperTypeName = helperArgType.name();
363 std::string exceptionText =
364 "RDataFrame::Jit: cannot just-in-time compile a \"" + actionTypeNameBase +
"\" action using helper type \"" +
365 actionHelperTypeName +
366 "\". This typically happens in a custom `Fill` or `Book` invocation where the types of the input columns have "
367 "not been specified as template parameters and the ROOT interpreter has no knowledge of this type of action "
368 "helper. Please add template parameters for the types of the input columns to avoid jitting this action (i.e. "
369 "`df.Fill<float>(..., {\"x\"})`, where `float` is the type of `x`) or declare the action helper type to the "
370 "interpreter, e.g. via gInterpreter->Declare.";
372 throw std::runtime_error(exceptionText);
387 std::copy_if(columnNames.begin(), columnNames.end(), std::back_inserter(columnListWithoutSizeColumns),
388 [&](
const std::string &
name) {
389 if (name[0] ==
'#') {
390 filteredColumns.emplace_back(name);
397 if (!filteredColumns.empty()) {
398 std::string msg =
"Column name(s) {";
399 for (
auto &
c : filteredColumns)
401 msg[msg.size() - 2] =
'}';
402 msg +=
"will be ignored. Please go through a valid Alias to " + action +
" an array size column";
403 throw std::runtime_error(msg);
406 return columnListWithoutSizeColumns;
409std::string
ResolveAlias(
const std::string &col,
const std::map<std::string, std::string> &aliasMap)
411 const auto it = aliasMap.find(col);
412 if (it != aliasMap.end())
416 if (col.size() > 1 && col[0] ==
'#')
417 return "R_rdf_sizeof_" + col.substr(1);
428 const char firstChar = var[0];
431 auto isALetter = [](
char c) {
return (
c >=
'A' &&
c <=
'Z') || (
c >=
'a' &&
c <=
'z'); };
432 const bool isValidFirstChar = firstChar ==
'_' || isALetter(firstChar);
433 if (!isValidFirstChar)
437 auto isANumber = [](
char c) {
return c >=
'0' &&
c <=
'9'; };
438 auto isValidTok = [&isALetter, &isANumber](
char c) {
return c ==
'_' || isALetter(
c) || isANumber(
c); };
439 for (
const char c : var)
444 const auto objName = where ==
"Define" ?
"column" :
"variation";
445 const auto error =
"RDataFrame::" + where +
": cannot define " + objName +
" \"" + std::string(var) +
446 "\". Not a valid C++ variable name.";
447 throw std::runtime_error(error);
455 std::string tname(tn);
463 const auto theRegexSize = columnNameRegexp.size();
464 std::string theRegex(columnNameRegexp);
466 const auto isEmptyRegex = 0 == theRegexSize;
468 if (theRegexSize > 0 && theRegex[0] !=
'^')
469 theRegex =
"^" + theRegex;
470 if (theRegexSize > 0 && theRegex[theRegexSize - 1] !=
'$')
471 theRegex = theRegex +
"$";
478 for (
auto &&colName : colNames) {
480 selectedColumns.emplace_back(colName);
484 if (selectedColumns.empty()) {
485 std::string
text(callerName);
486 if (columnNameRegexp.empty()) {
487 text =
": there is no column available to match.";
489 text =
": regex \"" + std::string(columnNameRegexp) +
"\" did not match any column.";
491 throw std::runtime_error(
text);
493 return selectedColumns;
502 if (colRegister.
IsAlias(definedColView))
503 error =
"An alias with that name, pointing to column \"" + std::string(colRegister.
ResolveAlias(definedColView)) +
504 "\", already exists in this branch of the computation graph.";
506 error =
"A column with that name has already been Define'd. Use Redefine to force redefinition.";
510 else if (std::find(treeColumns.begin(), treeColumns.end(), definedColView) != treeColumns.end())
512 "A branch with that name is already present in the input TTree/TChain. Use Redefine to force redefinition.";
513 else if (std::find(dataSourceColumns.begin(), dataSourceColumns.end(), definedColView) != dataSourceColumns.end())
515 "A column with that name is already present in the input data source. Use Redefine to force redefinition.";
517 if (!error.empty()) {
518 error =
"RDataFrame::" + where +
": cannot define column \"" + std::string(definedColView) +
"\". " + error;
519 throw std::runtime_error(error);
529 if (colRegister.
IsAlias(definedColView)) {
530 error =
"An alias with that name, pointing to column \"" + std::string(colRegister.
ResolveAlias(definedColView)) +
531 "\", already exists. Aliases cannot be Redefined or Varied.";
535 const bool isAlreadyDefined = colRegister.
IsDefineOrAlias(definedColView);
539 const bool isABranch = std::find(treeColumns.begin(), treeColumns.end(), definedColView) != treeColumns.end();
540 const bool isADSColumn =
541 std::find(dataSourceColumns.begin(), dataSourceColumns.end(), definedColView) != dataSourceColumns.end();
543 if (!isAlreadyDefined && !isABranch && !isADSColumn)
544 error =
"No column with that name was found in the dataset. Use Define to create a new column.";
547 if (!error.empty()) {
549 "RDataFrame::" + where +
": cannot redefine or vary column \"" + std::string(definedColView) +
"\". " + error;
550 throw std::runtime_error(error);
557 const std::string definedCol(definedColView);
559 if (!variationDeps.empty()) {
560 const std::string error =
561 "RDataFrame::" + where +
": cannot redefine column \"" + definedCol +
562 "\". The column depends on one or more systematic variations and re-defining varied columns is not supported.";
563 throw std::runtime_error(error);
569 if (nTemplateParams != nColumnNames) {
570 std::string err_msg =
"The number of template parameters specified is ";
571 err_msg += std::to_string(nTemplateParams);
572 err_msg +=
" while ";
573 err_msg += std::to_string(nColumnNames);
574 err_msg +=
" columns have been specified.";
575 throw std::runtime_error(err_msg);
585 if (defaultNames.size() < nRequiredNames)
586 throw std::runtime_error(
587 std::to_string(nRequiredNames) +
" column name" + (nRequiredNames == 1 ?
" is" :
"s are") +
588 " required but none were provided and the default list has size " + std::to_string(defaultNames.size()));
590 return ColumnNames_t(defaultNames.begin(), defaultNames.begin() + nRequiredNames);
593 if (names.size() != nRequiredNames) {
594 auto msg = std::to_string(nRequiredNames) +
" column name" + (nRequiredNames == 1 ?
" is" :
"s are") +
595 " required but " + std::to_string(names.size()) + (names.size() == 1 ?
" was" :
" were") +
597 for (
const auto &
name : names)
598 msg +=
" \"" +
name +
"\",";
600 throw std::runtime_error(msg);
610 for (
auto &column : requiredCols) {
611 const auto isBranch = std::find(datasetColumns.begin(), datasetColumns.end(), column) != datasetColumns.end();
616 const auto isDataSourceColumn =
617 std::find(dataSourceColumns.begin(), dataSourceColumns.end(), column) != dataSourceColumns.end();
618 if (isDataSourceColumn)
620 unknownColumns.emplace_back(column);
622 return unknownColumns;
625std::vector<std::string>
GetFilterNames(
const std::shared_ptr<RLoopManager> &loopManager)
627 return loopManager->GetFiltersNames();
633 std::string_view dirName =
"";
634 std::string_view treeName = fullTreeName;
635 const auto lastSlash = fullTreeName.rfind(
'/');
636 if (std::string_view::npos != lastSlash) {
637 dirName = treeName.substr(0, lastSlash);
638 treeName = treeName.substr(lastSlash + 1, treeName.size());
640 return {std::string(treeName), std::string(dirName)};
647 s << std::hex << std::showbase << reinterpret_cast<size_t>(addr);
652std::shared_ptr<RDFDetail::RJittedFilter>
653BookFilterJit(std::shared_ptr<RDFDetail::RNodeBase> *prevNodeOnHeap, std::string_view
name, std::string_view expression,
658 const auto parsedExpr = ParseRDFExpression(expression, branches, colRegister, dsColumns);
659 const auto exprVarTypes =
661 const auto funcName = DeclareFunction(parsedExpr.fExpr, parsedExpr.fVarNames, exprVarTypes);
662 const auto type = RetTypeOfFunc(funcName);
664 std::runtime_error(
"Filter: the following expression does not evaluate to bool:\n" + std::string(expression));
671 const auto jittedFilter = std::make_shared<RDFDetail::RJittedFilter>(
672 (*prevNodeOnHeap)->GetLoopManagerUnchecked(),
name,
677 std::stringstream filterInvocation;
678 filterInvocation <<
"ROOT::Internal::RDF::JitFilterHelper(" << funcName <<
", new const char*["
679 << parsedExpr.fUsedCols.size() <<
"]{";
680 for (
const auto &col : parsedExpr.fUsedCols)
681 filterInvocation <<
"\"" << col <<
"\", ";
682 if (!parsedExpr.fUsedCols.empty())
683 filterInvocation.seekp(-2, filterInvocation.cur);
688 filterInvocation <<
"}, " << parsedExpr.fUsedCols.size() <<
", \"" <<
name <<
"\", "
689 <<
"reinterpret_cast<std::weak_ptr<ROOT::Detail::RDF::RJittedFilter>*>("
691 <<
"reinterpret_cast<std::shared_ptr<ROOT::Detail::RDF::RNodeBase>*>(" << prevNodeAddr <<
"),"
692 <<
"reinterpret_cast<ROOT::Internal::RDF::RColumnRegister*>(" << definesOnHeapAddr <<
")"
695 auto lm = jittedFilter->GetLoopManagerUnchecked();
696 lm->ToJitExec(filterInvocation.str());
705 std::shared_ptr<RNodeBase> *upcastNodeOnHeap)
707 auto *
const tree = lm.
GetTree();
710 const auto parsedExpr = ParseRDFExpression(expression, branches, colRegister, dsColumns);
711 const auto exprVarTypes =
713 const auto funcName = DeclareFunction(parsedExpr.fExpr, parsedExpr.fVarNames, exprVarTypes);
714 const auto type = RetTypeOfFunc(funcName);
718 auto jittedDefine = std::make_shared<RDFDetail::RJittedDefine>(
name,
type, lm, colRegister, parsedExpr.fUsedCols);
720 std::stringstream defineInvocation;
721 defineInvocation <<
"ROOT::Internal::RDF::JitDefineHelper<ROOT::Internal::RDF::DefineTypes::RDefineTag>(" << funcName
722 <<
", new const char*[" << parsedExpr.fUsedCols.size() <<
"]{";
723 for (
const auto &col : parsedExpr.fUsedCols) {
724 defineInvocation <<
"\"" << col <<
"\", ";
726 if (!parsedExpr.fUsedCols.empty())
727 defineInvocation.seekp(-2, defineInvocation.cur);
732 defineInvocation <<
"}, " << parsedExpr.fUsedCols.size() <<
", \"" <<
name
733 <<
"\", reinterpret_cast<ROOT::Detail::RDF::RLoopManager*>(" <<
PrettyPrintAddr(&lm)
734 <<
"), reinterpret_cast<std::weak_ptr<ROOT::Detail::RDF::RJittedDefine>*>("
736 <<
"), reinterpret_cast<ROOT::Internal::RDF::RColumnRegister*>(" << definesAddr
737 <<
"), reinterpret_cast<std::shared_ptr<ROOT::Detail::RDF::RNodeBase>*>("
747 std::shared_ptr<RNodeBase> *upcastNodeOnHeap)
749 const auto funcName = DeclareFunction(std::string(expression), {
"rdfslot_",
"rdfsampleinfo_"},
750 {
"unsigned int",
"const ROOT::RDF::RSampleInfo"});
751 const auto retType = RetTypeOfFunc(funcName);
755 auto jittedDefine = std::make_shared<RDFDetail::RJittedDefine>(
name, retType, lm, colRegister,
ColumnNames_t{});
757 std::stringstream defineInvocation;
758 defineInvocation <<
"ROOT::Internal::RDF::JitDefineHelper<ROOT::Internal::RDF::DefineTypes::RDefinePerSampleTag>("
759 << funcName <<
", nullptr, 0, ";
764 defineInvocation <<
"\"" <<
name <<
"\", reinterpret_cast<ROOT::Detail::RDF::RLoopManager*>(" <<
PrettyPrintAddr(&lm)
765 <<
"), reinterpret_cast<std::weak_ptr<ROOT::Detail::RDF::RJittedDefine>*>("
767 <<
"), reinterpret_cast<ROOT::Internal::RDF::RColumnRegister*>(" << definesAddr
768 <<
"), reinterpret_cast<std::shared_ptr<ROOT::Detail::RDF::RNodeBase>*>("
776std::shared_ptr<RJittedVariation>
778 const std::vector<std::string> &variationTags, std::string_view expression,
RLoopManager &lm,
780 std::shared_ptr<RNodeBase> *upcastNodeOnHeap,
bool isSingleColumn)
782 auto *
const tree = lm.
GetTree();
785 const auto parsedExpr = ParseRDFExpression(expression, branches, colRegister, dsColumns);
786 const auto exprVarTypes =
788 const auto funcName = DeclareFunction(parsedExpr.fExpr, parsedExpr.fVarNames, exprVarTypes);
789 const auto type = RetTypeOfFunc(funcName);
791 if (
type.rfind(
"ROOT::VecOps::RVec", 0) != 0) {
793 delete upcastNodeOnHeap;
794 upcastNodeOnHeap =
nullptr;
795 throw std::runtime_error(
796 "Jitted Vary expressions must return an RVec object. The following expression returns a " +
type +
797 " instead:\n" + parsedExpr.fExpr);
802 auto jittedVariation = std::make_shared<RJittedVariation>(colNames, variationName, variationTags,
type, colRegister,
803 lm, parsedExpr.fUsedCols);
811 std::stringstream varyInvocation;
812 varyInvocation <<
"ROOT::Internal::RDF::JitVariationHelper<" << (isSingleColumn ?
"true" :
"false") <<
">("
813 << funcName <<
", new const char*[" << parsedExpr.fUsedCols.size() <<
"]{";
814 for (
const auto &col : parsedExpr.fUsedCols) {
815 varyInvocation <<
"\"" << col <<
"\", ";
817 if (!parsedExpr.fUsedCols.empty())
818 varyInvocation.seekp(-2, varyInvocation.cur);
819 varyInvocation <<
"}, " << parsedExpr.fUsedCols.size();
820 varyInvocation <<
", new const char*[" << colNames.size() <<
"]{";
821 for (
const auto &col : colNames) {
822 varyInvocation <<
"\"" << col <<
"\", ";
824 varyInvocation.seekp(-2, varyInvocation.cur);
825 varyInvocation <<
"}, " << colNames.size() <<
", new const char*[" << variationTags.size() <<
"]{";
826 for (
const auto &tag : variationTags) {
827 varyInvocation <<
"\"" << tag <<
"\", ";
829 varyInvocation.seekp(-2, varyInvocation.cur);
830 varyInvocation <<
"}, " << variationTags.size() <<
", \"" << variationName
831 <<
"\", reinterpret_cast<ROOT::Detail::RDF::RLoopManager*>(" <<
PrettyPrintAddr(&lm)
832 <<
"), reinterpret_cast<std::weak_ptr<ROOT::Internal::RDF::RJittedVariation>*>("
834 <<
"), reinterpret_cast<ROOT::Internal::RDF::RColumnRegister*>(" << colRegisterAddr
835 <<
"), reinterpret_cast<std::shared_ptr<ROOT::Detail::RDF::RNodeBase>*>("
839 return jittedVariation;
845 const std::type_info &helperArgType,
const std::type_info &at,
void *helperArgOnHeap,
847 std::weak_ptr<RJittedAction> *jittedActionOnHeap)
851 if (!actionTypeClass) {
852 std::string exceptionText =
"An error occurred while inferring the action type of the operation.";
853 throw std::runtime_error(exceptionText);
855 const std::string actionTypeName = actionTypeClass->GetName();
856 const std::string actionTypeNameBase = actionTypeName.substr(actionTypeName.rfind(
':') + 1);
860 if (helperArgTypeName.empty()) {
861 ThrowJitBuildActionHelperTypeError(actionTypeNameBase, helperArgType);
869 std::stringstream createAction_str;
870 createAction_str <<
"ROOT::Internal::RDF::CallBuildAction<" << actionTypeName;
871 const auto columnTypeNames =
873 for (
auto &colType : columnTypeNames)
874 createAction_str <<
", " << colType;
877 createAction_str <<
">(reinterpret_cast<std::shared_ptr<ROOT::Detail::RDF::RNodeBase>*>("
878 <<
PrettyPrintAddr(prevNode) <<
"), new const char*[" << cols.size() <<
"]{";
879 for (
auto i = 0u;
i < cols.size(); ++
i) {
881 createAction_str <<
", ";
882 createAction_str <<
'"' << cols[
i] <<
'"';
884 createAction_str <<
"}, " << cols.size() <<
", " << nSlots <<
", reinterpret_cast<shared_ptr<" << helperArgTypeName
886 <<
"), reinterpret_cast<std::weak_ptr<ROOT::Internal::RDF::RJittedAction>*>("
888 <<
"), reinterpret_cast<ROOT::Internal::RDF::RColumnRegister*>(" << definesAddr <<
"));";
889 return createAction_str.str();
894 for (
const auto &s : strings) {
901std::shared_ptr<RNodeBase>
UpcastNode(std::shared_ptr<RNodeBase> ptr)
916 for (
auto &col : selectedColumns) {
924 if (!unknownColumns.empty()) {
925 using namespace std::string_literals;
926 std::string errMsg =
"Unknown column"s + (unknownColumns.size() > 1 ?
"s: " :
": ");
927 for (
auto &unknownColumn : unknownColumns)
928 errMsg +=
'"' + unknownColumn +
"\", ";
929 errMsg.resize(errMsg.size() - 2);
930 throw std::runtime_error(errMsg);
933 return selectedColumns;
940 auto toCheckedArgType = [&](
const std::string &
c) {
941 RDFDetail::RDefineBase *define = colRegister.
GetDefine(
c);
943 if (colType.rfind(
"CLING_UNKNOWN_TYPE", 0) == 0) {
945 "The type of custom column \"" +
c +
"\" (" + colType.substr(19) +
946 ") is not known to the interpreter, but a just-in-time-compiled " + context +
947 " call requires this column. Make sure to create and load ROOT dictionaries for this column's class.";
948 throw std::runtime_error(msg);
952 std::vector<std::string> colTypes;
953 colTypes.reserve(colNames.size());
954 std::transform(colNames.begin(), colNames.end(), std::back_inserter(colTypes), toCheckedArgType);
963 const auto nColumns = requestedCols.size();
964 std::vector<bool> mustBeDefined(nColumns,
false);
965 for (
auto i = 0u;
i < nColumns; ++
i)
966 mustBeDefined[
i] = std::find(definedCols.begin(), definedCols.end(), requestedCols[
i]) == definedCols.end();
967 return mustBeDefined;
972 std::unordered_set<std::string> uniqueCols;
973 for (
auto &col : cols) {
974 if (!uniqueCols.insert(col).second) {
975 const auto msg =
"Error: column \"" + col +
976 "\" was passed to Snapshot twice. This is not supported: only one of the columns would be "
977 "readable with RDataFrame.";
978 throw std::logic_error(msg);
985std::pair<std::vector<std::string>, std::vector<std::string>>
986AddSizeBranches(
const std::vector<std::string> &branches,
TTree *tree, std::vector<std::string> &&colsWithoutAliases,
987 std::vector<std::string> &&colsWithAliases)
990 return {std::move(colsWithoutAliases), std::move(colsWithAliases)};
992 assert(colsWithoutAliases.size() == colsWithAliases.size());
994 auto nCols = colsWithoutAliases.size();
996 for (std::size_t
i = 0u;
i < nCols; ++
i) {
997 const auto &colName = colsWithoutAliases[
i];
1001 auto *
b = tree->GetBranch(colName.c_str());
1003 b = tree->FindBranch(colName.c_str());
1004 assert(
b !=
nullptr);
1005 auto *leaves =
b->GetListOfLeaves();
1014 colsWithoutAliases.insert(colsWithoutAliases.begin() +
i, countLeaf->
GetName());
1015 colsWithAliases.insert(colsWithAliases.begin() +
i, countLeaf->
GetName());
1020 return {std::move(colsWithoutAliases), std::move(colsWithAliases)};
1025 std::set<std::string> uniqueCols;
1027 std::remove_if(columnNames.begin(), columnNames.end(),
1028 [&uniqueCols](
const std::string &colName) { return !uniqueCols.insert(colName).second; }),
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 cname
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
Option_t Option_t TPoint TPoint const char text
externTVirtualMutex * gROOTMutex
#define R__LOCKGUARD(mutex)
The head node of a RDF computation graph.
const ColumnNames_t & GetBranchNames()
Return all valid TTree::Branch names (caching results for subsequent calls).
void ToJitExec(const std::string &) const
const ColumnNames_t & GetDefaultColumnNames() const
Return the list of default columns – empty if none was provided when constructing the RDataFrame.
A binder for user-defined columns, variations and aliases.
bool IsDefineOrAlias(std::string_view name) const
Check if the provided name is tracked in the names list.
bool IsAlias(std::string_view name) const
Return true if the given column name is an existing alias.
std::string_view ResolveAlias(std::string_view alias) const
Return the actual column name that the alias resolves to.
std::vector< std::string > GetVariationDeps(const std::string &column) const
Get the names of all variations that directly or indirectly affect a given column.
RDFDetail::RDefineBase * GetDefine(std::string_view colName) const
Return the RDefine for the requested column name, or nullptr.
RDataSource defines an API that RDataFrame can use to read arbitrary data formats.
virtual const std::vector< std::string > & GetColumnNames() const =0
Returns a reference to the collection of the dataset's column names.
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
A TLeaf describes individual elements of a TBranch See TBranch structure in TTree.
virtual TLeaf * GetLeafCount() const
If this leaf stores a variable-sized array or a multi-dimensional array whose last dimension has vari...
const char * GetName() const override
Returns name of object.
Bool_t MatchB(const TString &s, const TString &mods="", Int_t start=0, Int_t nMaxMatch=10)
A TTree represents a columnar dataset.
Special implementation of ROOT::RRangeCast for TCollection, including a check that the cast target ty...
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.
void CheckForNoVariations(const std::string &where, std::string_view definedColView, const RColumnRegister &colRegister)
Throw if the column has systematic variations attached.
ParsedTreePath ParseTreePath(std::string_view fullTreeName)
void CheckForRedefinition(const std::string &where, std::string_view definedColView, const RColumnRegister &colRegister, const ColumnNames_t &treeColumns, const ColumnNames_t &dataSourceColumns)
Throw if column definedColView is already there.
void CheckForDefinition(const std::string &where, std::string_view definedColView, const RColumnRegister &colRegister, const ColumnNames_t &treeColumns, const ColumnNames_t &dataSourceColumns)
Throw if column definedColView is not already there.
std::shared_ptr< RJittedDefine > BookDefineJit(std::string_view name, std::string_view expression, RLoopManager &lm, RDataSource *ds, const RColumnRegister &colRegister, const ColumnNames_t &branches, std::shared_ptr< RNodeBase > *upcastNodeOnHeap)
Book the jitting of a Define call.
void CheckValidCppVarName(std::string_view var, const std::string &where)
std::string ColumnName2ColumnTypeName(const std::string &colName, TTree *, RDataSource *, RDefineBase *, bool vector2rvec=true)
Return a string containing the type of the given branch.
void RemoveDuplicates(ColumnNames_t &columnNames)
ColumnNames_t GetValidatedColumnNames(RLoopManager &lm, const unsigned int nColumns, const ColumnNames_t &columns, const RColumnRegister &colRegister, RDataSource *ds)
Given the desired number of columns and the user-provided list of columns:
std::shared_ptr< RNodeBase > UpcastNode(std::shared_ptr< RNodeBase > ptr)
std::string TypeID2TypeName(const std::type_info &id)
Returns the name of a type starting from its type_info An empty string is returned in case of failure...
bool IsStrInVec(const std::string &str, const std::vector< std::string > &vec)
std::string ResolveAlias(const std::string &col, const std::map< std::string, std::string > &aliasMap)
std::string PrettyPrintAddr(const void *const addr)
void CheckTypesAndPars(unsigned int nTemplateParams, unsigned int nColumnNames)
std::string DemangleTypeIdName(const std::type_info &typeInfo)
bool AtLeastOneEmptyString(const std::vector< std::string_view > strings)
std::shared_ptr< RDFDetail::RJittedFilter > BookFilterJit(std::shared_ptr< RDFDetail::RNodeBase > *prevNodeOnHeap, std::string_view name, std::string_view expression, const ColumnNames_t &branches, const RColumnRegister &colRegister, TTree *tree, RDataSource *ds)
Book the jitting of a Filter call.
std::vector< T > Union(const std::vector< T > &v1, const std::vector< T > &v2)
Return a vector with all elements of v1 and v2 and duplicates removed.
std::string JitBuildAction(const ColumnNames_t &cols, std::shared_ptr< RDFDetail::RNodeBase > *prevNode, const std::type_info &helperArgType, const std::type_info &at, void *helperArgOnHeap, TTree *tree, const unsigned int nSlots, const RColumnRegister &colRegister, RDataSource *ds, std::weak_ptr< RJittedAction > *jittedActionOnHeap)
bool IsInternalColumn(std::string_view colName)
Whether custom column with name colName is an "internal" column such as rdfentry_ or rdfslot_.
ColumnNames_t FilterArraySizeColNames(const ColumnNames_t &columnNames, const std::string &action)
Take a list of column names, return that list with entries starting by '#' filtered out....
void InterpreterDeclare(const std::string &code)
Declare code in the interpreter via the TInterpreter::Declare method, throw in case of errors.
std::shared_ptr< RJittedVariation > BookVariationJit(const std::vector< std::string > &colNames, std::string_view variationName, const std::vector< std::string > &variationTags, std::string_view expression, RLoopManager &lm, RDataSource *ds, const RColumnRegister &colRegister, const ColumnNames_t &branches, std::shared_ptr< RNodeBase > *upcastNodeOnHeap, bool isSingleColumn)
Book the jitting of a Vary call.
void CheckForDuplicateSnapshotColumns(const ColumnNames_t &cols)
ColumnNames_t ConvertRegexToColumns(const ColumnNames_t &colNames, std::string_view columnNameRegexp, std::string_view callerName)
std::pair< std::vector< std::string >, std::vector< std::string > > AddSizeBranches(const std::vector< std::string > &branches, TTree *tree, std::vector< std::string > &&colsWithoutAliases, std::vector< std::string > &&colsWithAliases)
Return copies of colsWithoutAliases and colsWithAliases with size branches for variable-sized array b...
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 ...
std::shared_ptr< RJittedDefine > BookDefinePerSampleJit(std::string_view name, std::string_view expression, RLoopManager &lm, const RColumnRegister &colRegister, std::shared_ptr< RNodeBase > *upcastNodeOnHeap)
Book the jitting of a DefinePerSample call.
std::vector< std::string > GetValidatedArgTypes(const ColumnNames_t &colNames, const RColumnRegister &colRegister, TTree *tree, RDataSource *ds, const std::string &context, bool vector2rvec)
ColumnNames_t FindUnknownColumns(const ColumnNames_t &requiredCols, const ColumnNames_t &datasetColumns, const RColumnRegister &definedCols, const ColumnNames_t &dataSourceColumns)
std::vector< std::string > GetFilterNames()
Returns the names of the filters created.
std::vector< std::string > ColumnNames_t
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
char * DemangleTypeIdName(const std::type_info &ti, int &errorCode)
Demangle in a portable way the type id name.