|
#!/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)
|