Commit 11e2b682 authored by Tiago Peixoto's avatar Tiago Peixoto
Browse files

Documentation update, following new graph_draw() function

parent 7ae9a870
PDFIMAGES = $(shell ls *.pdf)
PNGIMAGES = ${PDFIMAGES:.pdf=.png}
HUGEIMAGES = $(shell find . -maxdepth 1 -name "*.pdf" -size +1000k)
HUGEIMAGES = $(shell find . -maxdepth 1 -name "*.pdf" -size +10000k)
ORIGIMAGES = ${HUGEIMAGES:.pdf=.pdf-orig}
PNGCONV = gm convert -density 600 -resample 50 -trim -antialias -quality 9 -filter Cubic
#PNGCONV = gm convert -density 1200 -resample 50 -trim -antialias -quality 9 -filter Cubic
PNGCONV = pdftoppm -png -singlefile -r 96 -freetype yes -aa yes -aaVector yes
PDFCONV = gm convert
all: $(ORIGIMAGES) $(PNGIMAGES)
sphinx-build -E -b html . build
%.pdf-orig: %.pdf
cp $< $@
gm mogrify -resize 600 -trim -antialias -filter Cubic $<
$(PNGCONV) $< > $@-tmp.png
$(PDFCONV) $@-tmp.png $@
rm $@-tmp.png
%.png: %.pdf
test -d $<-orig && $(PNGCONV) $<-orig $@ || true
test -d $<-orig || $(PNGCONV) $< $@ || true
test -d $<-orig && $(PNGCONV) $<-orig > $@ || true
test -d $<-orig || $(PNGCONV) $< > $@ || true
latex:
sphinx-build -E -b latex . build
......
This diff is collapsed.
......@@ -26,7 +26,8 @@ sys.path.append(os.path.abspath('.'))
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest',
'sphinx.ext.intersphinx', 'mathjax', 'sphinx.ext.autosummary',
'sphinxext.numpydoc', 'sphinx.ext.extlinks']
'sphinxext.numpydoc', 'sphinx.ext.extlinks',
'matplotlib.sphinxext.plot_directive']
mathjax_path = "MathJax/MathJax.js"
......@@ -92,47 +93,7 @@ pygments_style = 'sphinx'
# doctest
doctest_global_setup = \
r"""
from matplotlib import rc
from matplotlib import rcParams
font_size=12
rcParams["figure.figsize"] = (4,3)
rcParams["font.family"] = "serif"
rcParams["font.serif"] = ["Palatino"]
rcParams["font.size"] = font_size
rcParams["axes.labelsize"] = font_size
rcParams["xtick.labelsize"] = font_size
rcParams["ytick.labelsize"] = font_size
rcParams["legend.numpoints"] = 1
rcParams["legend.fontsize"] = "small"
rcParams["lines.markersize"] = 4
rcParams["figure.subplot.right"] = 0.95
rcParams["figure.subplot.top"] = 0.95
rcParams["figure.subplot.right"] = 0.95
rcParams["figure.subplot.top"] = 0.95
rcParams["figure.subplot.left"] = 0.2
rcParams["figure.subplot.bottom"] = 0.2
rcParams["text.usetex"] = True
rcParams["ps.usedistiller"] = "xpdf"
rcParams["pdf.compression"] = 9
rcParams["ps.useafm"] = True
rcParams["path.simplify"] = True
rcParams["text.latex.preamble"] = ["\usepackage{times}",
#"\usepackage{euler}",
"\usepackage{amssymb}",
"\usepackage{amsmath}"]
from numpy import *
import scipy
import scipy.stats
from math import *
import numpy as np
import graph_tool.all as gt
"""
doctest_global_setup = open("pyenv.py").read()
# Options for HTML outputs
# -----------------------
......@@ -232,10 +193,9 @@ latex_elements = {
# Example configuration for intersphinx: refer to the Python standard library.
intersphinx_mapping = {'python': ('http://docs.python.org', None),
'numpy': ('http://docs.scipy.org/doc/numpy', None),
'scipy': ('http://docs.scipy.org/doc/scipy/reference',
None),
'matplotlib': ('http://matplotlib.sourceforge.net',
None)}
'scipy': ('http://docs.scipy.org/doc/scipy/reference', None),
'matplotlib': ('http://matplotlib.sourceforge.net', None),
'cairo': ('http://www.cairographics.org/documentation/pycairo/3/', None)}
extlinks = {'ticket': ('http://projects.skewed.de/graph-tool/ticket/%s',
'ticket '),
......@@ -247,3 +207,8 @@ extlinks = {'ticket': ('http://projects.skewed.de/graph-tool/ticket/%s',
numpydoc_show_class_members = False
autodoc_member_order = 'bysource'
autodoc_docstring_signature = False
# plot directive
import pyenv
plot_rcparams = pyenv.rcParams
#plot_pre_code = open("pyenv.py").read()
.. automodule:: graph_tool.draw
:members:
:undoc-members:
Layout algorithms
=================
.. autofunction:: sfdp_layout
.. autofunction:: fruchterman_reingold_layout
.. autofunction:: arf_layout
.. autofunction:: random_layout
Graph drawing
=============
.. autofunction:: graph_draw
.. autofunction:: graphviz_draw
Low-level graph drawing
^^^^^^^^^^^^^^^^^^^^^^^
.. autofunction:: cairo_draw
.. autofunction:: interactive_window
.. autoclass:: GraphWidget
:members:
:undoc-members:
.. autoclass:: GraphWindow
:members:
:undoc-members:
@import url("flasky.css");
table.docutils {
margin-left:1em;
margin-right:1em;
}
table.docutils td {
padding-left: 0.5em;
}
table.docutils.field-list
{
table.docutils.field-list {
margin-left: 0;
margin-right: 0;
border-collapse: separate;
border-spacing: 0em 1em;
}
......@@ -16,6 +22,12 @@ table.docutils td.field-body {
padding-left: 1em;
}
table.docutils.citation
{
margin-left: 0;
margin-right: 0;
}
/* stupid workaround to hide ugly c++ signature stuff from sphinx*/
dl.method dl.last {
visibility: collapse;
......
......@@ -52,21 +52,6 @@ for i in xrange(1, N):
vlist.append(v)
# now we have a graph!
# let's calculate its in-degree distribution and plot it to a file
in_hist = vertex_hist(g, "in")
figure(figsize=(4, 3))
errorbar(in_hist[1][:-1], in_hist[0], fmt="o", yerr=sqrt(in_hist[0]),
label="in")
gca().set_yscale("log")
gca().set_xscale("log")
gca().set_ylim(1e-1, 1e5)
gca().set_xlim(0.8, 1e3)
subplots_adjust(left=0.2, bottom=0.2)
xlabel("$k_{in}$")
ylabel("$NP(k_{in})$")
savefig("deg-hist.pdf")
# let's do a random walk on the graph and print the age of the vertices we find,
# just for fun.
......
from matplotlib import rc
from matplotlib import rcParams
font_size=14
rcParams["figure.figsize"] = (6,4.5)
rcParams["font.family"] = "Serif"
rcParams["font.serif"] = ["Palatino"]
rcParams["font.size"] = font_size
rcParams["axes.labelsize"] = font_size
rcParams["xtick.labelsize"] = font_size - 2
rcParams["ytick.labelsize"] = font_size - 2
rcParams["legend.numpoints"] = 1
rcParams["legend.fontsize"] = "small"
rcParams["lines.markersize"] = 4
rcParams["figure.subplot.right"] = 0.95
rcParams["figure.subplot.top"] = 0.95
rcParams["figure.subplot.right"] = 0.95
rcParams["figure.subplot.top"] = 0.95
rcParams["figure.subplot.left"] = 0.2
rcParams["figure.subplot.bottom"] = 0.2
rcParams["text.usetex"] = True
rcParams["ps.usedistiller"] = "xpdf"
rcParams["pdf.compression"] = 9
rcParams["ps.useafm"] = True
rcParams["path.simplify"] = True
rcParams["text.latex.preamble"] = [#"\usepackage{times}",
#"\usepackage{euler}",
"\usepackage{amssymb}",
"\usepackage{amsmath}"]
from numpy import *
import scipy
import scipy.stats
from math import *
import numpy as np
import graph_tool.all as gt
......@@ -83,7 +83,8 @@ visualize the graph we created so far with the
.. doctest::
>>> graph_draw(g, vprops={"label": g.vertex_index}, output="two-nodes.pdf")
>>> graph_draw(g, vertex_text=g.vertex_index, vertex_font_size=18,
... output_size=(200, 200), output="two-nodes.pdf")
<...>
.. figure:: two-nodes.*
......@@ -140,11 +141,11 @@ Edges and vertices can also be removed at any time with the
.. note::
Removing a vertex is an :math:`O(N)` operation. The vertices are
internally stored in a STL vector, so removing an element somewhere
in the middle of the list requires the shifting of the rest of the
list. Thus, fast :math:`O(1)` removals are only possible if one can
guarantee that only vertices in the end of the list are removed (the
ones last added to the graph).
internally stored in a `STL vector <http://en.wikipedia.org/wiki/Vector_%28STL%29>`_,
so removing an element somewhere in the middle of the list requires
the shifting of the rest of the list. Thus, fast :math:`O(1)`
removals are only possible if one can guarantee that only vertices in
the end of the list are removed (the ones last added to the graph).
Removing an edge is an :math:`O(k_{s} + k_{t})` operation, where
:math:`k_{s}` is the out-degree of the source vertex, and
......@@ -455,10 +456,35 @@ This is the degree distribution, with 100000 nodes. If you want to see a broader
power law, try to increase the number of vertices to something like :math:`10^6`
or :math:`10^7`.
.. figure:: deg-hist.*
.. plot::
:context:
:align: center
In-degree distribution of a price network with 100000 nodes.
#from pyenv import *
from pylab import *
import graph_tool.all as gt
g = gt.load_graph("price.xml.gz")
in_hist = gt.vertex_hist(g, "in")
figure()
y = in_hist[0]
err = sqrt(in_hist[0])
err[err >= y] = y[err >= y] - 1e-2
errorbar(in_hist[1][:-1], in_hist[0], fmt="o", yerr=err,
label="in")
gca().set_yscale("log")
gca().set_xscale("log")
gca().set_ylim(1e-1, 1e5)
gca().set_xlim(0.8, 1e3)
subplots_adjust(left=0.2, bottom=0.2)
xlabel("$k_{in}$")
ylabel("$NP(k_{in})$")
Title ("In-degree distribution of a price network with $10^5$ nodes.")
tight_layout()
show()
We can draw the graph to see some other features of its topology. For that we
use the :func:`~graph_tool.draw.graph_draw` function.
......@@ -467,7 +493,9 @@ use the :func:`~graph_tool.draw.graph_draw` function.
g = load_graph("price.xml.gz")
age = g.vertex_properties["age"]
graph_draw(g, size=(15,15), vcolor=age, output="price.pdf")
graph_draw(g, output_size=(1000, 1000), vertex_color=age,
vertex_fill_color=age, vertex_size=2.5, edge_pen_width=1.5,
output="price.png")
.. figure:: price.*
:align: center
......@@ -512,7 +540,8 @@ edge filtering.
g, pos = triangulation(random((500, 2)) * 4, type="delaunay")
tree = min_spanning_tree(g)
graph_draw(g, pos=pos, pin=True, size=(8, 8), ecolor=tree, output="min_tree.pdf")
graph_draw(g, pos=pos, edge_color=tree, output_size=(400, 400),
output="min_tree.pdf")
The ``tree`` property map has a bool type, with value "1" if the edge belongs to
the tree, and "0" otherwise. Below is an image of the original graph, with the
......@@ -526,7 +555,7 @@ We can now filter out the edges which don't belong to the minimum spanning tree.
.. testcode::
g.set_edge_filter(tree)
graph_draw(g, pos=pos, pin=True, size=(8, 8), output="min_tree_filtered.pdf")
graph_draw(g, pos=pos, output_size=(400, 400), output="min_tree_filtered.pdf")
This is how the graph looks when filtered:
......@@ -541,9 +570,9 @@ and draws them as colors and line thickness in the graph.
.. testcode::
bv, be = betweenness(g)
be.a *= 10
graph_draw(g, pos=pos, pin=True, size=(8,8), vsize=0.07, vcolor=bv,
eprops={"penwidth":be}, output="filtered-bt.pdf")
be.a /= be.a.max() / 5
graph_draw(g, pos=pos, vertex_fill_color=bv, edge_pen_width=be,
output_size=(400, 400), output="filtered-bt.pdf")
.. figure:: filtered-bt.*
:align: center
......@@ -555,9 +584,9 @@ The original graph can be recovered by setting the edge filter to ``None``.
g.set_edge_filter(None)
bv, be = betweenness(g)
be.a *= 10
graph_draw(g, pos=pos, pin=True, size=(8,8), vsize=0.07, vcolor=bv,
eprops={"penwidth":be}, output="nonfiltered-bt.pdf")
be.a /= be.a.max() / 5
graph_draw(g, pos=pos, vertex_fill_color=bv, edge_pen_width=be,
output_size=(400, 400), output="nonfiltered-bt.pdf")
.. figure:: nonfiltered-bt.*
:align: center
......@@ -611,9 +640,10 @@ Like above, the result should be the isolated minimum spanning tree:
.. doctest::
>>> bv, be = betweenness(tv)
>>> be.a *= 10
>>> graph_draw(tv, pos=pos, pin=True, size=(8,8), vsize=0.07, vcolor=bv,
... eprops={"penwidth":be}, output="mst-view.pdf")
>>> be.a /= be.a.max() / 5
>>> graph_draw(tv, pos=pos, vertex_fill_color=bv,
... edge_pen_width=be, output_size=(400, 400),
... output="mst-view.pdf")
<...>
......@@ -643,22 +673,23 @@ edges, we can do:
.. doctest::
>>> bv, be = betweenness(g)
>>> u = GraphView(g, efilt=lambda e: be[e] > 0.01)
>>> u = GraphView(g, efilt=lambda e: be[e] > be.a.max() / 2)
This creates a graph view ``u`` which contains only the edges of ``g``
which have a normalized betweenness centrality larger than 0.01. Note
that, differently from the case above, this is an :math:`O(E)`
operation, where :math:`E` is the number of edges, since the supplied
function must be called :math:`E` times to construct a filter property
map. Thus, supplying a constructed filter map is always faster, but
supplying a function can be more convenient.
which have a normalized betweenness centrality larger than half of the
maximum value. Note that, differently from the case above, this is an
:math:`O(E)` operation, where :math:`E` is the number of edges, since
the supplied function must be called :math:`E` times to construct a
filter property map. Thus, supplying a constructed filter map is always
faster, but supplying a function can be more convenient.
The graph view constructed above can be visualized as
.. doctest::
>>> graph_draw(u, pos=pos, pin=True, size=(8,8), vsize=0.07, vcolor=bv,
... output="central-edges-view.pdf")
>>> be.a /= be.a.max() / 5
>>> graph_draw(u, pos=pos, vertex_fill_color=bv, output_size=(400, 400),
... output="central-edges-view.pdf")
<...>
.. figure:: central-edges-view.*
......@@ -671,10 +702,10 @@ Composing graph views
"""""""""""""""""""""
Since graph views are regular graphs, one can just as easily create
graph views of graph views. This provides a convenient way of composing
filters. For instance, in order to isolate the minimum spanning tree of
all vertices of the example above which have a degree larger than four,
one can do:
graph views `of graph views`. This provides a convenient way of
composing filters. For instance, in order to isolate the minimum
spanning tree of all vertices of the example above which have a degree
larger than four, one can do:
>>> u = GraphView(g, vfilt=lambda v: v.out_degree() > 4)
......@@ -685,8 +716,7 @@ The resulting graph view can be visualized as
.. doctest::
>>> graph_draw(u, pos=pos, pin=True, size=(8,8), vsize=0.07,
... output="composed-filter.pdf")
>>> graph_draw(u, pos=pos, output_size=(400, 400), output="composed-filter.pdf")
<...>
.. figure:: composed-filter.*
......
This diff is collapsed.
......@@ -87,9 +87,9 @@ def community_structure(g, n_iter, n_spins, gamma=1.0, corr="erdos",
See Also
--------
community_structure: obtain the community structure
modularity: calculate the network modularity
condensation_graph: network of communities
community_structure: Obtain the community structure
modularity: Calculate the network modularity
condensation_graph: Network of communities, or blocks
Notes
-----
......@@ -145,19 +145,17 @@ def community_structure(g, n_iter, n_spins, gamma=1.0, corr="erdos",
>>> from numpy.random import seed
>>> seed(42)
>>> g = gt.load_graph("community.xml")
>>> pos = (g.vertex_properties["pos_x"], g.vertex_properties["pos_y"])
>>> pos = g.vertex_properties["pos"]
>>> spins = gt.community_structure(g, 10000, 20, t_range=(5, 0.1),
... history_file="community-history1")
>>> gt.graph_draw(g, pos=pos, pin=True, vsize=0.3, vcolor=spins,
... output="comm1.pdf", size=(10,10))
>>> gt.graph_draw(g, pos=pos, vertex_fill_color=spins, output_size=(420, 420), output="comm1.pdf")
<...>
>>> spins = gt.community_structure(g, 10000, 40, t_range=(5, 0.1),
... gamma=2.5,
... history_file="community-history2")
>>> gt.graph_draw(g, pos=pos, pin=True, vsize=0.3, vcolor=spins,
... output="comm2.pdf", size=(10,10))
... gamma=2.5, history_file="community-history2")
>>> gt.graph_draw(g, pos=pos, vertex_fill_color=spins, output_size=(420, 420), output="comm2.pdf")
<...>
>>> figure(figsize=(6, 4))
<...>
>>> clf()
>>> xlabel("iterations")
<...>
>>> ylabel("number of communities")
......@@ -239,7 +237,7 @@ def modularity(g, prop, weight=None):
--------
community_structure: obtain the community structure
modularity: calculate the network modularity
condensation_graph: network of communities
condensation_graph: Network of communities, or blocks
Notes
-----
......@@ -307,9 +305,9 @@ def condensation_graph(g, prop, weight=None):
See Also
--------
community_structure: obtain the community structure
modularity: calculate the network modularity
condensation_graph: network of communities
community_structure: Obtain the community structure
modularity: Calculate the network modularity
condensation_graph: Network of communities, or blocks
Notes
-----
......@@ -324,13 +322,12 @@ def condensation_graph(g, prop, weight=None):
>>> from numpy.random import poisson, seed
>>> seed(42)
>>> g = gt.random_graph(1000, lambda: poisson(3), directed=False)
>>> g = gt.GraphView(g, vfilt=gt.label_largest_component(g))
>>> spins = gt.community_structure(g, 10000, 100)
>>> ng = gt.condensation_graph(g, spins)
>>> size = ng[0].new_vertex_property("double")
>>> size.a = log(ng[2].a+1)
>>> gt.graph_draw(ng[0], vsize=size, vcolor=ng[1], splines=True,
... eprops={"len":20, "penwidth":10}, vprops={"penwidth":10},
... output="comm-network.pdf", size=(10,10))
>>> size.a = 50 * ng[2].a / ng[2].a.max()
>>> gt.graph_draw(ng[0], vertex_fill_color=ng[1], vertex_size=size, output="comm-network.pdf")
<...>
.. figure:: comm-network.*
......
......@@ -269,9 +269,9 @@ def corr_hist(g, deg_source, deg_target, bins=[[0, 1], [0, 1]], weight=None,
... directed=False, mix_time=100)
>>> h = gt.corr_hist(g, "out", "out")
>>> clf()
>>> xlabel("source out-degree")
>>> xlabel("Source out-degree")
<...>
>>> ylabel("target out-degree")
>>> ylabel("Target out-degree")
<...>
>>> imshow(h[0], interpolation="nearest")
<...>
......@@ -355,9 +355,9 @@ def combined_corr_hist(g, deg1, deg2, bins=[[0, 1], [0, 1]], float_count=True):
>>> g = gt.random_graph(10000, lambda: sample_k(40))
>>> h = gt.combined_corr_hist(g, "in", "out")
>>> clf()
>>> xlabel("in-degree")
>>> xlabel("In-degree")
<...>
>>> ylabel("out-degree")
>>> ylabel("Out-degree")
<...>
>>> imshow(h[0], interpolation="nearest")
<...>
......@@ -447,12 +447,12 @@ def avg_neighbour_corr(g, deg_source, deg_target, bins=[0, 1], weight=None):
... directed=False, mix_time=100)
>>> h = gt.avg_neighbour_corr(g, "out", "out")
>>> clf()
>>> xlabel("source out-degree")
>>> xlabel("Source out-degree")
<...>
>>> ylabel("target out-degree")
>>> ylabel("Target out-degree")
<...>
>>> errorbar(h[2][:-1], h[0], yerr=h[1], fmt="o")
(...)
<...>
>>> savefig("avg_corr.pdf")
.. figure:: avg_corr.*
......@@ -524,12 +524,12 @@ def avg_combined_corr(g, deg1, deg2, bins=[0, 1]):
>>> g = gt.random_graph(10000, lambda: sample_k(40))
>>> h = gt.avg_combined_corr(g, "in", "out")
>>> clf()
>>> xlabel("in-degree")
>>> xlabel("In-degree")
<...>
>>> ylabel("out-degree")
>>> ylabel("Out-degree")
<...>
>>> errorbar(h[2][:-1], h[0], yerr=h[1], fmt="o")
(...)
<...>
>>> savefig("combined_avg_corr.pdf")
.. figure:: combined_avg_corr.*
......
......@@ -19,23 +19,45 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
``graph_tool.draw`` - Graph drawing
-----------------------------------
``graph_tool.draw`` - Graph drawing and layout
----------------------------------------------
Summary
+++++++
Layout algorithms
=================
.. autosummary::
:nosignatures:
graph_draw
sfdp_layout
fruchterman_reingold_layout
arf_layout
random_layout
cairo_draw
Graph drawing
=============
.. autosummary::
:nosignatures:
graph_draw
graphviz_draw
Low-level graph drawing
^^^^^^^^^^^^^^^^^^^^^^^
.. autosummary::
:nosignatures:
cairo_draw
interactive_window
GraphWidget
GraphWindow
Contents
++++++++
"""
......@@ -177,7 +199,7 @@ def fruchterman_reingold_layout(g, weight=None, a=None, r=1., scale=None,
>>> seed(42)
>>> g = gt.price_network(300)
>>> pos = gt.fruchterman_reingold_layout(g, n_iter=1000)
>>> gt.graph_draw(g, pos=pos, pin=True, output="graph-draw-fr.pdf")
>>> gt.graph_draw(g, pos=pos, output="graph-draw-fr.pdf")
<...>
.. figure:: graph-draw-fr.*
......@@ -258,7 +280,7 @@ def arf_layout(g, weight=None, d=0.5, a=10, dt=0.001, epsilon=1e-6,
>>> seed(42)
>>> g = gt.price_network(300)
>>> pos = gt.arf_layout(g, max_iter=0)
>>> gt.graph_draw(g, pos=pos, pin=True, output="graph-draw-arf.pdf")
>>> gt.graph_draw(g, pos=pos, output="graph-draw-arf.pdf")
<...>
.. figure:: graph-draw-arf.*
......
This diff is collapsed.