Bugfixes for EC serialization and plotting
[nepi.git] / src / nepi / util / plotter.py
1 #
2 #    NEPI, a framework to manage network experiments
3 #    Copyright (C) 2013 INRIA
4 #
5 #    This program is free software: you can redistribute it and/or modify
6 #    it under the terms of the GNU General Public License as published by
7 #    the Free Software Foundation, either version 3 of the License, or
8 #    (at your option) any later version.
9 #
10 #    This program is distributed in the hope that it will be useful,
11 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
12 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 #    GNU General Public License for more details.
14 #
15 #    You should have received a copy of the GNU General Public License
16 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 #
18 # Author: Alina Quereilhac <alina.quereilhac@inria.fr>
19
20 import networkx
21 import os
22
23 class PFormats:
24     DOT = "dot"
25     FIGURE = "figure"
26
27 class ECPlotter(object):
28     def plot(self, ec, dirpath = None, format= PFormats.FIGURE, 
29             show = False):
30         graph, labels = self._ec2graph(ec)
31
32         add_extension = False
33
34         if not dirpath:
35             import tempfile
36             dirpath = tempfile.mkdtemp()
37         
38         fpath = os.path.join(dirpath, "%s_%s" % (ec.exp_id, ec.run_id)) 
39
40         if format == PFormats.FIGURE:
41             import matplotlib.pyplot as plt
42             pos = networkx.graphviz_layout(graph, prog="neato")
43             networkx.draw(graph, pos = pos, node_color="white", 
44                     node_size = 500, with_labels=True)
45            
46             label = "\n".join(map(lambda v: "%s: %s" % (v[0], v[1]), labels.iteritems()))
47             plt.annotate(label, xy=(0.05, 0.95), xycoords='axes fraction')
48            
49             fpath += ".png"
50
51             plt.savefig(fpath, bbox_inches="tight")
52             
53             if show:
54                 plt.show()
55
56         elif format == PFormats.DOT:
57             fpath += ".dot"
58
59             networkx.write_dot(graph, fpath)
60             
61             if show:
62                 import subprocess
63                 subprocess.call(["dot", "-Tps", fpath, "-o", "%s.ps" % fpath])
64                 subprocess.call(["evince","%s.ps" % fpath])
65         
66         return fpath
67
68     def _ec2graph(self, ec):
69         graph = networkx.Graph(graph = dict(overlap = "false"))
70
71         labels = dict()
72         connections = set()
73
74         for guid, rm in ec._resources.iteritems():
75             label = rm.get_rtype()
76
77             graph.add_node(guid,
78                 label = "%d %s" % (guid, label),
79                 width = 50/72.0, # 1 inch = 72 points
80                 height = 50/72.0, 
81                 shape = "circle")
82
83             labels[guid] = label
84
85             for guid2 in rm.connections:
86                 # Avoid adding a same connection twice
87                 if (guid2, guid) not in connections:
88                     connections.add((guid, guid2))
89
90         for (guid1, guid2) in connections:
91             graph.add_edge(guid1, guid2)
92
93         return graph, labels