Project

General

Profile

MetisIntro » Graphvis.py

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

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

    
7
  Usage:
8
    Graphviz.py graph_file           -- renders without partitioning
9
    Graphviz.py graph_file part_file -- renders with partitioning
10

    
11
"""
12

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

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

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

    
24
    # Generate graph from first input file
25
    fh = open(path)
26
    firstline = map(int, fh.readline().split())
27
    nodes = firstline[0]
28
    edges = firstline[1]
29
    if len(firstline) <= 2:
30
        fmt = 0
31
        ncon = 0 # node constraints
32
    elif len(firstline) == 3:
33
        fmt = int(firstline[2])
34
        if fmt == 10 or fmt == 11:
35
            ncon = 1
36
        else:
37
            ncon = 0
38
    elif len(firstline) == 4:
39
        fmt = int(firstline[2])
40
        ncon = int(firstline[3])
41

    
42
    # econ means edge constraints (True or False)	
43
    if fmt == 0:
44
        econ = False
45
    elif fmt == 1:
46
        econ = True
47
    elif fmt == 10:
48
        econ = False
49
    elif fmt == 11:
50
        econ = True	
51
        
52
    for node in range(1, nodes + 1):
53
        Graph.add_node(node, colorscheme='set19', style='filled')
54

    
55
    for node, line in enumerate(fh):
56
        node += 1 # better use enumerate(fh, start=1) in Python 2.6
57
        elements = line.split()
58
        
59
        constraints = []
60
        for i in range(ncon):
61
            constraints.append(elements.pop(0))
62
        if len(constraints) > 0:
63
            constraints = ' ' * 2 + '[' + ", ".join(constraints) + ']'	
64
        else:
65
            constraints = ''
66

    
67
        if econ:
68
            for i in range(len(elements) / 2):
69
                Graph.add_edge(node, elements[2*i], elements[2*i+1])
70
                Graph.get_node(node).attr['label'] = str(node) + constraints
71
        else: 
72
            for neighbor in elements:
73
                Graph.add_edge(node, neighbor)
74
                Graph.get_node(node).attr['label'] = str(node) + constraints
75
        if node >= nodes:
76
            break
77
    fh.close()
78
    return Graph
79

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

    
88
def layoutGraph(Graph):
89
    """layouts graph in a rectangular way"""
90
    nodes = len(Graph.nodes())    
91
    linewidth = max(map(int, Graph.neighbors(1))) - 1
92
    for node in range(1, nodes + 1):
93
        x_coord = (node - 1) % linewidth * 100
94
        y_coord = (node - 1) // linewidth * 100 
95
        node_obj = Graph.get_node(node)
96
        node_obj.attr['pos'] = "%s,%s"%(x_coord, y_coord) 
97
        node_obj.attr['height'] = "0.8"
98
        node_obj.attr['width'] = "0.8"
99

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

    
105
    import sys
106
    if len(sys.argv) <= 1:
107
        print __doc__
108
        sys.exit(1)
109
    path = sys.argv[1]
110
    
111
    Graph = createGraph(path)
112
    
113
    # Generate coloring according to partitioning from second input file
114
    if len(sys.argv) == 3:
115
        path = sys.argv[2]
116
        colorGraph(Graph, path)
117
    
118
    layoutGraph(Graph)
119
    
120
    import os.path
121
    (basepath, filename) = os.path.split(path)
122
    
123
    # Save output
124
    outputformat = 'svg'
125
    output = os.path.join(basepath, "%s.%s"%(filename, outputformat))
126
    Graph.draw(output, prog='neato', args='-n2', format=outputformat)
(2-2/8)