{
"metadata": {
"name": "Using__repr_svg_with_networkx"
},
"nbformat": 3,
"nbformat_minor": 0,
"worksheets": [
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"If you use the excellent [networkx](http://networkx.lanl.gov) package from working with graphs, here's a cool way to use the ``_repr_svg_`` in the IPython Notebook or qtconsole. "
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"import networkx as nx\n",
"import matplotlib.pyplot as plt\n",
"import StringIO\n",
"from matplotlib.figure import Figure\n",
"\n",
"class MyGraph(nx.Graph):\n",
" def _repr_svg_(self):\n",
" plt.ioff() # turn off interactive mode\n",
" fig=plt.figure(figsize=(2,2))\n",
" ax = fig.add_subplot(111)\n",
" nx.draw_shell(self, ax=ax)\n",
" output = StringIO.StringIO()\n",
" fig.savefig(output,format='svg')\n",
" plt.ion() # turn on interactive mode\n",
" return output.getvalue()\n"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 2
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Basically, I'm creating a class to use as a *harness* for networkx graphs so that I don't have to keep plotting them to see what changes have been made to the graph as a result of various operations on the graph (e.g. removing nodes, adding edges). For example,here's a binomial graph:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"g=nx.random_graphs.binomial_graph(10,.5)\n",
"f=MyGraph(g)\n",
"f\n"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "pyout",
"prompt_number": 3,
"svg": [
"\n",
"\n",
"\n",
"\n"
],
"text": [
"<__main__.MyGraph at 0x19aaad0>"
]
}
],
"prompt_number": 3
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now, if I remove some edges as shown:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"f.remove_nodes_from([0,3,7,5] )\n",
"f # this triggers the _repr_svg function in the notebook"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "pyout",
"prompt_number": 4,
"svg": [
"\n",
"\n",
"\n",
"\n"
],
"text": [
"<__main__.MyGraph at 0x19aaad0>"
]
}
],
"prompt_number": 4
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Pretty cool, huh? Now, you can interact with networkx graphs and get quick SVG's the represent those changes. Because I've defined a subclass, then I can do everything I normally do with network graphs.\n",
"\n",
"I'm sure there's a neater way to do this and I'd love to hear it! You can download this notebook on my github [site](https://github.com/unpingco/Pig-in-the-Python/blob/master/Using__repr_svg_with_networkx.ipynb)."
]
},
{
"cell_type": "heading",
"level": 2,
"metadata": {},
"source": [
"Addendum by Min RK in the comments"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Min has come up with a better way to do this [without subclassing](ttp://nbviewer.ipython.org/urls/raw.github.com/minrk/Pig-in-the-Python/master/Using__repr_svg_with_networkx.ipynb). I'm including his work below to keep everything in one place.\n",
"\n",
"Let's define a function to render a graph to SVG:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"import matplotlib.pyplot as plt\n",
"from io import BytesIO\n",
"\n",
"def graph_to_svg(g):\n",
" \"\"\"return the SVG of a matplotlib figure generated from a graph\"\"\"\n",
" fig=plt.figure(figsize=(2,2))\n",
" ax = fig.add_subplot(111)\n",
" nx.draw_shell(g, ax=ax)\n",
" output = BytesIO()\n",
" fig.savefig(output, format='svg')\n",
" plt.close(fig)\n",
" return output.getvalue()"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 5
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"And call it:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"from IPython.display import display, SVG\n",
"display(SVG(graph_to_svg(g)))"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "display_data",
"svg": [
""
],
"text": [
""
]
}
],
"prompt_number": 6
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now we can register `graph_to_svg` as the formatter to be called *any time* an `nx.Graph` object is seen:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"formatter = get_ipython().display_formatter.formatters['image/svg+xml']\n",
"formatter.for_type(nx.Graph, graph_to_svg)"
],
"language": "python",
"metadata": {},
"outputs": [],
"prompt_number": 7
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"From now on, any time we would return a graph, we will see it as an SVG:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"g"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "pyout",
"prompt_number": 8,
"svg": [
"\n",
"\n",
"\n",
"\n"
],
"text": [
""
]
}
],
"prompt_number": 8
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now, if I remove some edges as shown:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"g.remove_nodes_from([0,3,7,5])\n",
"g # this triggers the graph_to_svg function in the notebook"
],
"language": "python",
"metadata": {},
"outputs": [
{
"output_type": "pyout",
"prompt_number": 9,
"svg": [
"\n",
"\n",
"\n",
"\n"
],
"text": [
""
]
}
],
"prompt_number": 9
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Pretty cool, huh? Now, you can interact with networkx graphs and get quick SVG's the represent those changes, without any subclasses.\n",
"\n",
"Thanks for the input, Min! This is a much cleaner way to accomplish this rendering."
]
}
],
"metadata": {}
}
]
}