README moves to markdown
[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 version 2 as
7 #    published by the Free Software Foundation;
8 #
9 #    This program is distributed in the hope that it will be useful,
10 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
11 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 #    GNU General Public License for more details.
13 #
14 #    You should have received a copy of the GNU General Public License
15 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 #
17 # Author: Alina Quereilhac <alina.quereilhac@inria.fr>
18
19 import logging
20 import os
21
22 try:
23     import networkx
24 except ImportError:
25     msg = "Networkx library is not installed, you will not be able to plot."
26     logger = logging.Logger("Plotter")
27     logger.debug(msg)
28
29 try:
30     import matplotlib.pyplot as plt
31 except:
32     msg = ("Matplotlib library is not installed or X11 is not enabled. "
33         "You will not be able generate PNG plots.")
34     logger = logging.Logger("Plotter")
35     logger.debug(msg)
36
37 class PFormats:
38     DOT = "dot"
39     FIGURE = "figure"
40
41 class ECPlotter(object):
42     def plot(self, ec, dirpath = None, format= PFormats.FIGURE, 
43             show = False):
44         graph, labels = self._ec2graph(ec)
45
46         add_extension = False
47
48         if not dirpath:
49             import tempfile
50             dirpath = tempfile.mkdtemp()
51         
52         fpath = os.path.join(dirpath, "%s_%s" % (ec.exp_id, ec.run_id)) 
53
54         if format == PFormats.FIGURE:
55             pos = networkx.graphviz_layout(graph, prog="neato")
56             networkx.draw(graph, pos = pos, node_color="white", 
57                     node_size = 500, with_labels=True)
58            
59             label = "\n".join(["%s: %s" % (v[0], v[1]) for v in iter(labels.items())])
60             plt.annotate(label, xy=(0.05, 0.95), xycoords='axes fraction')
61            
62             fpath += ".png"
63
64             plt.savefig(fpath, bbox_inches="tight")
65             
66             if show:
67                 plt.show()
68
69         elif format == PFormats.DOT:
70             fpath += ".dot"
71
72             networkx.write_dot(graph, fpath)
73             
74             if show:
75                 import subprocess
76                 subprocess.call(["dot", "-Tps", fpath, "-o", "%s.ps" % fpath])
77                 subprocess.call(["evince","%s.ps" % fpath])
78         
79         return fpath
80
81     def _ec2graph(self, ec):
82         graph = networkx.Graph(graph = dict(overlap = "false"))
83
84         labels = dict()
85         connections = set()
86
87         for guid, rm in ec._resources.items():
88             label = rm.get_rtype()
89
90             graph.add_node(guid,
91                 label = "%d %s" % (guid, label),
92                 width = 50/72.0, # 1 inch = 72 points
93                 height = 50/72.0, 
94                 shape = "circle")
95
96             labels[guid] = label
97
98             for guid2 in rm.connections:
99                 # Avoid adding a same connection twice
100                 if (guid2, guid) not in connections:
101                     connections.add((guid, guid2))
102
103         for (guid1, guid2) in connections:
104             graph.add_edge(guid1, guid2)
105
106         return graph, labels