Project

General

Profile

MetisIntro » Graphvis.py

Thomas Jahns, 12/03/2010 04:15 PM

 
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
Graphvis renders a METIS graph and partitioning file in a SVG file.
Only works for rectangular meshes!

Usage:
Graphviz.py graph_file -- renders without partitioning
Graphviz.py graph_file part_file -- renders with partitioning

"""

__author__ = """Florian Wilhelm (Florian.Wilhelm@kit.edu)"""
__date__ = """26.03.2009"""

def createGraph(path):
"""creates graph by reading the METIS file format and feeding it
into the Graphviz library."""
import pygraphviz as pgv
import os.path

Graph = pgv.AGraph(colorscheme='set19')

# Generate graph from first input file
fh = open(path)
firstline = map(int, fh.readline().split())
nodes = firstline[0]
edges = firstline[1]
if len(firstline) <= 2:
fmt = 0
ncon = 0 # node constraints
elif len(firstline) == 3:
fmt = int(firstline[2])
if fmt == 10 or fmt == 11:
ncon = 1
else:
ncon = 0
elif len(firstline) == 4:
fmt = int(firstline[2])
ncon = int(firstline[3])

# econ means edge constraints (True or False)
if fmt == 0:
econ = False
elif fmt == 1:
econ = True
elif fmt == 10:
econ = False
elif fmt == 11:
econ = True
for node in range(1, nodes + 1):
Graph.add_node(node, colorscheme='set19', style='filled')

for node, line in enumerate(fh):
node += 1 # better use enumerate(fh, start=1) in Python 2.6
elements = line.split()
constraints = []
for i in range(ncon):
constraints.append(elements.pop(0))
if len(constraints) > 0:
constraints = ' ' * 2 + '[' + ", ".join(constraints) + ']'
else:
constraints = ''

if econ:
for i in range(len(elements) / 2):
Graph.add_edge(node, elements[2*i], elements[2*i+1])
Graph.get_node(node).attr['label'] = str(node) + constraints
else:
for neighbor in elements:
Graph.add_edge(node, neighbor)
Graph.get_node(node).attr['label'] = str(node) + constraints
if node >= nodes:
break
fh.close()
return Graph

def colorGraph(Graph, path):
"""colors graph according to given partitioning file"""
fh = open(path)
for node, line in enumerate(fh):
node += 1
color = str(1 + int(line))
Graph.get_node(node).attr['color'] = color

def layoutGraph(Graph):
"""layouts graph in a rectangular way"""
nodes = len(Graph.nodes())
linewidth = max(map(int, Graph.neighbors(1))) - 1
for node in range(1, nodes + 1):
x_coord = (node - 1) % linewidth * 100
y_coord = (node - 1) // linewidth * 100
node_obj = Graph.get_node(node)
node_obj.attr['pos'] = "%s,%s"%(x_coord, y_coord)
node_obj.attr['height'] = "0.8"
node_obj.attr['width'] = "0.8"

if __name__ == '__main__':
import warnings
# Filter some annoying warnings about color names
warnings.filterwarnings('ignore', '.* is not a known color.', RuntimeWarning)

import sys
if len(sys.argv) <= 1:
print __doc__
sys.exit(1)
path = sys.argv[1]
Graph = createGraph(path)
# Generate coloring according to partitioning from second input file
if len(sys.argv) == 3:
path = sys.argv[2]
colorGraph(Graph, path)
layoutGraph(Graph)
import os.path
(basepath, filename) = os.path.split(path)
# Save output
outputformat = 'svg'
output = os.path.join(basepath, "%s.%s"%(filename, outputformat))
Graph.draw(output, prog='neato', args='-n2', format=outputformat)
(2-2/8)