Commit 3a95582f authored by Tiago Peixoto's avatar Tiago Peixoto

Implement `return_maps` option in motifs()

This returns an optional list of locations of the motifs found in the
main graph.
parent 1e2702b4
...@@ -56,8 +56,8 @@ using namespace boost::python; ...@@ -56,8 +56,8 @@ using namespace boost::python;
void extended_clustering(GraphInterface& g, python::list props); void extended_clustering(GraphInterface& g, python::list props);
void get_motifs(GraphInterface& g, size_t k, python::list subgraph_list, void get_motifs(GraphInterface& g, size_t k, python::list subgraph_list,
python::list hist, python::list p, bool comp_iso, python::list hist, python::list pvmaps, bool collect_vmaps,
bool fill_list, rng_t& rng); python::list p, bool comp_iso, bool fill_list, rng_t& rng);
BOOST_PYTHON_MODULE(libgraph_tool_clustering) BOOST_PYTHON_MODULE(libgraph_tool_clustering)
{ {
......
...@@ -22,6 +22,8 @@ ...@@ -22,6 +22,8 @@
#include "graph_properties.hh" #include "graph_properties.hh"
#include "graph_util.hh" #include "graph_util.hh"
#include "graph_python_interface.hh"
#include "graph_motifs.hh" #include "graph_motifs.hh"
#include <boost/python.hpp> #include <boost/python.hpp>
...@@ -66,8 +68,8 @@ struct retrieve_from_list ...@@ -66,8 +68,8 @@ struct retrieve_from_list
}; };
void get_motifs(GraphInterface& g, size_t k, python::list subgraph_list, void get_motifs(GraphInterface& g, size_t k, python::list subgraph_list,
python::list hist, python::list p, bool comp_iso, python::list hist, python::list pvmaps, bool collect_vmaps,
bool fill_list, rng_t& rng) python::list p, bool comp_iso, bool fill_list, rng_t& rng)
{ {
boost::any list; boost::any list;
if (g.GetDirected()) if (g.GetDirected())
...@@ -105,15 +107,29 @@ void get_motifs(GraphInterface& g, size_t k, python::list subgraph_list, ...@@ -105,15 +107,29 @@ void get_motifs(GraphInterface& g, size_t k, python::list subgraph_list,
else else
sampler = sample_some(plist, rng); sampler = sample_some(plist, rng);
typedef property_map_type
::apply<int32_t, GraphInterface::vertex_index_map_t>::type
vmap_t;
vector<vector<vmap_t> > vmaps;
run_action<>() run_action<>()
(g, boost::bind<void>(get_all_motifs(), _1, k, boost::ref(list), (g, boost::bind<void>(get_all_motifs(collect_vmaps, plist[0], comp_iso,
boost::ref(phist), _2, fill_list, rng),
plist[0], comp_iso, fill_list, boost::ref(rng)), _1, k, boost::ref(list), boost::ref(phist),
boost::ref(vmaps),_2),
mpl::vector<sample_all,sample_some>())(sampler); mpl::vector<sample_all,sample_some>())(sampler);
for (size_t i = 0; i < phist.size(); ++i) for (size_t i = 0; i < phist.size(); ++i)
hist.append(phist[i]); hist.append(phist[i]);
for (size_t i = 0; i < vmaps.size(); ++i)
{
python::list vlist;
for (size_t j = 0; j < vmaps[i].size(); ++j)
vlist.append(PythonPropertyMap<vmap_t>(vmaps[i][j]));
pvmaps.append(vlist);
}
if (fill_list) if (fill_list)
{ {
for (int i = 0; i < python::len(subgraph_list); ++i) for (int i = 0; i < python::len(subgraph_list); ++i)
......
...@@ -288,10 +288,20 @@ void get_sig(Graph& g, vector<size_t>& sig) ...@@ -288,10 +288,20 @@ void get_sig(Graph& g, vector<size_t>& sig)
// gets (or samples) all the subgraphs in graph g // gets (or samples) all the subgraphs in graph g
struct get_all_motifs struct get_all_motifs
{ {
template <class Graph, class Sampler> get_all_motifs(bool collect_vmaps, double p, bool comp_iso, bool fill_list,
rng_t& rng)
: collect_vmaps(collect_vmaps), p(p),
comp_iso(comp_iso), fill_list(fill_list), rng(rng) {}
bool collect_vmaps;
double p;
bool comp_iso;
bool fill_list;
rng_t& rng;
template <class Graph, class Sampler, class VMap>
void operator()(Graph& g, size_t k, boost::any& list, void operator()(Graph& g, size_t k, boost::any& list,
vector<size_t>& hist, Sampler sampler, double p, vector<size_t>& hist, vector<vector<VMap> >& vmaps,
bool comp_iso, bool fill_list, rng_t& rng) const Sampler sampler) const
{ {
typedef typename mpl::if_<typename is_directed::apply<Graph>::type, typedef typename mpl::if_<typename is_directed::apply<Graph>::type,
d_graph_t, d_graph_t,
...@@ -377,6 +387,7 @@ struct get_all_motifs ...@@ -377,6 +387,7 @@ struct get_all_motifs
} }
bool found = false; bool found = false;
size_t pos;
typeof(sub_list.begin()) sl = sub_list.find(sig); typeof(sub_list.begin()) sl = sub_list.find(sig);
if (sl != sub_list.end()) if (sl != sub_list.end())
{ {
...@@ -397,7 +408,8 @@ struct get_all_motifs ...@@ -397,7 +408,8 @@ struct get_all_motifs
} }
if (found) if (found)
{ {
hist[sl->second[l].first]++; pos = sl->second[l].first;
hist[pos]++;
break; break;
} }
} }
...@@ -409,6 +421,17 @@ struct get_all_motifs ...@@ -409,6 +421,17 @@ struct get_all_motifs
sub_list[sig].push_back(make_pair(subgraph_list.size() - 1, sub_list[sig].push_back(make_pair(subgraph_list.size() - 1,
sub)); sub));
hist.push_back(1); hist.push_back(1);
pos = hist.size() - 1;
found = true;
}
if (found && collect_vmaps)
{
if (pos >= vmaps.size())
vmaps.resize(pos + 1);
vmaps[pos].push_back(VMap(get(boost::vertex_index,sub)));
for (size_t vi = 0; vi < num_vertices(sub); ++vi)
vmaps[pos].back()[vertex(vi, sub)] = subgraphs[j][vi];
} }
} }
} }
......
...@@ -46,7 +46,7 @@ from __future__ import division, absolute_import, print_function ...@@ -46,7 +46,7 @@ from __future__ import division, absolute_import, print_function
from .. dl_import import dl_import from .. dl_import import dl_import
dl_import("from . import libgraph_tool_clustering as _gt") dl_import("from . import libgraph_tool_clustering as _gt")
from .. import _degree, _prop, Graph, GraphView, _get_rng from .. import _degree, _prop, Graph, GraphView, PropertyMap, _get_rng
from .. topology import isomorphism from .. topology import isomorphism
from .. generation import random_rewire from .. generation import random_rewire
from .. stats import vertex_hist from .. stats import vertex_hist
...@@ -284,7 +284,7 @@ def extended_clustering(g, props=None, max_depth=3, undirected=False): ...@@ -284,7 +284,7 @@ def extended_clustering(g, props=None, max_depth=3, undirected=False):
return props return props
def motifs(g, k, p=1.0, motif_list=None): def motifs(g, k, p=1.0, motif_list=None, return_maps=False):
r""" r"""
Count the occurrence of k-size subgraphs (motifs). A tuple with two lists is Count the occurrence of k-size subgraphs (motifs). A tuple with two lists is
returned: the list of motifs found, and the list with their respective returned: the list of motifs found, and the list with their respective
...@@ -296,7 +296,7 @@ def motifs(g, k, p=1.0, motif_list=None): ...@@ -296,7 +296,7 @@ def motifs(g, k, p=1.0, motif_list=None):
Graph to be used. Graph to be used.
k : int k : int
number of vertices of the motifs number of vertices of the motifs
p : float or float list (optional, default: 1.0) p : float or float list (optional, default: `1.0`)
uniform fraction of the motifs to be sampled. If a float list is uniform fraction of the motifs to be sampled. If a float list is
provided, it will be used as the fraction at each depth provided, it will be used as the fraction at each depth
:math:`[1,\dots,k]` in the algorithm. See [wernicke-efficient-2006]_ for :math:`[1,\dots,k]` in the algorithm. See [wernicke-efficient-2006]_ for
...@@ -304,6 +304,10 @@ def motifs(g, k, p=1.0, motif_list=None): ...@@ -304,6 +304,10 @@ def motifs(g, k, p=1.0, motif_list=None):
motif_list : list of :class:`~graph_tool.Graph` objects, optional motif_list : list of :class:`~graph_tool.Graph` objects, optional
If supplied, the algorithms will only search for the motifs in this list If supplied, the algorithms will only search for the motifs in this list
(or isomorphisms). (or isomorphisms).
return_maps : bool (optional, default `False`)
If true, a list will be returned, which provide for each motif graph a
list of vertex property maps which map the motif to its location in the
main graph.
Returns Returns
------- -------
...@@ -314,6 +318,9 @@ def motifs(g, k, p=1.0, motif_list=None): ...@@ -314,6 +318,9 @@ def motifs(g, k, p=1.0, motif_list=None):
out-degree-sequence, and number of edges (in this order). out-degree-sequence, and number of edges (in this order).
counts : list of ints counts : list of ints
The number of times the respective motif in the motifs list was counted The number of times the respective motif in the motifs list was counted
vertex_maps : list of lists of :class:`~graph_tool.PropertyMap` objects
List for each motif graph containing the locations in the main
graph. This is only returned if `return_maps == True`.
See Also See Also
-------- --------
...@@ -375,9 +382,10 @@ def motifs(g, k, p=1.0, motif_list=None): ...@@ -375,9 +382,10 @@ def motifs(g, k, p=1.0, motif_list=None):
pd = [float(x) for x in p] pd = [float(x) for x in p]
hist = [] hist = []
vertex_maps = []
was_directed = g.is_directed() was_directed = g.is_directed()
_gt.get_motifs(g._Graph__graph, k, sub_list, hist, pd, _gt.get_motifs(g._Graph__graph, k, sub_list, hist, vertex_maps,
True, len(sub_list) == 0, return_maps, pd, True, len(sub_list) == 0,
_get_rng()) _get_rng())
# assemble graphs # assemble graphs
...@@ -402,6 +410,11 @@ def motifs(g, k, p=1.0, motif_list=None): ...@@ -402,6 +410,11 @@ def motifs(g, k, p=1.0, motif_list=None):
sub_list = [x[0] for x in list_hist] sub_list = [x[0] for x in list_hist]
hist = [x[1] for x in list_hist] hist = [x[1] for x in list_hist]
if return_maps:
for i, vlist in enumerate(vertex_maps):
sub = sub_list[i]
vertex_maps[i] = [PropertyMap(vm, sub, "v") for vm in vlist]
return sub_list, hist, vertex_maps
return sub_list, hist return sub_list, hist
......
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