Gravio is graph generation and visualization with an object oriented data structure.
Gravio helps you write Python code which construct graphs. It does this by providing a command-oriented interface to add nodes, edges and subgraphs. As a graph is developed its intermediate state may be queried which helps to factor construction code into functional parts which can build on prior results.
Construction commands are queued so that they may be replayed in order. This allows commands to mutate shared state which reduces the need to exhaustively specify attributes.
Gravio command interface is very closely aligned with the GraphViz Dot language and indeed the primary goal of Gravio is that its command queue is interpreted into Dot text.
Install it like any Python package.
The gravio.gen.Graph
class is the main entry point to constructing graphs. It provides methods .node()
, .edge()
and .subgraph()
(in the GraphViz “cluster” sense). Each return and add new objects to command list in order of their calling. Positional arguments are node or subgraph names. Arbitrary keyword arguments may be applied. If positional arguments are omitted the call is equivalent to using a typename. For example g.node(color='red')
is equivalent to creating a node named node
with the color
attribute set to red
. Some Graph
consumers may interpret this as setting a default value for any subsequent node
. Indeed the example Graph
below is consumed by dotify.Dotify
which when evaluated as a string will produce Dot text.
Here is a simple example gravio
code, the result of exporting to Dot and its visualization with dot
:
from gravio import gen, dotify
g = gen.Graph("simple", "digraph", style='filled', rankdir='LR')
g.node('a', color='red')
g.edge('a','b',style='dashed')
sg = g.subgraph('cluster_sg', style='solid')
sg.node(color='blue')
sg.edge('b','c')
d = dotify.Dotify(g, indent=' ')
print (str(d))
digraph simple { graph[rankdir="LR",style="filled"]; a[color="red"]; "a" -> "b"[style="dashed"]; subgraph cluster_sg { graph[style="solid"]; node[color="blue"]; "b" -> "c"[]; } }
The gravio.gen.Graph
is actually a list of other gravio.gen
objects. It’s order reflects the order in which the objects were created. Note that naming a node only in the creation of an edge does not explicitly add a gravio.gen.Node
object to the Graph
list.
The Graph
object also provides some convenience methods to query its list.
from gravio import gen, dotify
g = gen.Graph("simple", "digraph", style='filled', rankdir='LR')
sg = g.subgraph("sg", category='cats')
g.node('a',color='red')
g.node('b',color='blue')
sg.node('c',color='red', special=True)
sg.node('d',color='red')
g.edge('a','b')
g.edge('a','c')
rednodes = g.nodes(color='red')
print ('\n'.join([n.name for n in rednodes]))
print (sg.nodes(special=True))
print (len(g.subgraphs))
print (len(g.graphs(category='cats')))
The Graph.nodes()
returns all nodes directly in Graph (the search does not descend into subgraphs) with matching attributes. Likewise Graph.graphs()
will search for any direct subgraphs of the given Graph
object. A list of all subgraphs in order of their addition are available as Graph.subgraphs
.
Graph construction code may use these mechanisms to separate subgraph creation from code which connects nodes between subgraphs based on some assumption about the structure if not the exact content of the subgraphs. For example, the user may give individual nodes or subgraphs attributes that make up some addressing scheme. The user may then write code which looks for these addresses in order to form new edges. This code may then need not be dependent on details of the structure and exact content of the graph (eg, it may be independent of the exact names and connectivity). The user is limited only by their imagination.
See the modules under gravio.test
and gravio.examples
. This example produces two large graphs each with a variant in terms of the connections among parts near the center.
$ python gravio/test/test_examples_dune.py $ for ext in svg pdf png; do $ dot -T$ext -o images/example-dune-felix.$ext test_examples_dune_felix.dot $ dot -T$ext -o images/example-dune-rce-felix.$ext test_examples_dune_rce_felix.dot $ done