Commit 973d73cf authored by Tiago Peixoto's avatar Tiago Peixoto
Browse files

draw_hieararchy() and radial_tree_layout(): Add "node_weight" parameter

parent c84e5eeb
......@@ -31,19 +31,21 @@ using namespace graph_tool;
struct do_get_radial
{
template <class Graph, class PosProp, class LevelMap, class OrderMap>
template <class Graph, class PosProp, class LevelMap, class OrderMap,
class WeightMap>
void operator()(Graph& g, PosProp tpos, LevelMap level, OrderMap order,
size_t root, bool weighted, double r) const
WeightMap weight, size_t root, bool weighted, double r) const
{
typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
typedef property_map_type::apply<int, GraphInterface::vertex_index_map_t>::type
typedef typename property_map_type::apply<typename property_traits<WeightMap>::value_type,
GraphInterface::vertex_index_map_t>::type
vcount_t;
vcount_t::unchecked_t count(get(vertex_index, g), num_vertices(g));
typename vcount_t::unchecked_t count(get(vertex_index, g), num_vertices(g));
if (!weighted)
{
for (auto v : vertices_range(g))
count[v] = 1;
count[v] = weight[v];
}
else
{
......@@ -53,7 +55,7 @@ struct do_get_radial
if (out_degree(v, g) == 0)
{
q.push_back(v);
count[v] = 1;
count[v] = weight[v];
}
}
......@@ -78,7 +80,7 @@ struct do_get_radial
}
}
vector<vector<vertex_t> > layers(1);
vector<vector<vertex_t>> layers(1);
layers[0].push_back(root);
bool last = false;
......@@ -121,8 +123,11 @@ struct do_get_radial
vector<vertex_t>& outer_layer = layers.back();
for (size_t i = 0; i < outer_layer.size(); ++i)
d_sum += count[outer_layer[i]];
angle[outer_layer[0]] = (2 * M_PI * count[outer_layer[0]]) / d_sum;
for (size_t i = 1; i < outer_layer.size(); ++i)
angle[outer_layer[i]] = angle[outer_layer[i-1]] + (2 * M_PI * count[outer_layer[i]]) / d_sum;
for (size_t i = 0; i < outer_layer.size(); ++i)
angle[outer_layer[i]] = (i * 2 * M_PI * count[outer_layer[i]]) / d_sum;
angle[outer_layer[i]] -= (2 * M_PI * count[outer_layer[i]]) / (2 * d_sum);
for (size_t i = 0; i < layers.size(); ++i)
{
......@@ -151,7 +156,8 @@ struct do_get_radial
};
void get_radial(GraphInterface& gi, boost::any otpos, boost::any olevels,
boost::any oorder, size_t root, bool weighted, double r)
boost::any oorder, boost::any oweight, size_t root,
bool weighted, double r)
{
typedef property_map_type::apply<int32_t,
GraphInterface::vertex_index_map_t>::type
......@@ -159,9 +165,15 @@ void get_radial(GraphInterface& gi, boost::any otpos, boost::any olevels,
vmap_t levels = boost::any_cast<vmap_t>(olevels);
typedef property_map_type::apply<double,
GraphInterface::vertex_index_map_t>::type
wmap_t;
wmap_t weight = boost::any_cast<wmap_t>(oweight);
run_action<graph_tool::detail::always_directed>()
(gi, std::bind(do_get_radial(), placeholders::_1, placeholders::_2,
levels, placeholders::_3, root, weighted, r),
levels, placeholders::_3, weight, root, weighted, r),
vertex_scalar_vector_properties(),
vertex_properties())(otpos, oorder);
}
......
......@@ -702,7 +702,8 @@ def sfdp_layout(g, vweight=None, eweight=None, pin=None, groups=None, C=0.2,
verbose, _get_rng())
return pos
def radial_tree_layout(g, root, rel_order=None, weighted=False, r=1.):
def radial_tree_layout(g, root, rel_order=None, weighted=False,
node_weight=None, r=1.):
r"""Computes a radial layout of the graph according to the minimum spanning
tree centered at the ``root`` vertex.
......@@ -717,6 +718,9 @@ def radial_tree_layout(g, root, rel_order=None, weighted=False, r=1.):
weighted : ``bool`` (optional, default: ``False``)
If true, the angle between the child branches will be computed according
to weight of the entire sub-branches.
node_weight : :class:`~graph_tool.PropertyMap` (optional, default: ``None``)
If given, the relative spacing between leafs will correspond to the node
weights.
r : ``float`` (optional, default: ``1.``)
Layer spacing.
......@@ -762,11 +766,15 @@ def radial_tree_layout(g, root, rel_order=None, weighted=False, r=1.):
levels = t.own_property(levels)
if rel_order is None:
rel_order = g.vertex_index.copy("int")
if node_weight is None:
node_weight = g.new_vertex_property("double", 1)
elif node_weight.value_type() != "double":
node_weight = node_weight.copy("double")
libgraph_tool_layout.get_radial(t._Graph__graph,
_prop("v", g, pos),
_prop("v", g, levels),
_prop("v", g, rel_order),
_prop("v", g, node_weight),
int(root), weighted, r)
return g.own_property(pos)
......
......@@ -1524,8 +1524,8 @@ class GraphArtist(matplotlib.artist.Artist):
# ===================
#
def draw_hierarchy(state, pos=None, layout="radial", beta=0.8, vprops=None,
eprops=None, hvprops=None, heprops=None,
def draw_hierarchy(state, pos=None, layout="radial", beta=0.8, node_weight=None,
vprops=None, eprops=None, hvprops=None, heprops=None,
subsample_edges=None, deg_order=True, deg_size=True,
vsize_scale=1, hsize_scale=1, hshortcuts=0, hide=0,
empty_branches=True, **kwargs):
......@@ -1694,11 +1694,17 @@ def draw_hierarchy(state, pos=None, layout="radial", beta=0.8, vprops=None,
angle = g.new_vertex_property("double")
angle.fa = (numpy.arctan2(y.fa, x.fa) + 2 * numpy.pi) % (2 * numpy.pi)
vorder = angle
tpos = radial_tree_layout(t, root=t.vertex(t.num_vertices() - 1,
if node_weight is not None:
node_weight = t.own_property(node_weight.copy())
node_weight.a[node_weight.a == 0] = 1
tpos = radial_tree_layout(t, root=t.vertex(t.num_vertices(True) - 1,
use_index=False),
node_weight=node_weight,
rel_order=vorder)
elif layout == "bipartite":
tpos = t.own_property(get_bip_hierachy_pos(state))
tpos = get_bip_hierachy_pos(state,
node_weight=node_weight)
tpos = t.own_property(tpos)
elif layout == "sfdp":
if pos is None:
tpos = sfdp_layout(t)
......@@ -1709,7 +1715,7 @@ def draw_hierarchy(state, pos=None, layout="radial", beta=0.8, vprops=None,
K = numpy.sqrt(x.fa.std() + y.fa.std()) / 10
tpos = t.new_vertex_property("vector<double>")
for v in t.vertices():
if int(v) < g.num_vertices():
if int(v) < g.num_vertices(True):
tpos[v] = [x[v], y[v]]
else:
tpos[v] = [0, 0]
......@@ -1721,7 +1727,7 @@ def draw_hierarchy(state, pos=None, layout="radial", beta=0.8, vprops=None,
hvvisible = t.new_vertex_property("bool", True)
if hide > 0:
root = t.vertex(t.num_vertices() - 1)
root = t.vertex(t.num_vertices(True) - 1)
dist = shortest_distance(t, source=root)
hvvisible.fa = dist.fa >= hide
......@@ -1875,15 +1881,15 @@ def draw_hierarchy(state, pos=None, layout="radial", beta=0.8, vprops=None,
def update_cts(widget, gg, picked, pos, vprops, eprops):
vmask = gg.vertex_index.copy("int")
u = GraphView(gg, directed=False, vfilt=vmask.fa < g.num_vertices())
u = GraphView(gg, directed=False, vfilt=vmask.fa < g.num_vertices(True))
cts = eprops["control_points"]
get_hierarchy_control_points(u, t_orig, pos, beta, cts=cts,
max_depth=len(state.levels) - hshortcuts)
def draw_branch(widget, gg, key_id, picked, pos, vprops, eprops):
if key_id == ord('b'):
if picked is not None and not isinstance(picked, PropertyMap) and int(picked) > g.num_vertices():
p = shortest_path(t_orig, source=t_orig.vertex(t_orig.num_vertices() - 1),
if picked is not None and not isinstance(picked, PropertyMap) and int(picked) > g.num_vertices(True):
p = shortest_path(t_orig, source=t_orig.vertex(t_orig.num_vertices(True) - 1),
target=picked)[0]
l = len(state.levels) - max(len(p), 1)
......@@ -1936,8 +1942,7 @@ def draw_hierarchy(state, pos=None, layout="radial", beta=0.8, vprops=None,
angle = gg.new_vertex_property("double")
angle.fa = (numpy.arctan2(y.fa, x.fa) + 2 * numpy.pi) % (2 * numpy.pi)
tpos = radial_tree_layout(t_orig,
root=t_orig.vertex(t_orig.num_vertices() - 1,
use_index=False),
root=t_orig.vertex(t_orig.num_vertices(True) - 1),
rel_order=angle)
gg.copy_property(tpos, pos)
......@@ -1969,7 +1974,7 @@ def draw_hierarchy(state, pos=None, layout="radial", beta=0.8, vprops=None,
return pos, t_orig, tpos
def get_bip_hierachy_pos(state):
def get_bip_hierachy_pos(state, node_weight=None):
if state.overlap:
g = state.g
......@@ -2000,7 +2005,7 @@ def get_bip_hierachy_pos(state):
t, tb, order = get_hierarchy_tree(state)
root = t.vertex(t.num_vertices() - 1)
root = t.vertex(t.num_vertices(True) - 1)
if root.out_degree() > 2:
clabel = is_bipartite(g, partition=True)[1].copy("int")
if state.overlap:
......@@ -2030,7 +2035,7 @@ def get_bip_hierachy_pos(state):
if v.in_degree() == 0:
break
if v.out_degree() == 0:
w[v] = 1
w[v] = 1 if node_weight is None else node_weight[v]
parent, = v.in_neighbours()
w[parent] += w[v]
......@@ -2040,7 +2045,8 @@ def get_bip_hierachy_pos(state):
p1, p2 = root.out_neighbours()
if w[p1] > w[p2]:
if ((w[p1] == w[p2] and p1.out_degree() > p2.out_degree()) or
w[p1] > w[p2]):
p1, p2 = p2, p1
L = len(state.levels)
......@@ -2052,14 +2058,14 @@ def get_bip_hierachy_pos(state):
while len(roots) > 0:
nroots = []
for r in roots:
cw = pos[r][1] - w[r] / 2 / w[p]
cw = pos[r][1] - w[r] / (2. * w[p])
for v in sorted(r.out_neighbours(), key=lambda a: order[a]):
pos[v] = (0, 0)
if i == 0:
pos[v][0] = pos[r][0] - 1 / L * .5
else:
pos[v][0] = pos[r][0] + 1 / L * .5
pos[v][1] = cw + w[v] / 2 / w[p]
pos[v][1] = cw + w[v] / (2. * w[p])
cw += w[v] / w[p]
nroots.append(v)
roots = nroots
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment