#!/usr/bin/env python # coding: utf-8 # > This is one of the 100 recipes of the [IPython Cookbook](http://ipython-books.github.io/), the definitive guide to high-performance scientific computing and data science in Python. # # # 6.4. Visualizing a NetworkX graph in the IPython notebook with d3.js # 1. Let's import the packages. # In[1]: import json import numpy as np import networkx as nx import matplotlib.pyplot as plt get_ipython().run_line_magic('matplotlib', 'inline') # 2. We load a famous social graph published in 1977, called **Zachary's Karate club graph**. This graph represents the friendships between members of a Karate Club. The club's president and the instructor were involved in a dispute, resulting in a split-up of this group. Here, we simply display the graph with matplotlib (using `networkx.draw()`). # In[2]: g = nx.karate_club_graph() plt.figure(figsize=(6,4)); nx.draw(g) # 3. Now, we're going to display this graph in the notebook with d3.js. The first step is to bring this graph to Javascript. We choose here to export the graph in JSON. Note that d3.js generally expects each edge to be an object with a `source` and a `target`. Also, we specify which side each member has taken (`club` attribute). # In[3]: from networkx.readwrite import json_graph data = json_graph.node_link_data(g) with open('graph.json', 'w') as f: json.dump(data, f, indent=4) # 4. The next step is to create an HTML object that will contain the visualization. Here, we create a `
` element in the notebook. We also specify a few CSS styles for nodes and links (also called edges). # In[4]: get_ipython().run_cell_magic('html', '', '
\n\n') # 5. The last step is trickier. We write the Javascript code to load the graph from the JSON file, and display it with d3.js. Knowing the basics of d3.js is required here (see the documentation of d3.js). We also give detailled explanations in the code comments below. (http://d3js.org) # In[5]: get_ipython().run_cell_magic('javascript', '', '// We load the d3.js library from the Web.\nrequire.config({paths: {d3: "http://d3js.org/d3.v3.min"}});\nrequire(["d3"], function(d3) {\n // The code in this block is executed when the \n // d3.js library has been loaded.\n \n // First, we specify the size of the canvas containing\n // the visualization (size of the
element).\n var width = 300,\n height = 300;\n\n // We create a color scale.\n var color = d3.scale.category10();\n\n // We create a force-directed dynamic graph layout.\n var force = d3.layout.force()\n .charge(-120)\n .linkDistance(30)\n .size([width, height]);\n\n // In the
element, we create a graphic\n // that will contain our interactive visualization.\n var svg = d3.select("#d3-example").select("svg")\n if (svg.empty()) {\n svg = d3.select("#d3-example").append("svg")\n .attr("width", width)\n .attr("height", height);\n }\n \n // We load the JSON file.\n d3.json("graph.json", function(error, graph) {\n // In this block, the file has been loaded\n // and the \'graph\' object contains our graph.\n \n // We load the nodes and links in the force-directed\n // graph.\n force.nodes(graph.nodes)\n .links(graph.links)\n .start();\n\n // We create a SVG element for each link\n // in the graph.\n var link = svg.selectAll(".link")\n .data(graph.links)\n .enter().append("line")\n .attr("class", "link");\n\n // We create a SVG element for each node\n // in the graph, and we specify a few attributes.\n var node = svg.selectAll(".node")\n .data(graph.nodes)\n .enter().append("circle")\n .attr("class", "node")\n .attr("r", 5) // radius\n .style("fill", function(d) {\n // The node color depends on the club.\n return color(d.club); \n })\n .call(force.drag);\n\n // The name of each node is the node number.\n node.append("title")\n .text(function(d) { return d.id; });\n\n // We bind the positions of the SVG elements\n // to the positions of the dynamic force-directed graph,\n // at each time step.\n force.on("tick", function() {\n link.attr("x1", function(d) { return d.source.x; })\n .attr("y1", function(d) { return d.source.y; })\n .attr("x2", function(d) { return d.target.x; })\n .attr("y2", function(d) { return d.target.y; });\n\n node.attr("cx", function(d) { return d.x; })\n .attr("cy", function(d) { return d.y; });\n });\n });\n});\n') # When we execute this cell, the HTML object created in the previous cell is updated. The graph is animated and interactive: we can click on nodes, see their labels, and move them within the canvas. # > You'll find all the explanations, figures, references, and much more in the book (to be released later this summer). # # > [IPython Cookbook](http://ipython-books.github.io/), by [Cyrille Rossant](http://cyrille.rossant.net), Packt Publishing, 2014 (500 pages).