Logo ROOT  
Reference Guide
RDFGraphUtils.cxx
Go to the documentation of this file.
1 // Author: Enrico Guiraud, Danilo Piparo, CERN, Massimo Tumolo Politecnico di Torino 08/2018
2 
3 /*************************************************************************
4  * Copyright (C) 1995-2020, 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 
12 #include "ROOT/RDF/GraphUtils.hxx"
13 
14 #include <algorithm> // std::find
15 
16 namespace ROOT {
17 namespace Internal {
18 namespace RDF {
19 namespace GraphDrawing {
20 
21 std::string GraphCreatorHelper::FromGraphLeafToDot(std::shared_ptr<GraphNode> leaf)
22 {
23  // Only the mapping between node id and node label (i.e. name)
24  std::stringstream dotStringLabels;
25  // Representation of the relationships between nodes
26  std::stringstream dotStringGraph;
27 
28  // Explore the graph bottom-up and store its dot representation.
29  while (leaf) {
30  dotStringLabels << "\t" << leaf->fCounter << " [label=\"" << leaf->fName << "\", style=\"filled\", fillcolor=\""
31  << leaf->fColor << "\", shape=\"" << leaf->fShape << "\"];\n";
32  if (leaf->fPrevNode) {
33  dotStringGraph << "\t" << leaf->fPrevNode->fCounter << " -> " << leaf->fCounter << ";\n";
34  }
35  leaf = leaf->fPrevNode;
36  }
37 
38  return "digraph {\n" + dotStringLabels.str() + dotStringGraph.str() + "}";
39 }
40 
41 std::string GraphCreatorHelper::FromGraphActionsToDot(std::vector<std::shared_ptr<GraphNode>> leaves)
42 {
43  // Only the mapping between node id and node label (i.e. name)
44  std::stringstream dotStringLabels;
45  // Representation of the relationships between nodes
46  std::stringstream dotStringGraph;
47 
48  for (auto leaf : leaves) {
49  while (leaf && !leaf->fIsExplored) {
50  dotStringLabels << "\t" << leaf->fCounter << " [label=\"" << leaf->fName
51  << "\", style=\"filled\", fillcolor=\"" << leaf->fColor << "\", shape=\"" << leaf->fShape
52  << "\"];\n";
53  if (leaf->fPrevNode) {
54  dotStringGraph << "\t" << leaf->fPrevNode->fCounter << " -> " << leaf->fCounter << ";\n";
55  }
56  // Multiple branches may share the same nodes. It is wrong to explore them more than once.
57  leaf->fIsExplored = true;
58  leaf = leaf->fPrevNode;
59  }
60  }
61  return "digraph {\n" + dotStringLabels.str() + dotStringGraph.str() + "}";
62 }
63 
65 {
66  auto loopManager = rDataFrame.GetLoopManager();
67  // Jitting is triggered because nodes must not be empty at the time of the calling in order to draw the graph.
68  loopManager->Jit();
69 
70  return RepresentGraph(loopManager);
71 }
72 
74 {
75  const auto actions = loopManager->GetAllActions();
76  const auto edges = loopManager->GetGraphEdges();
77 
78  std::vector<std::shared_ptr<GraphNode>> nodes;
79  nodes.reserve(actions.size() + edges.size());
80 
81  for (auto *action : actions)
82  nodes.emplace_back(action->GetGraph());
83  for (auto *edge : edges)
84  nodes.emplace_back(edge->GetGraph());
85 
86  return FromGraphActionsToDot(nodes);
87 }
88 
89 std::shared_ptr<GraphNode>
90 CreateDefineNode(const std::string &columnName, const ROOT::Detail::RDF::RDefineBase *columnPtr)
91 {
92  // If there is already a node for this define (recognized by the custom column it is defining) return it. If there is
93  // not, return a new one.
94  auto &sColumnsMap = GraphCreatorHelper::GetStaticColumnsMap();
95  auto duplicateDefineIt = sColumnsMap.find(columnPtr);
96  if (duplicateDefineIt != sColumnsMap.end()) {
97  auto duplicateDefine = duplicateDefineIt->second.lock();
98  return duplicateDefine;
99  }
100 
101  auto node = std::make_shared<GraphNode>("Define\n" + columnName);
102  node->SetDefine();
103 
104  sColumnsMap[columnPtr] = node;
105  return node;
106 }
107 
108 std::shared_ptr<GraphNode> CreateFilterNode(const ROOT::Detail::RDF::RFilterBase *filterPtr)
109 {
110  // If there is already a node for this filter return it. If there is not, return a new one.
111  auto &sFiltersMap = GraphCreatorHelper::GetStaticFiltersMap();
112  auto duplicateFilterIt = sFiltersMap.find(filterPtr);
113  if (duplicateFilterIt != sFiltersMap.end()) {
114  auto duplicateFilter = duplicateFilterIt->second.lock();
115  duplicateFilter->SetIsNew(false);
116  return duplicateFilter;
117  }
118  auto filterName = (filterPtr->HasName() ? filterPtr->GetName() : "Filter");
119  auto node = std::make_shared<GraphNode>(filterName);
120 
121  sFiltersMap[filterPtr] = node;
122  node->SetFilter();
123  return node;
124 }
125 
126 std::shared_ptr<GraphNode> CreateRangeNode(const ROOT::Detail::RDF::RRangeBase *rangePtr)
127 {
128  // If there is already a node for this range return it. If there is not, return a new one.
129  auto &sRangesMap = GraphCreatorHelper::GetStaticRangesMap();
130  auto duplicateRangeIt = sRangesMap.find(rangePtr);
131  if (duplicateRangeIt != sRangesMap.end()) {
132  auto duplicateRange = duplicateRangeIt->second.lock();
133  duplicateRange->SetIsNew(false);
134  return duplicateRange;
135  }
136  auto node = std::make_shared<GraphNode>("Range");
137  node->SetRange();
138 
139  sRangesMap[rangePtr] = node;
140  return node;
141 }
142 
143 std::shared_ptr<GraphNode> AddDefinesToGraph(std::shared_ptr<GraphNode> node,
144  const RDFInternal::RBookedDefines &defines,
145  const std::vector<std::string> &prevNodeDefines)
146 {
147  auto upmostNode = node;
148  const auto &defineNames = defines.GetNames();
149  const auto &defineMap = defines.GetColumns();
150  for (auto i = int(defineNames.size()) - 1; i >= 0; --i) { // walk backwards through the names of defined columns
151  const auto colName = defineNames[i];
152  const bool isAlias = defineMap.find(colName) == defineMap.end();
153  if (isAlias || RDFInternal::IsInternalColumn(colName))
154  continue; // aliases appear in the list of defineNames but we don't support them yet
155  const bool isANewDefine =
156  std::find(prevNodeDefines.begin(), prevNodeDefines.end(), colName) == prevNodeDefines.end();
157  if (!isANewDefine)
158  break; // we walked back through all new defines, the rest is stuff that was already in the graph
159 
160  // create a node for this new Define
161  auto defineNode = RDFGraphDrawing::CreateDefineNode(colName, defineMap.at(colName).get());
162  upmostNode->SetPrevNode(defineNode);
163  upmostNode = defineNode;
164  }
165 
166  return upmostNode;
167 }
168 
169 } // namespace GraphDrawing
170 } // namespace RDF
171 } // namespace Internal
172 } // namespace ROOT
ROOT::Detail::RDF::RFilterBase
Definition: RFilterBase.hxx:36
ROOT::Internal::RDF::GraphDrawing::CreateDefineNode
std::shared_ptr< GraphNode > CreateDefineNode(const std::string &columnName, const ROOT::Detail::RDF::RDefineBase *columnPtr)
Definition: RDFGraphUtils.cxx:90
ROOT::Internal::RDF::GraphDrawing::GraphCreatorHelper::FromGraphLeafToDot
std::string FromGraphLeafToDot(std::shared_ptr< GraphNode > leaf)
Starting from any leaf (Action, Filter, Range) it draws the dot representation of the branch.
Definition: RDFGraphUtils.cxx:21
RBookedDefines.hxx
ROOT::Internal::RDF::RBookedDefines::GetNames
ColumnNames_t GetNames() const
Returns the list of the names of the defined columns.
Definition: RBookedDefines.hxx:81
ROOT::Internal::RDF::GraphDrawing::GraphCreatorHelper::GetStaticFiltersMap
static FiltersNodesMap_t & GetStaticFiltersMap()
Stores the filters defined and which node in the graph defined them.
Definition: GraphUtils.hxx:81
ROOT::Detail::RDF::RRangeBase
Definition: RRangeBase.hxx:32
ROOT::Internal::RDF::RBookedDefines
Encapsulates the columns defined by the user.
Definition: RBookedDefines.hxx:39
ROOT::Detail::RDF::RFilterBase::GetName
std::string GetName() const
Definition: RFilterBase.cxx:30
ROOT::RDataFrame
ROOT's RDataFrame offers a high level interface for analyses of data stored in TTrees,...
Definition: RDataFrame.hxx:42
ROOT::Detail::RDF::RDefineBase
Definition: RDefineBase.hxx:34
ROOT::Detail::RDF::RFilterBase::HasName
bool HasName() const
Definition: RFilterBase.cxx:25
ROOT::Internal::RDF::GraphDrawing::CreateFilterNode
std::shared_ptr< GraphNode > CreateFilterNode(const ROOT::Detail::RDF::RFilterBase *filterPtr)
Definition: RDFGraphUtils.cxx:108
ROOT::Internal::RDF::GraphDrawing::AddDefinesToGraph
std::shared_ptr< GraphNode > AddDefinesToGraph(std::shared_ptr< GraphNode > node, const RDFInternal::RBookedDefines &defines, const std::vector< std::string > &prevNodeDefines)
Add the Defines that have been added between this node and the previous to the graph.
Definition: RDFGraphUtils.cxx:143
ROOT::Detail::RDF::RLoopManager::GetAllActions
std::vector< RDFInternal::RActionBase * > GetAllActions() const
Return all actions, either booked or already run.
Definition: RLoopManager.cxx:766
ROOT::Internal::RDF::IsInternalColumn
bool IsInternalColumn(std::string_view colName)
Definition: RDFUtils.cxx:342
GraphUtils.hxx
ROOT::Internal::RDF::GraphDrawing::GraphCreatorHelper::GetStaticRangesMap
static RangesNodesMap_t & GetStaticRangesMap()
Stores the ranges defined and which node in the graph defined them.
Definition: GraphUtils.hxx:89
ROOT::Internal::RDF::RBookedDefines::GetColumns
const RDefineBasePtrMap_t & GetColumns() const
Returns the list of the pointers to the defined columns.
Definition: RBookedDefines.hxx:85
ROOT::Internal::RDF::GraphDrawing::CreateRangeNode
std::shared_ptr< GraphNode > CreateRangeNode(const ROOT::Detail::RDF::RRangeBase *rangePtr)
Definition: RDFGraphUtils.cxx:126
ROOT::Internal::RDF::GraphDrawing::GraphCreatorHelper::GetStaticColumnsMap
static DefinesNodesMap_t & GetStaticColumnsMap()
Stores the columns defined and which node in the graph defined them.
Definition: GraphUtils.hxx:73
ROOT::Detail::RDF::RLoopManager::Jit
void Jit()
Add RDF nodes that require just-in-time compilation to the computation graph.
Definition: RLoopManager.cxx:606
ROOT::Detail::RDF::RLoopManager::GetGraphEdges
std::vector< RNodeBase * > GetGraphEdges() const
Return all graph edges known to RLoopManager This includes Filters and Ranges but not Defines.
Definition: RLoopManager.cxx:758
ROOT::Internal::RDF::GraphDrawing::GraphCreatorHelper::FromGraphActionsToDot
std::string FromGraphActionsToDot(std::vector< std::shared_ptr< GraphNode >> leaves)
Starting by an array of leaves, it draws the entire graph.
Definition: RDFGraphUtils.cxx:41
ROOT::RDF::RInterface::GetLoopManager
RLoopManager * GetLoopManager() const
Definition: RInterface.hxx:2433
ROOT
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
Definition: EExecutionPolicy.hxx:4
ROOT::Detail::RDF::RLoopManager
The head node of a RDF computation graph.
Definition: RLoopManager.hxx:57
ROOT::Internal::RDF::GraphDrawing::GraphCreatorHelper::RepresentGraph
std::string RepresentGraph(ROOT::RDataFrame &rDataFrame)
Starting from the root node, prints the entire graph.
Definition: RDFGraphUtils.cxx:64