Skip to content

Commit 6581294

Browse files
committed
added support for plotting BayesNet network structures in XML BIF format
1 parent f8d5a6f commit 6581294

File tree

4 files changed

+85
-3
lines changed

4 files changed

+85
-3
lines changed

CHANGES.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ Changelog
1515
- added `split_commandline` method to module `weka.core.classes`, which splits a command-line
1616
into classname and option list tuple
1717
- the `Instances` class (module: `weka.core.dataset`) now supports slicing
18+
- added methods `plot_xmlbif_graph` and `xmlbif_to_dot` to module `weka.plot.graph` for plotting
19+
XML BIF graphs generated by BayesNet using GraphViz
20+
- added method `plot_graph` to module `weka.plot.graph` to plot dot or XML BIF graphs
1821

1922

2023
0.2.10 (2022-06-27)

python/weka/plot/__init__.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
# along with this program. If not, see <http://www.gnu.org/licenses/>.
1313

1414
# __init__.py
15-
# Copyright (C) 2014-2021 Fracpete (pythonwekawrapper at gmail dot com)
15+
# Copyright (C) 2014-2022 Fracpete (pythonwekawrapper at gmail dot com)
1616

1717
from weka.core.dataset import Instances
1818
from weka.core.classes import Random
@@ -44,6 +44,14 @@
4444
except ImportError:
4545
pass
4646

47+
# check whether lxml is there
48+
lxml_available = False
49+
try:
50+
from lxml import etree
51+
lxml_available = True
52+
except ImportError:
53+
pass
54+
4755

4856
def create_subsample(data, percent, seed=1):
4957
"""

python/weka/plot/graph.py

Lines changed: 72 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
# along with this program. If not, see <http://www.gnu.org/licenses/>.
1313

1414
# graph.py
15-
# Copyright (C) 2014-2016 Fracpete (pythonwekawrapper at gmail dot com)
15+
# Copyright (C) 2014-2022 Fracpete (pythonwekawrapper at gmail dot com)
1616

1717
import logging
1818
import tempfile
@@ -21,6 +21,8 @@
2121
from pygraphviz.agraph import AGraph
2222
if plot.PIL_available:
2323
from PIL import Image
24+
if plot.lxml_available:
25+
from lxml import etree
2426

2527
# logging setup
2628
logger = logging.getLogger(__name__)
@@ -30,6 +32,8 @@ def plot_dot_graph(graph, filename=None):
3032
"""
3133
Plots a graph in graphviz dot notation.
3234
35+
http://graphviz.org/doc/info/lang.html
36+
3337
:param graph: the dot notation graph
3438
:type graph: str
3539
:param filename: the (optional) file to save the generated plot to. The extension determines the file format.
@@ -49,3 +53,70 @@ def plot_dot_graph(graph, filename=None):
4953
agraph.draw(filename)
5054
image = Image.open(filename)
5155
image.show()
56+
57+
58+
def xmlbif_to_dot(graph):
59+
"""
60+
Converts the graph in XML BIF notation into a dot graph.
61+
62+
http://sites.poli.usp.br/p/fabio.cozman/Research/InterchangeFormat/index.html
63+
64+
:param graph: the graph to convert
65+
:type graph: str
66+
:return: the graph in dot notation
67+
:rtype: str
68+
"""
69+
if not plot.lxml_available:
70+
logger.error("lxml is not installed, cannot convert XML BIF graph!")
71+
return
72+
73+
result = list()
74+
result.append("digraph {")
75+
76+
root = etree.fromstring(graph)
77+
network = root.find("NETWORK")
78+
definitions = network.findall("DEFINITION")
79+
for definition in definitions:
80+
f = definition.find("FOR")
81+
givens = definition.findall("GIVEN")
82+
for given in givens:
83+
result.append(" %s -> %s;" % (given.text, f.text))
84+
85+
result.append("}")
86+
87+
return "\n".join(result)
88+
89+
90+
def plot_xmlbif_graph(graph, filename=None):
91+
"""
92+
Plots a graph in XML BIF notation. Only plots the structure, not the tables.
93+
94+
http://sites.poli.usp.br/p/fabio.cozman/Research/InterchangeFormat/index.html
95+
96+
:param graph: the XML BIF notation graph
97+
:type graph: str
98+
:param filename: the (optional) file to save the generated plot to. The extension determines the file format.
99+
:type filename: str
100+
"""
101+
if not plot.lxml_available:
102+
logger.error("lxml is not installed, cannot convert XML BIF graph!")
103+
return
104+
plot_dot_graph(xmlbif_to_dot(graph), filename)
105+
106+
107+
def plot_graph(graph, filename=None):
108+
"""
109+
Plots a graph in dot or XML BIF notation.
110+
111+
http://graphviz.org/doc/info/lang.html
112+
http://sites.poli.usp.br/p/fabio.cozman/Research/InterchangeFormat/index.html
113+
114+
:param graph: the dot/XML BIF notation graph
115+
:type graph: str
116+
:param filename: the (optional) file to save the generated plot to. The extension determines the file format.
117+
:type filename: str
118+
"""
119+
if "<BIF" in graph and "<NETWORK>" in graph:
120+
return plot_xmlbif_graph(graph, filename=filename)
121+
else:
122+
return plot_dot_graph(graph, filename=filename)

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ def _read(f):
6565
],
6666
extras_require={
6767
'plots': ["matplotlib"],
68-
'graphs': ["pygraphviz", "pillow"],
68+
'graphs': ["pygraphviz", "pillow", "lxml"],
6969
},
7070
entry_points={
7171
"console_scripts": [

0 commit comments

Comments
 (0)