Skip to content

brettviren/gravio

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

19 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Gravio

Gravio is graph generation and visualization with an object oriented data structure.

images/puff-ball-that-catches-neutrinos.svg

Overview

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.

Installation

Install it like any Python package.

Getting started

Simple Construction

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"[];
  }
}

images/simple.png

Interrogating the Graph

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.

Going further

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

Just FELIX, SVG PDF.

images/example-dune-felix.svg

RCE+FELIX, SVG PDF.

images/example-dune-rce-felix.svg

About

A graph generator

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages