Coder Social home page Coder Social logo

riak_graphviz's Introduction

Synopsis

riak_graphviz is a python library, built on graphviz.py, intended to simplify generating diagrams for complex processes. The primary functionality it adds to graphviz.py is ease of construction of complicated call stacks, and logical ordering of nodes through the use of subgraphs under the hood.

You'll need graphviz installed to use this code, which you can get, for example, via:

pip install graphviz

or see the official graphviz site for other download options: http://www.graphviz.org.

Extensive (but weirdly awkward to navigate) documentation about graphviz can be found at the official graphviz site: http://www.graphviz.org/Documentation.php

Back to Examples

To create a new directional graph, and output the result as a .png file:

from riak_graphviz import Node, DiGraph
digraph = DiGraph({'format':'png'})

Now we have our main digraph object. Let's add some nodes to it and render it:

node1 = Node({'label':'module1', 'color': 'red'})
digraph.append(node1)

node2 = Node({'label':'module2', 'color': 'blue'})
digraph.append(node2)

digraph.render('img/modules.png')

All top-level nodes appended to a digraph are treated as modules, and given the same rank, so when the plot is rendered, it will look like this:

alt tag

Each node object can have its own hierarchy of nodes. You can construct this hierarchy by appending to the nodes themselves, via the Node.append() function, as detailed below:

Back to Examples

Node.append() takes a single argument with a flexible syntax: a tuple of values (i.e., (val1, val2, val3)) is interpreted as a call-stack, i.e., a set of nodes representing functions that call each other in turn, so the following code:

digraph = DiGraph({'format':'png'})
node = Node({'label':'module1', 'color': 'red'})
node.append(({'label': 'module:fn1'}, {'label': 'module:fn2'}, {'label': 'module:fn3'}))
digraph.append(node)

produces this diagram:

alt tag

Back to Examples

On the other hand, a list of values (i.e., [val1, val2, val3]) is interpreted as a simple list of functions, i.e., a set of nodes representing functions that are called by the same function, one after the other. Thus the following code:

digraph = DiGraph({'format':'png'})
node = Node({'label':'module1', 'color': 'red'})
node.append([{'label': 'module:fn1'}, {'label': 'module:fn2'}, {'label': 'module:fn3'}])
digraph.append(node)

produces this diagram:

alt tag

where the rank of the nodes indicates the order in which the functions are called (assumed to be represented by the order of the function in the list). Setting the rank attribute to same for any node changes this behavior to put every list element at the same rank. Thus the following code

digraph = DiGraph({'format':'png'})
node = Node({'label':'module1', 'color': 'red'})
node.append([{'label': 'module:fn1'}, {'label': 'module:fn2'}, {'label': 'module:fn3'}])
node.setNodeAttr('module1', 'rank', 'same')
digraph.append(node)

produces this diagram instead:

alt tag

Back to Examples

Calls to append can be made sequentially on a node, or any supported syntax may be arbitrarily nested. Thus the following code creates a call-stack of functions, the last of which is itself another call-stack, consisting of a function calling three sub-functions:

    node = Node({'label':'module1', 'color': 'blue'})
    node.append(
      (
        {'label': 'module1:fn1'},
        {'label': 'module1:fn2'},
        ({'label': 'module1:fn3'}, [{'label': 'module1:fn3_1'}, {'label': 'module1:fn3_2'}, {'label': 'module1:fn3_3'}]),
      )
    )
    digraph.append(node)

producing this diagram:

alt tag

Back to Examples

Putting it all together, we can create a digraph with multiple modules by instantiating separate nodes:

node1 = Node({'label':'module1', 'color': 'red'})
node2 = Node({'label':'module2', 'color': 'blue'})

Each one can be configured as desired and appended to the digraph:

node1.append(
  (
    {'label': 'module1:fn1'},
    {'label': 'module1:fn2'},
    ({'label': 'module1:fn3'}, [{'label': 'module1:fn3_1'}, {'label': 'module1:fn3_2'}, {'label': 'module1:fn3_3'}]),
  )
)

node2.append([{'label': 'module2:fn1'}, {'label': 'module2:fn2'}, {'label': 'module2:fn3'}])
node2.setNodeAttr('module1', 'rank', 'same')

digraph.append(node1)
digraph.append(node2)

producing this diagram:

alt tag

Back to Examples

Edges can be added between arbitrary nodes by using the DiGraph.edge() function:

digraph.edge('module2:fn3', 'module1:fn3_3', {'color':'green'})

would produce the following output:

alt tag

Back to Examples

The dictionary passed with a node or edge definition can contain any of the supported graphviz attributes. Thus the following code:

node1 = Node({'label':'module1', 'color': 'red'})
node2 = Node({'label':'module2', 'color': 'blue'})

node1.append(
  (
    {'label': 'module1:fn1', 'color':'darkgreen'},
    {'label': 'module1:fn2'},
    ({'label': 'module1:fn3'}, [{'label': 'module1:fn3_1'}, {'label': 'module1:fn3_2'}, {'label': 'module1:fn3_3'}]),
  )
)

node2.append(
  [
    {'label': 'module2:fn1'},
    {'label': 'module2:fn2',  'style':'filled', 'fillcolor':'mistyrose'},
    {'label': 'module2:fn3'}
  ]
)
node2.setNodeAttr('module1', 'rank', 'same')

digraph.edge('module2:fn3', 'module1:fn3_3', {'color':'green', 'dir':'both', 'label':'gen_server:send'})

digraph.append(node1)
digraph.append(node2)

produces the following diagram:

alt tag

NB: Graphviz attributes are documented at http://soc.if.usp.br/manual/graphviz/html/info/attrs.html.

Back to Examples

Constructing complicated calling sequences with a single call to Node.append() can be challenging to get right. riak_graphviz provides some convenience methods to make this easier.

For example, the following code:

    # Construct a single sequence all at one go:

    node = Node({'label':'module1', 'color': 'blue'})
    node.append(
      (
        {'label': 'module1:fn1'},
        {'label': 'module1:fn2'},
        ({'label': 'module1:fn3'}, [{'label': 'module1:fn3_1'}, {'label': 'module1:fn3_2'}, {'label': 'module1:fn3_3'}]),
      )
    )
    digraph.append(node)

and this code:

    # Construct a single node
    
    node1 = Node({'label':'module1', 'color': 'blue'})
    node1.append({'label': 'module1:fn1'})

    # Construct another node
    
    node2 = Node({'label': 'module1:fn3'})
    node2.append([{'label':'module1:fn3_1'}, {'label':'module1:fn3_3'}])

    # Now append node2 to node1
    
    node1.appendTo('module1:fn1', node2)

    # Now insert on node1
    
    node1.insertBetween('module1:fn1', 'module1:fn3', {'label':'module:fn2'})
    node1.insertBetween('module1:fn3_1', 'module1:fn3_3', {'label':'module:fn3_2'})

    digraph.append(node1)

both produce the same diagram below:

alt tag

riak_graphviz's People

Contributors

erikleitch avatar

Stargazers

Jason Voegele avatar Brett Hazen avatar

Watchers

James Cloos avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.