Commit 01fd54e2 authored by Tiago Peixoto's avatar Tiago Peixoto

Implement compatibility with python 3

parent cc1b6517
......@@ -17,6 +17,7 @@
#include <boost/python.hpp>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
#include "bytesobject.h"
#define NUMPY_EXPORT
#include "numpy_bind.hh"
......@@ -160,7 +161,7 @@ void graph_exception_translator(const Exception& e)
if (is_same<Exception, ValueException>::value)
error = PyExc_ValueError;
PyObject* message = PyString_FromString(e.what());
PyObject* message = PyUnicode_FromString(e.what());
PyObject_SetAttrString(error, "message", message);
PyErr_SetString(error, e.what());
}
......@@ -314,6 +315,13 @@ bool openmp_enabled()
#endif
}
// numpy array interface weirdness
void* do_import_array()
{
import_array1(NULL);
return NULL;
}
void ungroup_vector_property(GraphInterface& g, boost::any vector_prop,
boost::any prop, size_t pos, bool edge);
void group_vector_property(GraphInterface& g, boost::any vector_prop,
......@@ -327,8 +335,7 @@ void export_python_interface();
BOOST_PYTHON_MODULE(libgraph_tool_core)
{
// numpy
import_array();
do_import_array();
export_python_interface();
register_exception_translator<GraphException>
......
......@@ -330,6 +330,8 @@ struct export_python_interface
class_<PythonIterator<PythonVertex, vertex_iterator> >
("VertexIterator", no_init)
.def("__iter__", objects::identity_function())
.def("__next__", &PythonIterator<PythonVertex,
vertex_iterator>::Next)
.def("next", &PythonIterator<PythonVertex,
vertex_iterator>::Next);
v_iterators.insert(typeid(vertex_iterator).name());
......@@ -339,6 +341,8 @@ struct export_python_interface
class_<PythonIterator<PythonEdge<Graph>,
edge_iterator> >("EdgeIterator", no_init)
.def("__iter__", objects::identity_function())
.def("__next__", &PythonIterator<PythonEdge<Graph>,
edge_iterator>::Next)
.def("next", &PythonIterator<PythonEdge<Graph>,
edge_iterator>::Next);
......@@ -347,6 +351,8 @@ struct export_python_interface
class_<PythonIterator<PythonEdge<Graph>,
out_edge_iterator> >("OutEdgeIterator", no_init)
.def("__iter__", objects::identity_function())
.def("__next__", &PythonIterator<PythonEdge<Graph>,
out_edge_iterator>::Next)
.def("next", &PythonIterator<PythonEdge<Graph>,
out_edge_iterator>::Next);
......@@ -360,6 +366,8 @@ struct export_python_interface
class_<PythonIterator<PythonEdge<Graph>,
in_edge_iterator> >("InEdgeIterator", no_init)
.def("__iter__", objects::identity_function())
.def("__next__", &PythonIterator<PythonEdge<Graph>,
in_edge_iterator>::Next)
.def("next", &PythonIterator<PythonEdge<Graph>,
in_edge_iterator>::Next);
}
......
This diff is collapsed.
......@@ -22,14 +22,20 @@
Utility module which includes all the sub-modules in graph_tool
"""
from __future__ import division, absolute_import, print_function
from graph_tool import *
import graph_tool
from graph_tool.correlations import *
import graph_tool.correlations
from graph_tool.centrality import *
import graph_tool.centrality
from graph_tool.draw import *
import graph_tool.draw
try:
from graph_tool.draw import *
import graph_tool.draw
except ImportError:
# Proceed despite errors with cairo, matplotlib, etc.
pass
from graph_tool.stats import *
import graph_tool.stats
from graph_tool.generation import *
......
......@@ -41,8 +41,10 @@ Contents
++++++++
"""
from __future__ import division, absolute_import, print_function
from .. dl_import import dl_import
dl_import("import libgraph_tool_centrality")
dl_import("from . import libgraph_tool_centrality")
from .. import _prop, ungroup_vector_property
import sys
......@@ -131,7 +133,7 @@ def pagerank(g, damping=0.85, pers=None, weight=None, prop=None, epsilon=1e-6,
>>> seed(42)
>>> g = gt.random_graph(100, lambda: (poisson(3), poisson(3)))
>>> pr = gt.pagerank(g)
>>> print pr.a
>>> print(pr.a)
[ 0.00865316 0.0054067 0.00406312 0.00426668 0.0015 0.00991696
0.00550065 0.00936397 0.00347917 0.00731864 0.00689843 0.00286274
0.00508731 0.01020047 0.00562247 0.00584915 0.02457086 0.00438568
......@@ -158,7 +160,7 @@ def pagerank(g, damping=0.85, pers=None, weight=None, prop=None, epsilon=1e-6,
>>> p.a = random(g.num_vertices())
>>> p.a /= p.a.sum()
>>> pr = gt.pagerank(g, pers=p, weight=w)
>>> print pr.a
>>> print(pr.a)
[ 0.00712999 0.00663336 0.00685722 0.00402663 0.00092715 0.01021926
0.00269502 0.0073301 0.00449892 0.00582793 0.00580542 0.00275149
0.00676363 0.01157972 0.00486918 0.00616345 0.02506695 0.00607967
......@@ -258,7 +260,7 @@ def betweenness(g, vprop=None, eprop=None, weight=None, norm=True):
>>> seed(42)
>>> g = gt.random_graph(100, lambda: (poisson(3), poisson(3)))
>>> vb, eb = gt.betweenness(g)
>>> print vb.a
>>> print(vb.a)
[ 0.04889806 0.07181892 0.0256799 0.02885791 0. 0.05060927
0.04490836 0.03763462 0.02033383 0.03163202 0.02641248 0.03171598
0.03771112 0.02194663 0.0374907 0.01072567 0. 0.03079281
......@@ -340,7 +342,7 @@ def central_point_dominance(g, betweenness):
>>> seed(42)
>>> g = gt.random_graph(100, lambda: (poisson(3), poisson(3)))
>>> vb, eb = gt.betweenness(g)
>>> print gt.central_point_dominance(g, vb)
>>> print(gt.central_point_dominance(g, vb))
0.0766473408634
References
......@@ -418,9 +420,9 @@ def eigenvector(g, weight=None, vprop=None, epsilon=1e-6, max_iter=None):
>>> w = g.new_edge_property("double")
>>> w.a = random(g.num_edges()) * 42
>>> x = gt.eigenvector(g, w)
>>> print x[0]
>>> print(x[0])
0.0160851991895
>>> print x[1].a
>>> print(x[1].a)
[ 0.1376411 0.07207366 0.02727508 0.05805304 0. 0.10690994
0.04315491 0.01040908 0.02300252 0.08874163 0.04968119 0.06718114
0.05526028 0.20449371 0.02337425 0.07581173 0.19993899 0.14718912
......@@ -524,7 +526,7 @@ def eigentrust(g, trust_map, vprop=None, norm=False, epsilon=1e-6, max_iter=0,
>>> trust = g.new_edge_property("double")
>>> trust.a = random(g.num_edges())*42
>>> t = gt.eigentrust(g, trust, norm=True)
>>> print t.a
>>> print(t.a)
[ 1.12095562e-02 3.97280231e-03 1.31675503e-02 9.61282478e-03
0.00000000e+00 1.73295741e-02 3.53395497e-03 1.06203582e-02
1.36906165e-03 8.64587777e-03 1.12049516e-02 3.18891993e-03
......@@ -650,7 +652,7 @@ def trust_transitivity(g, trust_map, source=None, target=None, vprop=None):
>>> trust = g.new_edge_property("double")
>>> trust.a = random(g.num_edges())
>>> t = gt.trust_transitivity(g, trust, source=g.vertex(0))
>>> print t.a
>>> print(t.a)
[ 1.00000000e+00 9.59916062e-02 4.27717883e-02 7.70755875e-02
0.00000000e+00 2.04476926e-01 5.55315822e-02 2.82854665e-02
5.08479257e-02 1.68128402e-01 3.28567434e-02 7.39525583e-02
......@@ -707,3 +709,4 @@ def trust_transitivity(g, trust_map, source=None, target=None, vprop=None):
if target != -1 and source != -1:
return vprop.a[target]
return vprop
......@@ -41,14 +41,16 @@ Contents
++++++++
"""
from __future__ import division, absolute_import, print_function
from .. dl_import import dl_import
dl_import("import libgraph_tool_clustering as _gt")
dl_import("from . import libgraph_tool_clustering as _gt")
from .. import _degree, _prop, Graph, GraphView
from .. topology import isomorphism
from .. generation import random_rewire
from .. stats import vertex_hist
from itertools import izip
from collections import defaultdict
from numpy import *
from numpy import random
......@@ -114,7 +116,7 @@ def local_clustering(g, prop=None, undirected=True):
>>> seed(42)
>>> g = gt.random_graph(1000, lambda: (5,5))
>>> clust = gt.local_clustering(g)
>>> print gt.vertex_average(g, clust)
>>> print(gt.vertex_average(g, clust))
(0.00908888888888889, 0.0004449824521439575)
References
......@@ -171,7 +173,7 @@ def global_clustering(g):
>>> from numpy.random import seed
>>> seed(42)
>>> g = gt.random_graph(1000, lambda: (5,5))
>>> print gt.global_clustering(g)
>>> print(gt.global_clustering(g))
(0.009114059777509717, 0.0004464454368899158)
References
......@@ -244,9 +246,9 @@ def extended_clustering(g, props=None, max_depth=3, undirected=False):
>>> seed(42)
>>> g = gt.random_graph(1000, lambda: (5,5))
>>> clusts = gt.extended_clustering(g, max_depth=5)
>>> for i in xrange(0, 5):
... print gt.vertex_average(g, clusts[i])
...
>>> for i in range(0, 5):
... print(gt.vertex_average(g, clusts[i]))
...
(0.0058850000000000005, 0.0004726257592782405)
(0.026346666666666668, 0.0009562588213100747)
(0.11638833333333333, 0.002086419787711849)
......@@ -263,7 +265,7 @@ def extended_clustering(g, props=None, max_depth=3, undirected=False):
g = GraphView(g, directed=False)
if props == None:
props = []
for i in xrange(0, max_depth):
for i in range(0, max_depth):
props.append(g.new_vertex_property("double"))
_gt.extended_clustering(g._Graph__graph,
[_prop("v", g, p) for p in props])
......@@ -321,9 +323,9 @@ def motifs(g, k, p=1.0, motif_list=None):
>>> seed(42)
>>> g = gt.random_graph(1000, lambda: (5,5))
>>> motifs, counts = gt.motifs(gt.GraphView(g, directed=False), 4)
>>> print len(motifs)
>>> print(len(motifs))
11
>>> print counts
>>> print(counts)
[115104, 389090, 724, 820, 1828, 3208, 791, 4, 12, 12, 3]
......@@ -335,7 +337,7 @@ def motifs(g, k, p=1.0, motif_list=None):
:doi:`10.1109/TCBB.2006.51`
"""
seed = random.randint(0, sys.maxint)
seed = random.randint(0, sys.maxsize)
sub_list = []
directed_motifs = g.is_directed()
......@@ -373,7 +375,7 @@ def motifs(g, k, p=1.0, motif_list=None):
temp.append(mg)
sub_list = temp
list_hist = zip(sub_list, hist)
list_hist = list(zip(sub_list, hist))
# sort according to in-degree sequence
list_hist.sort(lambda x, y: cmp(sorted([v.in_degree() for v in x[0].vertices()]),
sorted([v.in_degree() for v in y[0].vertices()])))
......@@ -394,14 +396,14 @@ def motifs(g, k, p=1.0, motif_list=None):
def _graph_sig(g):
"""return the graph signature, i.e., the in and out degree distribution as
concatenated as a tuple."""
bins = range(0, g.num_vertices() + 1)
bins = list(range(0, g.num_vertices() + 1))
in_dist = vertex_hist(g, "in", bins=bins if g.is_directed() else [0],
float_count=False)
out_dist = vertex_hist(g, "out", bins=bins, float_count=False)
sig = tuple([(in_dist[1][i], in_dist[0][i]) for \
i in xrange(len(in_dist[0]))] +
i in range(len(in_dist[0]))] +
[(out_dist[1][i], out_dist[0][i]) for\
i in xrange(len(out_dist[0]))])
i in range(len(out_dist[0]))])
return sig
......@@ -486,15 +488,15 @@ def motif_significance(g, k, n_shuffles=100, p=1.0, motif_list=None,
>>> random.seed(10)
>>> g = gt.random_graph(100, lambda: (3,3))
>>> motifs, zscores = gt.motif_significance(g, 3)
>>> print len(motifs)
>>> print(len(motifs))
11
>>> print zscores
>>> print(zscores)
[0.014875553792545083, 0.016154998074953769, 0.002455801898331304, -1.9579019397305546, 0.83542298414538518, 0.84715258999068244, -0.93385230436820643, -0.11, -0.1, -0.31, -0.14]
"""
s_ms, counts = motifs(g, k, p, motif_list)
if threshold > 0:
s_ms, counts = zip(*[x for x in zip(s_ms, counts) if x[1] > threshold])
s_ms, counts = list(zip(*[x for x in zip(s_ms, counts) if x[1] > threshold]))
s_ms = list(s_ms)
counts = list(counts)
s_counts = [0] * len(s_ms)
......@@ -502,19 +504,19 @@ def motif_significance(g, k, n_shuffles=100, p=1.0, motif_list=None,
# group subgraphs by number of edges
m_e = defaultdict(lambda: [])
for i in xrange(len(s_ms)):
for i in range(len(s_ms)):
m_e[_graph_sig(s_ms[i])].append(i)
# get samples
sg = g.copy()
for i in xrange(0, n_shuffles):
for i in range(0, n_shuffles):
random_rewire(sg, shuffle_strategy, self_loops=self_loops,
parallel_edges=parallel_edges)
m_temp, count_temp = motifs(sg, k, p, motif_list)
if threshold > 0:
m_temp, count_temp = zip(*[x for x in zip(m_temp, count_temp) \
if x[1] > threshold])
for j in xrange(0, len(m_temp)):
m_temp, count_temp = list(zip(*[x for x in zip(m_temp, count_temp) \
if x[1] > threshold]))
for j in range(0, len(m_temp)):
found = False
for l in m_e[_graph_sig(m_temp[j])]:
if isomorphism(s_ms[l], m_temp[j]):
......@@ -530,9 +532,9 @@ def motif_significance(g, k, n_shuffles=100, p=1.0, motif_list=None,
s_counts = [x / float(n_shuffles) for x in s_counts]
s_dev = [max(sqrt(x[0] / float(n_shuffles) - x[1] ** 2), 1) \
for x in izip(s_dev, s_counts)]
for x in zip(s_dev, s_counts)]
list_hist = zip(s_ms, s_counts, s_dev)
list_hist = list(zip(s_ms, s_counts, s_dev))
# sort according to in-degree sequence
list_hist.sort(lambda x, y: cmp(sorted([v.in_degree()\
for v in x[0].vertices()]),
......@@ -548,11 +550,12 @@ def motif_significance(g, k, n_shuffles=100, p=1.0, motif_list=None,
# sort according to ascending number of edges
list_hist.sort(lambda x, y: cmp(x[0].num_edges(), y[0].num_edges()))
s_ms, s_counts, s_dev = zip(*list_hist)
s_ms, s_counts, s_dev = list(zip(*list_hist))
zscore = [(x[0] - x[1]) / x[2] for x in izip(counts, s_counts, s_dev)]
zscore = [(x[0] - x[1]) / x[2] for x in zip(counts, s_counts, s_dev)]
if full_output:
return s_ms, zscore, counts, s_counts, s_dev
else:
return s_ms, zscore
......@@ -39,8 +39,10 @@ Contents
++++++++
"""
from __future__ import division, absolute_import, print_function
from .. dl_import import dl_import
dl_import("import libgraph_tool_community")
dl_import("from . import libgraph_tool_community")
from .. import _degree, _prop, Graph, GraphView, libcore
import random
......@@ -204,7 +206,7 @@ def community_structure(g, n_iter, n_spins, gamma=1.0, corr="erdos",
new_spins = False
if history_file == None:
history_file = ""
seed = random.randint(0, sys.maxint)
seed = random.randint(0, sys.maxsize)
ug = GraphView(g, directed=False)
libgraph_tool_community.community_structure(ug._Graph__graph, gamma, corr,
n_iter, t_range[1], t_range[0],
......
......@@ -39,9 +39,10 @@ Contents
++++++++
"""
from __future__ import division, absolute_import, print_function
from .. dl_import import dl_import
dl_import("import libgraph_tool_correlations")
dl_import("from . import libgraph_tool_correlations")
from .. import _degree, _prop
from numpy import *
......
......@@ -21,18 +21,31 @@
Some useful decorators
"""
from __future__ import division, absolute_import, print_function
__author__ = "Tiago de Paula Peixoto <tiago@skewed.de>"
__copyright__ = "Copyright 2008 Tiago de Paula Peixoto"
__copyright__ = "Copyright 2006-2012 Tiago de Paula Peixoto"
__license__ = "GPL version 3 or above"
import inspect
import functools
import sys
################################################################################
# Decorators
# Some useful function decorators which will be used
################################################################################
# exec statement in python 2.7 and exec() function in 3.2 are mutually exclusive
if sys.hexversion > 0x03000000:
def exec_function(source, filename, global_map):
exec(compile(source, filename, "exec"), global_map)
else:
eval(compile("""\
def exec_function(source, filename, global_map):
exec compile(source, filename, "exec") in global_map
""","<exec_function>", "exec"))
def _wraps(func):
"""This decorator works like the functools.wraps meta-decorator, but
......@@ -43,7 +56,7 @@ def _wraps(func):
___wrap_defaults = defaults = argspec[-1]
if defaults is not None:
def_string = ["___wrap_defaults[%d]" % d for
d in xrange(len(defaults))]
d in range(len(defaults))]
def_names = argspec[0][-len(defaults):]
else:
def_string = None
......@@ -58,7 +71,7 @@ def _wraps(func):
wf = wf.replace("'%s'" % d, "%s" % d)
for d in def_names:
wf = wf.replace("'%s'" % d, "%s" % d)
exec wf in locals()
exec_function(wf, __file__, locals())
return functools.wraps(func)(locals()[func.__name__])
return decorate
......@@ -81,8 +94,8 @@ def _limit_args(allowed_vals):
@_wraps(func)
def wrap(*args, **kwargs):
arg_names = inspect.getargspec(func)[0]
arguments = zip(arg_names, args)
arguments += [(k, kwargs[k]) for k in kwargs.keys()]
arguments = list(zip(arg_names, args))
arguments += [(k, kwargs[k]) for k in list(kwargs.keys())]
for a in arguments:
if a[0] in allowed_vals:
if a[1] not in allowed_vals[a[0]]:
......@@ -101,7 +114,7 @@ def _require(arg_name, *allowed_types):
if hasattr(f, "wrapped_args"):
wrapped_args = f.wrapped_args
else:
code = f.func_code
code = f.__code__
wrapped_args = list(code.co_varnames[:code.co_argcount])
try:
......
......@@ -18,7 +18,11 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from __future__ import division, absolute_import, print_function
import sys
import os.path
try:
from DLFCN import RTLD_LAZY, RTLD_GLOBAL
dl_flags = RTLD_LAZY | RTLD_GLOBAL
......@@ -49,7 +53,9 @@ def dl_import(import_expr):
orig_dlopen_flags = sys.getdlopenflags()
sys.setdlopenflags(dl_flags)
exec import_expr in local_dict, global_dict
sys.setdlopenflags(orig_dlopen_flags) # reset it to normal case to avoid
# unnecessary symbol collision
try:
exec(import_expr, local_dict, global_dict)
finally:
sys.setdlopenflags(orig_dlopen_flags) # reset it to normal case to
# avoid unnecessary symbol
# collision
......@@ -62,6 +62,8 @@ Contents
++++++++
"""
from __future__ import division, absolute_import, print_function
from .. import GraphView, _check_prop_vector, group_vector_property, \
ungroup_vector_property, infect_vertex_property, _prop
from .. topology import max_cardinality_matching, max_independent_vertex_set, \
......@@ -73,10 +75,11 @@ from numpy import sqrt
import sys
from .. dl_import import dl_import
dl_import("import libgraph_tool_layout")
dl_import("from . import libgraph_tool_layout")
__all__ = ["graph_draw", "graphviz_draw", "fruchterman_reingold_layout",
__all__ = ["graph_draw", "graphviz_draw",
"fruchterman_reingold_layout",
"arf_layout", "sfdp_layout", "random_layout",
"cairo_draw"]
......@@ -124,12 +127,12 @@ def random_layout(g, shape=None, pos=None, dim=2):
pos = g.new_vertex_property("vector<double>")
_check_prop_vector(pos, name="pos")
pos = ungroup_vector_property(pos, range(0, dim))
pos = ungroup_vector_property(pos, list(range(0, dim)))
if shape == None:
shape = [sqrt(g.num_vertices())] * dim
for i in xrange(dim):
for i in range(dim):
if hasattr(shape[i], "__len__"):
if len(shape[i]) != 2:
raise ValueError("The elements of 'shape' must have size 2.")
......@@ -314,7 +317,7 @@ def _coarse_graph(g, vweight, eweight, mivs=False):
c.fa += 1
u = GraphView(g, directed=False)
infect_vertex_property(u, c,
range(1, c.fa.max() + 1))
list(range(1, c.fa.max() + 1)))
c = g.own_property(c)
else:
mivs = None
......@@ -330,7 +333,7 @@ def _coarse_graph(g, vweight, eweight, mivs=False):
def _propagate_pos(g, cg, c, cc, cpos, delta, mivs):
seed = numpy.random.randint(sys.maxint)
seed = numpy.random.randint(sys.maxsize)
pos = g.new_vertex_property(cpos.value_type())
if mivs is not None:
......@@ -382,13 +385,13 @@ def coarse_graphs(g, method="hybrid", mivs_thres=0.9, ec_thres=0.75,
break
cg.append(u)
if verbose:
print "Coarse level (%s):" % ("MIVS" if mivs else "EC"),
print len(cg), " num vertices:",
print u[0].num_vertices()
print("Coarse level (%s):" % ("MIVS" if mivs else "EC"), end=' ')
print(len(cg), " num vertices:", end=' ')
print(u[0].num_vertices())
cg.reverse()
Ks = []
pos = random_layout(cg[0][0], dim=2)
for i in xrange(len(cg)):
for i in range(len(cg)):
if i == 0:
u = cg[i][0]
K = _avg_edge_distance(u, pos)
......@@ -405,17 +408,17 @@ def coarse_graphs(g, method="hybrid", mivs_thres=0.9, ec_thres=0.75,
gamma = 0.75
Ks.append(Ks[-1] * gamma)
for i in xrange(len(cg)):
for i in range(len(cg)):
u, cc, vcount, ecount, c, mivs = cg[i]
yield u, pos, Ks[i], vcount, ecount
if verbose:
print "avg edge distance:", _avg_edge_distance(u, pos)
print("avg edge distance:", _avg_edge_distance(u, pos))
if i < len(cg) - 1:
if verbose:
print "propagating...",
print mivs.a.sum() if mivs is not None else ""
print("propagating...", end=' ')
print(mivs.a.sum() if mivs is not None else "")
pos = _propagate_pos(cg[i + 1][0], u, c, cc, pos,
Ks[i] / 1000, mivs)
......@@ -545,8 +548,8 @@ def sfdp_layout(g, vweight=None, eweight=None, pin=None, C=0.2, K=None, p=2.,
count = 0
for u, pos, K, vcount, ecount in cgs:
if verbose:
print "Positioning level:", count, u.num_vertices(),
print "with K =", K, "..."
print("Positioning level:", count, u.num_vertices(), end=' ')
print("with K =", K, "...")
count += 1
#graph_draw(u, pos)
pos = sfdp_layout(u, pos=pos,
......@@ -584,13 +587,19 @@ def sfdp_layout(g, vweight=None, eweight=None, pin=None, C=0.2, K=None, p=2.,
verbose)
return pos
from cairo_draw import graph_draw, cairo_draw
try:
from .cairo_draw import graph_draw, cairo_draw
except ImportError:
pass
try:
from cairo_draw import GraphWidget, GraphWindow, \
from .cairo_draw import GraphWidget, GraphWindow, \
interactive_window
__all__ += ["interactive_window", "GraphWidget", "GraphWindow"]
except ImportError:
pass
from graphviz_draw import graphviz_draw
try:
from .graphviz_draw import graphviz_draw
except ImportError:
pass
......@@ -18,6 +18,8 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from __future__ import division, absolute_import, print_function
import os
import warnings
......@@ -27,14 +29,17 @@ except ImportError:
msg = "Error importing cairo. Graph drawing will not work."
warnings.filterwarnings("always", msg, ImportWarning)
warnings.warn(msg, ImportWarning)
raise
try:
import matplotlib.cm
import matplotlib.colors
import matplotlib
#import matplotlib.cm
#import matplotlib.colors
except ImportError: