using pydot to draw node tree

In this post, I'm going to talk about drawing trees and graphs programatically. I've written several answers on quora regarding recursion where I had to manually draw recursion tree as in Finding Subsets Solution enter image description here I'll try to visulise this recursion tree programatically in the second part of this Visualisation with Pydot But before that, let's learn some basc concepts:
I'll be using pydot, which is a Python interface for Graphviz which is an awesome tool for Grah visualisation. So let's get started.
First thing first, we'll first setup the environment for graphviz. Let's download the graphviz binary from here. I'll be using a windows 10 64bit machine for this tutorial and install it. Now we have to add graphviz bin folder to the environment variable path. If you are having trouble here is the installation guide.
Let's install pydot by using:

          pip            install            pydot                  

After installing the pydot package let's draw some simple graphs. Ill be using VS Code for the demo. Here is the minimalist example that draws a simple graph

          # Import pydot            import            pydot  # Make Dot graph object            of            type graph graph = pydot.Dot(graph_type='graph')  # Make Edge            from            1            ->            2            graph.add_edge(pydot.Edge("1",            "2")) # Make Edge            from            1            ->            3            graph.add_edge(pydot.Edge("1",            "3")) # Save the graph            as            png graph.write_png("out.png")                  

Here is how the output looks like. Cool, right?? We'll be exploring more options later on. Now let's say we want to change show a directed edge from node 1 to 2 and node 1 to 3. That's simple as changing the line
(

          #            Make            Dot            graph object            of            type            graph            graph            = pydot.Dot(graph_type='graph')                  

to

                      graph            = pydot.Dot(graph_type='digraph')                  

Here is how the updated diagram looks like

Now let's say we allow multiple edges from one node to another. Say, we want an edge from 1 -> 2, 1 -> 3 and another edge from 1 -> 2. This is easy, we can add another line

                      graph.add_edge(pydot.Edge("1",            "3"))                  

The output looks as follows.

But what if we want to prevent another edge from drawing if it is already present.

          # Import pydot            import            pydot  # Make Dot graph obect            of            type graph graph = pydot.Dot(graph_type='digraph', strict=True)  # Make Edge            from            1            ->            2            graph.add_edge(pydot.Edge("1",            "2")) graph.add_edge(pydot.Edge("1",            "2")) graph.add_edge(pydot.Edge("1",            "3")) # Save the graph            as            png graph.write_png("4.png")                  

We simply supllied another option strict = True while making a dot graph object.
Now we have basic idea of drawing edges , let's eplore how we can add nodes on graph without any edges.

          # Import pydot            import            pydot  # Make Dot graph obect            of            type graph graph = pydot.Dot(graph_type='digraph', strict=True)  # Make pydot Node obect            with            name            1            u = pydot.Node(name="1") graph.add_node(u)  # Make pydot Node obect            with            name            2            v = pydot.Node(name="2") graph.add_node(v) # Save the graph            as            png graph.write_png("out.png")                  

But what if you want 2 nodes with same name, Is it possible?

          # Import pydot            import            pydot  # Make Dot graph obect            of            type graph graph = pydot.Dot(graph_type='digraph', strict=True)  # Make pydot Node obect            with            name            1            u = pydot.Node(name="1") graph.add_node(u)  # Make pydot Node obect            with            name            2            v = pydot.Node(name="1") graph.add_node(v) # Save the graph            as            png graph.write_png("out.png")                  

Here we can see, we are only able to get 1 node with the name "1", so what's the fix?
We'll see another property of pydot.Node called label. What exactly is a label? It is the value that appears on Node whereas the name is the actual value that identifies the node.

          # Import pydot import pydot  # Make Dot            graph            obect of            type            graph            graph            = pydot.Dot(graph_type='digraph', strict=True)            u            = pydot.Node(name="1",            label="One")            graph.add_node(u)  v = pydot.Node(name="2",            label="Two")            graph.add_node(v) #            Save            the            graph            as            png            graph.write_png("7.png")                  

Can we make the graphs more attractive using different colors for nodes and edges?

          # Import pydot import pydot  # Make Dot            graph            obect of            type            graph            graph            = pydot.Dot(graph_type='digraph', strict=True)            u            = pydot.Node(name="1",            label="One", style="filled", fillcolor="gold")            graph.add_node(u)  v = pydot.Node(name="2",            label="Two", style="filled", fillcolor="green")            graph.add_node(v) #            Save            the            graph            as            png            graph.write_png("8.png")                  

Now let's wrap up the tutorial by drawing some example graphs. First let's try drawing trees from google image results.

  1. https://s3-ap-south-1.amazonaws.com/av-blog-media/wp-content/uploads/2018/09/Screenshot-from-2018-09-05-16-36-16.png
          # Import pydot import pydot  # Make Dot            graph            obect of            type            graph            graph            = pydot.Dot(graph_type='graph', strict=True)  x = pydot.Node("A", style="filled", fillcolor="green")            graph.add_node(x) x = pydot.Node("B", style="filled", fillcolor="green")            graph.add_node(x) x = pydot.Node("C", style="filled", fillcolor="green")            graph.add_node(x) x = pydot.Node("D", style="filled", fillcolor="green")            graph.add_node(x) x = pydot.Node("E", style="filled", fillcolor="green")            graph.add_node(x)  edge = pydot.Edge("A",            "B")            graph.add_edge(edge) edge = pydot.Edge("A",            "C")            graph.add_edge(edge) edge = pydot.Edge("B",            "D")            graph.add_edge(edge) edge = pydot.Edge("B",            "E")            graph.add_edge(edge)  #            Save            the            graph            as            png            graph.write_png("9.png")                  



          # Import pydot import pydot  # Make Dot            graph            obect of            type            graph            graph            = pydot.Dot(graph_type='graph', strict=True)  x = pydot.Node("A", style="filled", fillcolor="green")            graph.add_node(x) x = pydot.Node("B", style="filled", fillcolor="green")            graph.add_node(x) x = pydot.Node("C", style="filled", fillcolor="green")            graph.add_node(x) x = pydot.Node("D", style="filled", fillcolor="green")            graph.add_node(x) x = pydot.Node("E", style="filled", fillcolor="green")            graph.add_node(x)  edge = pydot.Edge("A",            "B")            graph.add_edge(edge) edge = pydot.Edge("A",            "C")            graph.add_edge(edge) edge = pydot.Edge("C",            "E")            graph.add_edge(edge) edge = pydot.Edge("B",            "D")            graph.add_edge(edge) edge = pydot.Edge("B",            "E")            graph.add_edge(edge)  #            Save            the            graph            as            png            graph.write_png("10.png")                  

Here is another question which asks to visualise recursion tree for nth fibonacci number.

                      

deffib(n):

if n<=1:

return n

return fib(n-1)+ fib(n-2)

Let's update the code :

                      import pydot   i = 0 graph = pydot.Dot(graph_type="digraph") parent = dict()  def fib(n, node_num):     global i      current_node = (n, node_num)     if node_num == 0:         u = pydot.Node(str((n, node_num)), label=f"fib({n})")         graph.add_node(u)     else: 	# Draw edge from parent of current node and current node 	         u = pydot.Node(str(parent[current_node]), label=f"fib({parent[current_node ][0]})", style="filled", fillcolor="gold")         graph.add_node(u)          v = pydot.Node(str(current_node), label=f"fib({n})")         graph.add_node(v)          edge = pydot.Edge(str(parent[current_node]), str(current_node ))         graph.add_edge(edge)       if n <= 1: 	# Draw Node for base cases         u = pydot.Node(str(current_node), label=f"fib({n})")         graph.add_node(u)         i += 1          v = pydot.Node(str((n, i)), label=f"{n}", shape="plaintext")         graph.add_node(v)          edge = pydot.Edge(str(current_node), str((n, i)), dir="backward")         graph.add_edge(edge)         return n     i += 1     # Store current node as the parent of left child     left_child =  (n - 1, i)     parent[left_child] = current_node      	     i += 1     right_child = (n - 2, i)     parent[right_child] = current_node          #fib(n - 1) + fib(n - 2)     return fib(*left_child) + fib(*right_child)  n = 6 memo = dict() parent[(n, 0)] = None fib(n, 0) graph.write_png("out.png")                  

I'll be adding more on graphviz on Part II. Keep following... for more updates.

Share:

romanbeell1990.blogspot.com

Source: https://sarangbishal.blogspot.com/2019/12/visualisation-with-pydot-part-i.html

0 Response to "using pydot to draw node tree"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel