Commit 73fe12a8 authored by Tiago Peixoto's avatar Tiago Peixoto

Implement layout module ('draw' from python) and arf layout

This implements a layout module (called 'draw' from python) with an
implementation of the arf spring-block layout.
parent 0db15a14
......@@ -294,6 +294,7 @@ src/graph/community/Makefile
src/graph/util/Makefile
src/graph/topology/Makefile
src/graph/flow/Makefile
src/graph/layout/Makefile
src/graph_tool/Makefile
])
......
## Process this file with automake to produce Makefile.in
SUBDIRS = generation stats clustering community util topology centrality correlations flow
SUBDIRS = generation stats clustering community util topology centrality correlations flow layout
AM_CPPFLAGS =\
-I$(srcdir)/.. \
......@@ -24,6 +24,8 @@ libgraph_tool_core_la_SOURCES = \
graph_filtering.cc \
graph_io.cc \
graph_properties.cc \
graph_properties_group.cc \
graph_properties_ungroup.cc \
graph_python_interface.cc \
graph_python_interface_export.cc \
graph_selectors.cc \
......@@ -39,6 +41,7 @@ libgraph_tool_core_la_include_HEADERS = \
graph_filtering.hh \
graph.hh \
graph_properties.hh \
graph_properties_group.hh \
graph_python_interface.hh \
graph_selectors.hh \
graph_util.hh \
......
## Process this file with automake to produce Makefile.in
AM_CPPFLAGS = $(MOD_CPPFLAGS)
AM_CFLAGS = $(AM_CXXFLAGS)
libgraph_tool_layoutdir = $(pythondir)/graph_tool/draw
libgraph_tool_layout_LTLIBRARIES = libgraph_tool_layout.la
libgraph_tool_layout_la_includedir = $(pythondir)/graph_tool/include
libgraph_tool_layout_la_LIBADD = $(MOD_LIBADD)
libgraph_tool_layout_la_LDFLAGS = $(MOD_LDFLAGS)
libgraph_tool_layout_la_SOURCES = \
graph_arf.cc \
graph_bind_layout.cc
libgraph_tool_layout_la_include_HEADERS = \
graph_arf.hh
// graph-tool -- a general graph modification and manipulation thingy
//
// Copyright (C) 2007 Tiago de Paula Peixoto <tiago@forked.de>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "graph_filtering.hh"
#include "graph.hh"
#include "graph_properties.hh"
#include <boost/lambda/bind.hpp>
#include "graph_arf.hh"
using namespace std;
using namespace boost;
using namespace graph_tool;
void arf_layout(GraphInterface& g, boost::any pos, boost::any weight, double d,
double a, double dt, size_t max_iter, double epsilon,
size_t dim)
{
typedef ConstantPropertyMap<int32_t,GraphInterface::edge_t> weight_map_t;
typedef mpl::push_back<edge_scalar_properties, weight_map_t>::type
edge_props_t;
if(weight.empty())
weight = weight_map_t(1);
run_action<graph_tool::detail::never_directed>()
(g,
lambda::bind<void>(get_arf_layout(), lambda::_1, lambda::_2,
lambda::_3, a, d, dt, epsilon, max_iter, dim),
vertex_floating_vector_properties(), edge_props_t())(pos, weight);
}
#include <boost/python.hpp>
void export_arf()
{
python::def("arf_layout", &arf_layout);
}
// graph-tool -- a general graph modification and manipulation thingy
//
// Copyright (C) 2007 Tiago de Paula Peixoto <tiago@forked.de>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef GRAPH_ARF_HH
#define GRAPH_ARF_HH
#include <tr1/random>
#include <limits>
#include <iostream>
namespace graph_tool
{
using namespace std;
using namespace boost;
struct get_arf_layout
{
template <class Graph, class PosMap, class WeightMap>
void operator()(Graph& g, PosMap pos, WeightMap weight, double a, double d,
double dt, double epsilon, size_t max_iter, size_t dim)
const
{
typedef typename property_traits<PosMap>::value_type::value_type pos_t;
int i, N = num_vertices(g);
#pragma omp parallel for default(shared) private(i)
for (i = 0; i < N; ++i)
{
typename graph_traits<Graph>::vertex_descriptor v =
vertex(i, g);
if (v == graph_traits<Graph>::null_vertex())
continue;
pos[v].resize(dim);
}
pos_t delta = epsilon + 1;
size_t n_iter = 0;
pos_t r = d*sqrt(pos_t(HardNumVertices()(g)));
while (delta > epsilon && (max_iter == 0 || n_iter < max_iter))
{
delta = 0;
#pragma omp parallel for default(shared) private(i) \
reduction(+:delta)
for (i = 0; i < N; ++i)
{
typename graph_traits<Graph>::vertex_descriptor v =
vertex(i, g);
if (v == graph_traits<Graph>::null_vertex())
continue;
vector<pos_t> delta_pos(dim,0);
typename graph_traits<Graph>::vertex_iterator w, w_end;
for (tie(w, w_end) = vertices(g); w != w_end; ++w)
{
if (*w == v)
continue;
pos_t diff = 0;
for (size_t j = 0; j < dim; ++j)
{
pos_t dx = pos[*w][j] - pos[v][j];
diff += dx*dx;
delta_pos[j] += dx;
}
diff = sqrt(diff);
if (diff < 1e-6)
diff = 1e-6;
pos_t m = r/diff;
for (size_t j = 0; j < dim; ++j)
{
pos_t dx = pos[*w][j] - pos[v][j];
delta_pos[j] -= m*dx;
}
}
typename graph_traits<Graph>::out_edge_iterator e, e_end;
for (tie(e,e_end) = out_edges(v, g); e != e_end; ++e)
{
typename graph_traits<Graph>::vertex_descriptor u =
target(*e, g);
if (u == v)
continue;
pos_t m = a*get(weight, *e) - 1;
for (size_t j = 0; j < dim; ++j)
{
pos_t dx = pos[u][j] - pos[v][j];
delta_pos[j] += m*dx;
}
}
for (size_t j = 0; j < dim; ++j)
{
pos[v][j] += dt*delta_pos[j];
delta += abs(delta_pos[j]);
}
}
n_iter++;
}
}
};
} // namespace graph_tool
#endif // GRAPH_ARF_HH
// graph-tool -- a general graph modification and manipulation thingy
//
// Copyright (C) 2007 Tiago de Paula Peixoto <tiago@forked.de>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <boost/python.hpp>
using namespace boost::python;
void export_arf();
BOOST_PYTHON_MODULE(libgraph_tool_layout)
{
export_arf();
}
This diff is collapsed.
......@@ -22,9 +22,15 @@
"""
import sys, os, os.path, time, warnings
from .. core import _degree, _prop, PropertyMap
from .. core import _degree, _prop, PropertyMap, _check_prop_vector,\
_check_prop_scalar, _check_prop_writable, group_vector_property,\
ungroup_vector_property
from .. decorators import _limit_args
import numpy.random
from numpy import *
from .. dl_import import dl_import
dl_import("import libgraph_tool_layout")
try:
import gv
......@@ -38,6 +44,8 @@ except ImportError:
warnings.warn("error importing matplotlib module... " + \
"graph_draw() will not work.", ImportWarning)
__all__ = ["graph_draw", "arf_layout", "random_layout"]
def graph_draw(g, pos=None, size=(15, 15), pin=False, layout= "neato",
maxiter=None, ratio= "fill", overlap="prism", sep=None,
splines=False, vsize=0.1, penwidth=1.0, elen=None, gprops={},
......@@ -59,7 +67,7 @@ def graph_draw(g, pos=None, size=(15, 15), pin=False, layout= "neato",
If True, the vertices are not moved from their initial position.
layout : string (default: "neato")
Layout engine to be used. Possible values are "neato", "fdp", "dot",
"circo" and "twopi".
"circo", "twopi" and "arf".
maxiter : int (default: None)
If specified, limits the maximum number of iterations.
ratio : string or float (default: "fill")
......@@ -241,9 +249,17 @@ def graph_draw(g, pos=None, size=(15, 15), pin=False, layout= "neato",
else:
gvg = gv.graph("G")
if layout == "arf":
layout = "neato"
pos = arf_layout(g, pos=pos)
pin = True
if pos != None:
# copy user-supplied property
pos = (g.copy_property(pos[0]), g.copy_property(pos[1]))
if isinstance(pos, PropertyMap):
pos = ungroup_vector_property(g, pos, [0,1])
else:
pos = (g.copy_property(pos[0]), g.copy_property(pos[1]))
# main graph properties
gv.setv(gvg,"outputorder", "edgesfirst")
......@@ -429,9 +445,44 @@ def graph_draw(g, pos=None, size=(15, 15), pin=False, layout= "neato",
pos[0].get_array()[:] /= 100
pos[1].get_array()[:] /= 100
pos = group_vector_property(g, pos)
if returngv:
return pos, gv
else:
gv.rm(gvg)
del gvg
return pos
def random_layout(g, shape=None, pos=None, dim=2):
if pos == None:
pos = [g.new_vertex_property("double") for i in xrange(dim)]
if isinstance(pos, PropertyMap) and "vector" in pos.value_type():
pos = ungroup_vector_property(pos)
if shape == None:
shape = (sqrt(g.num_vertices()), sqrt(g.num_vertices()))
for i in xrange(dim):
_check_prop_scalar(pos[i], name="pos[%d]" % i)
_check_prop_writable(pos[i], name="pos[%d]" % i)
a = pos[i].get_array()
a[:] = numpy.random.random(len(a))*shape[i]
pos = group_vector_property(g, pos)
return pos
def arf_layout(g, weight=None, d=0.1, a=10, dt=0.001, epsilon=1e-6,
max_iter=1000, pos=None, dim=2):
if pos == None:
pos = random_layout(g, dim=dim)
_check_prop_vector(pos, name="pos", floating=True)
g.stash_filter(directed=True)
g.set_directed(False)
libgraph_tool_layout.arf_layout(g._Graph__graph, _prop("v", g, pos),
_prop("e", g, weight), d, a, dt, max_iter,
epsilon, dim)
g.pop_filter()
return pos
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