Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
GraphUtils.hxx
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-2018, Rene Brun and Fons Rademakers. *
5  * All rights reserved. *
6  * *
7  * For the licensing terms see $ROOTSYS/LICENSE. *
8  * For the list of contributors see $ROOTSYS/README/CREDITS. *
9  *************************************************************************/
10 
11 #ifndef ROOT_GRAPHUTILS
12 #define ROOT_GRAPHUTILS
13 
14 #include <string>
15 #include <sstream>
16 #include <vector>
17 #include <map>
18 #include <memory>
19 #include <type_traits>
20 #include <ROOT/RDataFrame.hxx>
21 #include <ROOT/RDF/RInterface.hxx>
22 #include <ROOT/RDF/GraphNode.hxx>
23 
24 #include <iostream>
25 
26 namespace ROOT {
27 namespace Detail {
28 namespace RDF {
29 class RCustomColumnBase;
30 class RFilterBase;
31 class RRangeBase;
32 } // namespace RDF
33 } // namespace Detail
34 
35 namespace Internal {
36 namespace RDF {
37 namespace GraphDrawing {
38 std::shared_ptr<GraphNode>
39 CreateDefineNode(const std::string &columnName, const ROOT::Detail::RDF::RCustomColumnBase *columnPtr);
40 
41 std::shared_ptr<GraphNode> CreateFilterNode(const ROOT::Detail::RDF::RFilterBase *filterPtr);
42 
43 std::shared_ptr<GraphNode> CreateRangeNode(const ROOT::Detail::RDF::RRangeBase *rangePtr);
44 
45 bool CheckIfDefaultOrDSColumn(const std::string &name,
46  const std::shared_ptr<ROOT::Detail::RDF::RCustomColumnBase> &column);
47 
48 // clang-format off
49 /**
50 \class ROOT::Internal::RDF::GraphCreatorHelper
51 \ingroup dataframe
52 \brief Helper class that provides the operation graph nodes.
53 
54  This class is the single point from which graph nodes can be retrieved. Every time an object is created,
55  it clears the static members and starts again.
56  By asking this class to create a node, it will return an existing node if already created, otherwise a new one.
57 */
58 // clang-format on
59 class GraphCreatorHelper {
60 private:
61  using ColumnsNodesMap_t = std::map<const ROOT::Detail::RDF::RCustomColumnBase *, std::weak_ptr<GraphNode>>;
62  using FiltersNodesMap_t = std::map<const ROOT::Detail::RDF::RFilterBase *, std::weak_ptr<GraphNode>>;
63  using RangesNodesMap_t = std::map<const ROOT::Detail::RDF::RRangeBase *, std::weak_ptr<GraphNode>>;
64 
65  ////////////////////////////////////////////////////////////////////////////
66  /// \brief Stores the columns defined and which node in the graph defined them.
67  static ColumnsNodesMap_t &GetStaticColumnsMap()
68  {
69  static ColumnsNodesMap_t sMap;
70  return sMap;
71  };
72 
73  ////////////////////////////////////////////////////////////////////////////
74  /// \brief Stores the filters defined and which node in the graph defined them.
75  static FiltersNodesMap_t &GetStaticFiltersMap()
76  {
77  static FiltersNodesMap_t sMap;
78  return sMap;
79  }
80 
81  ////////////////////////////////////////////////////////////////////////////
82  /// \brief Stores the ranges defined and which node in the graph defined them.
83  static RangesNodesMap_t &GetStaticRangesMap()
84  {
85  static RangesNodesMap_t sMap;
86  return sMap;
87  }
88 
89  ////////////////////////////////////////////////////////////////////////////
90  /// \brief Invoked by the RNodes to create a define graph node.
91  friend std::shared_ptr<GraphNode>
92  CreateDefineNode(const std::string &columnName, const ROOT::Detail::RDF::RCustomColumnBase *columnPtr);
93 
94  ////////////////////////////////////////////////////////////////////////////
95  /// \brief Invoked by the RNodes to create a Filter graph node.
96  friend std::shared_ptr<GraphNode> CreateFilterNode(const ROOT::Detail::RDF::RFilterBase *filterPtr);
97 
98  ////////////////////////////////////////////////////////////////////////////
99  /// \brief Invoked by the RNodes to create a Range graph node.
100  friend std::shared_ptr<GraphNode> CreateRangeNode(const ROOT::Detail::RDF::RRangeBase *rangePtr);
101 
102  ////////////////////////////////////////////////////////////////////////////
103  /// \brief Starting from any leaf (Action, Filter, Range) it draws the dot representation of the branch.
104  std::string FromGraphLeafToDot(std::shared_ptr<GraphNode> leaf);
105 
106  ////////////////////////////////////////////////////////////////////////////
107  /// \brief Starting by an array of leaves, it draws the entire graph.
108  std::string FromGraphActionsToDot(std::vector<std::shared_ptr<GraphNode>> leaves);
109 
110  ////////////////////////////////////////////////////////////////////////////
111  /// \brief Starting from the root node, prints the entire graph.
112  std::string RepresentGraph(ROOT::RDataFrame &rDataFrame);
113 
114  ////////////////////////////////////////////////////////////////////////////
115  /// \brief Starting from the root node, prints the entire graph.
116  std::string RepresentGraph(RLoopManager *rLoopManager);
117 
118  ////////////////////////////////////////////////////////////////////////////
119  /// \brief Starting from a Filter or Range, prints the branch it belongs to
120  template <typename Proxied, typename DataSource>
121  std::string RepresentGraph(RInterface<Proxied, DataSource> &rInterface)
122  {
123  auto loopManager = rInterface.GetLoopManager();
124  loopManager->Jit();
125 
126  return FromGraphLeafToDot(rInterface.GetProxiedPtr()->GetGraph());
127  }
128 
129  ////////////////////////////////////////////////////////////////////////////
130  /// \brief Starting from an action, prints the branch it belongs to
131  template <typename T>
132  std::string RepresentGraph(const RResultPtr<T> &resultPtr)
133  {
134  auto loopManager = resultPtr.fLoopManager;
135  if (!loopManager)
136  throw std::runtime_error("Something went wrong");
137 
138  if (std::is_same<T, RInterface<RLoopManager, void>>::value) {
139  return RepresentGraph(loopManager);
140  }
141 
142  loopManager->Jit();
143 
144  auto actionPtr = resultPtr.fActionPtr;
145  return FromGraphLeafToDot(actionPtr->GetGraph());
146  }
147 
148 public:
149  ////////////////////////////////////////////////////////////////////////////
150  /// \brief Functor. Initializes the static members and delegates the work to the right override.
151  /// \tparam NodeType the RNode from which the graph has to be drawn
152  template <typename NodeType>
153  std::string operator()(NodeType &node)
154  {
155  // First all static data structures are cleaned, to avoid undefined behaviours if more than one Represent is
156  // called
157  GetStaticFiltersMap() = FiltersNodesMap_t();
158  GetStaticColumnsMap() = ColumnsNodesMap_t();
159  GetStaticRangesMap() = RangesNodesMap_t();
160  GraphNode::ClearCounter();
161  // The Represent can now start on a clean environment
162  return RepresentGraph(node);
163  }
164 };
165 
166 } // namespace GraphDrawing
167 } // namespace RDF
168 } // namespace Internal
169 } // namespace ROOT
170 
171 #endif