Created
April 19, 2016 17:39
-
-
Save robclewley/12efcf551351214e3d7823bb096c951f to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"cells": [ | |
{ | |
"cell_type": "code", | |
"execution_count": 1, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [ | |
"import IPython\n", | |
"import json\n", | |
"import matplotlib.pyplot as plt\n", | |
"%matplotlib inline" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 2, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"data = json.load(open('./vax_graph.json'))\n", | |
"# conversions for JS\n", | |
"false = False\n", | |
"true = True\n", | |
"def f(nodes):\n", | |
" return \"{} nodes\".format(len(nodes))" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 7, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"data = {u'links': [{u'source': 0, u'target': 1},\n", | |
" {u'source': 0, u'target': 2},\n", | |
" {u'source': 0, u'target': 3},\n", | |
" {u'source': 0, u'target': 4},\n", | |
" {u'source': 0, u'target': 5},\n", | |
" {u'source': 0, u'target': 6},\n", | |
" {u'source': 0, u'target': 7},\n", | |
" {u'source': 0, u'target': 8},\n", | |
" {u'source': 0, u'target': 10},\n", | |
" {u'source': 0, u'target': 11},\n", | |
" {u'source': 0, u'target': 12},\n", | |
" {u'source': 0, u'target': 13},\n", | |
" {u'source': 0, u'target': 17},\n", | |
" {u'source': 0, u'target': 19},\n", | |
" {u'source': 0, u'target': 21},\n", | |
" {u'source': 0, u'target': 31},\n", | |
" {u'source': 1, u'target': 2},\n", | |
" {u'source': 1, u'target': 3},\n", | |
" {u'source': 1, u'target': 7},\n", | |
" {u'source': 1, u'target': 13},\n", | |
" {u'source': 1, u'target': 17},\n", | |
" {u'source': 1, u'target': 19},\n", | |
" {u'source': 1, u'target': 21},\n", | |
" {u'source': 1, u'target': 30},\n", | |
" {u'source': 2, u'target': 3},\n", | |
" {u'source': 2, u'target': 32},\n", | |
" {u'source': 2, u'target': 7},\n", | |
" {u'source': 2, u'target': 8},\n", | |
" {u'source': 2, u'target': 9},\n", | |
" {u'source': 2, u'target': 13},\n", | |
" {u'source': 2, u'target': 27},\n", | |
" {u'source': 2, u'target': 28},\n", | |
" {u'source': 3, u'target': 7},\n", | |
" {u'source': 3, u'target': 12},\n", | |
" {u'source': 3, u'target': 13},\n", | |
" {u'source': 4, u'target': 10},\n", | |
" {u'source': 4, u'target': 6},\n", | |
" {u'source': 5, u'target': 16},\n", | |
" {u'source': 5, u'target': 10},\n", | |
" {u'source': 5, u'target': 6},\n", | |
" {u'source': 6, u'target': 16},\n", | |
" {u'source': 8, u'target': 32},\n", | |
" {u'source': 8, u'target': 30},\n", | |
" {u'source': 8, u'target': 33},\n", | |
" {u'source': 9, u'target': 33},\n", | |
" {u'source': 13, u'target': 33},\n", | |
" {u'source': 14, u'target': 32},\n", | |
" {u'source': 14, u'target': 33},\n", | |
" {u'source': 15, u'target': 32},\n", | |
" {u'source': 15, u'target': 33},\n", | |
" {u'source': 18, u'target': 32},\n", | |
" {u'source': 18, u'target': 33},\n", | |
" {u'source': 19, u'target': 33},\n", | |
" {u'source': 20, u'target': 32},\n", | |
" {u'source': 20, u'target': 33},\n", | |
" {u'source': 22, u'target': 32},\n", | |
" {u'source': 22, u'target': 33},\n", | |
" {u'source': 23, u'target': 32},\n", | |
" {u'source': 23, u'target': 25},\n", | |
" {u'source': 23, u'target': 27},\n", | |
" {u'source': 23, u'target': 29},\n", | |
" {u'source': 23, u'target': 33},\n", | |
" {u'source': 24, u'target': 25},\n", | |
" {u'source': 24, u'target': 27},\n", | |
" {u'source': 24, u'target': 31},\n", | |
" {u'source': 25, u'target': 31},\n", | |
" {u'source': 26, u'target': 33},\n", | |
" {u'source': 26, u'target': 29},\n", | |
" {u'source': 27, u'target': 33},\n", | |
" {u'source': 28, u'target': 33},\n", | |
" {u'source': 28, u'target': 31},\n", | |
" {u'source': 29, u'target': 32},\n", | |
" {u'source': 29, u'target': 33},\n", | |
" {u'source': 30, u'target': 33},\n", | |
" {u'source': 30, u'target': 32},\n", | |
" {u'source': 31, u'target': 33},\n", | |
" {u'source': 31, u'target': 32},\n", | |
" {u'source': 32, u'target': 33}],\n", | |
" u'nodes': [{u'name': u'0', u'state': u'S'},\n", | |
" {u'name': u'1', u'state': u'S'},\n", | |
" {u'name': u'2', u'state': u'S'},\n", | |
" {u'name': u'3', u'state': u'S'},\n", | |
" {u'name': u'4', u'state': u'S'},\n", | |
" {u'name': u'5', u'state': u'S'},\n", | |
" {u'name': u'6', u'state': u'S'},\n", | |
" {u'name': u'7', u'state': u'S'},\n", | |
" {u'name': u'8', u'state': u'S'},\n", | |
" {u'name': u'9', u'state': u'S'},\n", | |
" {u'name': u'10', u'state': u'S'},\n", | |
" {u'name': u'11', u'state': u'S'},\n", | |
" {u'name': u'12', u'state': u'S'},\n", | |
" {u'name': u'13', u'state': u'S'},\n", | |
" {u'name': u'14', u'state': u'S'},\n", | |
" {u'name': u'15', u'state': u'S'},\n", | |
" {u'name': u'16', u'state': u'S'},\n", | |
" {u'name': u'17', u'state': u'S'},\n", | |
" {u'name': u'18', u'state': u'S'},\n", | |
" {u'name': u'19', u'state': u'S'},\n", | |
" {u'name': u'20', u'state': u'S'},\n", | |
" {u'name': u'21', u'state': u'S'},\n", | |
" {u'name': u'22', u'state': u'S'},\n", | |
" {u'name': u'23', u'state': u'S'},\n", | |
" {u'name': u'24', u'state': u'S'},\n", | |
" {u'name': u'25', u'state': u'S'},\n", | |
" {u'name': u'26', u'state': u'S'},\n", | |
" {u'name': u'27', u'state': u'S'},\n", | |
" {u'name': u'28', u'state': u'S'},\n", | |
" {u'name': u'29', u'state': u'S'},\n", | |
" {u'name': u'30', u'state': u'S'},\n", | |
" {u'name': u'31', u'state': u'S'},\n", | |
" {u'name': u'32', u'state': u'S'},\n", | |
" {u'name': u'33', u'state': u'S'}]}" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 3, | |
"metadata": { | |
"collapsed": false, | |
"scrolled": true | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [ | |
"<center><h1>Click nodes to immunize them!</h1></center>\n", | |
"<div id=\"d3-example\"></div>\n", | |
"<div class=\"mybutton\" id=\"flex\">\n", | |
" <button>FLEX!</button>\n", | |
"</div>\n", | |
"<style>\n", | |
".node {stroke: #fff; stroke-width: 1.5px;}\n", | |
"line.link {stroke: #999; stroke-opacity: .6;}\n", | |
"</style>" | |
], | |
"text/plain": [ | |
"<IPython.core.display.HTML object>" | |
] | |
}, | |
"metadata": {}, | |
"output_type": "display_data" | |
} | |
], | |
"source": [ | |
"%%html\n", | |
"<center><h1>Click nodes to immunize them!</h1></center>\n", | |
"<div id=\"d3-example\"></div>\n", | |
"<div class=\"mybutton\" id=\"flex\">\n", | |
" <button>FLEX!</button>\n", | |
"</div>\n", | |
"<style>\n", | |
".node {stroke: #fff; stroke-width: 1.5px;}\n", | |
"line.link {stroke: #999; stroke-opacity: .6;}\n", | |
"</style>" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 4, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"application/javascript": [ | |
"window._graph={\"nodes\": [{\"state\": \"S\", \"name\": \"0\"}, {\"state\": \"S\", \"name\": \"1\"}, {\"state\": \"S\", \"name\": \"2\"}, {\"state\": \"S\", \"name\": \"3\"}, {\"state\": \"S\", \"name\": \"4\"}, {\"state\": \"S\", \"name\": \"5\"}, {\"state\": \"S\", \"name\": \"6\"}, {\"state\": \"S\", \"name\": \"7\"}, {\"state\": \"S\", \"name\": \"8\"}, {\"state\": \"S\", \"name\": \"9\"}, {\"state\": \"S\", \"name\": \"10\"}, {\"state\": \"S\", \"name\": \"11\"}, {\"state\": \"S\", \"name\": \"12\"}, {\"state\": \"S\", \"name\": \"13\"}, {\"state\": \"S\", \"name\": \"14\"}, {\"state\": \"S\", \"name\": \"15\"}, {\"state\": \"S\", \"name\": \"16\"}, {\"state\": \"S\", \"name\": \"17\"}, {\"state\": \"S\", \"name\": \"18\"}, {\"state\": \"S\", \"name\": \"19\"}, {\"state\": \"S\", \"name\": \"20\"}, {\"state\": \"S\", \"name\": \"21\"}, {\"state\": \"S\", \"name\": \"22\"}, {\"state\": \"S\", \"name\": \"23\"}, {\"state\": \"S\", \"name\": \"24\"}, {\"state\": \"S\", \"name\": \"25\"}, {\"state\": \"S\", \"name\": \"26\"}, {\"state\": \"S\", \"name\": \"27\"}, {\"state\": \"S\", \"name\": \"28\"}, {\"state\": \"S\", \"name\": \"29\"}, {\"state\": \"S\", \"name\": \"30\"}, {\"state\": \"S\", \"name\": \"31\"}, {\"state\": \"S\", \"name\": \"32\"}, {\"state\": \"S\", \"name\": \"33\"}], \"links\": [{\"source\": 0, \"target\": 1}, {\"source\": 0, \"target\": 2}, {\"source\": 0, \"target\": 3}, {\"source\": 0, \"target\": 4}, {\"source\": 0, \"target\": 5}, {\"source\": 0, \"target\": 6}, {\"source\": 0, \"target\": 7}, {\"source\": 0, \"target\": 8}, {\"source\": 0, \"target\": 10}, {\"source\": 0, \"target\": 11}, {\"source\": 0, \"target\": 12}, {\"source\": 0, \"target\": 13}, {\"source\": 0, \"target\": 17}, {\"source\": 0, \"target\": 19}, {\"source\": 0, \"target\": 21}, {\"source\": 0, \"target\": 31}, {\"source\": 1, \"target\": 2}, {\"source\": 1, \"target\": 3}, {\"source\": 1, \"target\": 7}, {\"source\": 1, \"target\": 13}, {\"source\": 1, \"target\": 17}, {\"source\": 1, \"target\": 19}, {\"source\": 1, \"target\": 21}, {\"source\": 1, \"target\": 30}, {\"source\": 2, \"target\": 3}, {\"source\": 2, \"target\": 32}, {\"source\": 2, \"target\": 7}, {\"source\": 2, \"target\": 8}, {\"source\": 2, \"target\": 9}, {\"source\": 2, \"target\": 13}, {\"source\": 2, \"target\": 27}, {\"source\": 2, \"target\": 28}, {\"source\": 3, \"target\": 7}, {\"source\": 3, \"target\": 12}, {\"source\": 3, \"target\": 13}, {\"source\": 4, \"target\": 10}, {\"source\": 4, \"target\": 6}, {\"source\": 5, \"target\": 16}, {\"source\": 5, \"target\": 10}, {\"source\": 5, \"target\": 6}, {\"source\": 6, \"target\": 16}, {\"source\": 8, \"target\": 32}, {\"source\": 8, \"target\": 30}, {\"source\": 8, \"target\": 33}, {\"source\": 9, \"target\": 33}, {\"source\": 13, \"target\": 33}, {\"source\": 14, \"target\": 32}, {\"source\": 14, \"target\": 33}, {\"source\": 15, \"target\": 32}, {\"source\": 15, \"target\": 33}, {\"source\": 18, \"target\": 32}, {\"source\": 18, \"target\": 33}, {\"source\": 19, \"target\": 33}, {\"source\": 20, \"target\": 32}, {\"source\": 20, \"target\": 33}, {\"source\": 22, \"target\": 32}, {\"source\": 22, \"target\": 33}, {\"source\": 23, \"target\": 32}, {\"source\": 23, \"target\": 25}, {\"source\": 23, \"target\": 27}, {\"source\": 23, \"target\": 29}, {\"source\": 23, \"target\": 33}, {\"source\": 24, \"target\": 25}, {\"source\": 24, \"target\": 27}, {\"source\": 24, \"target\": 31}, {\"source\": 25, \"target\": 31}, {\"source\": 26, \"target\": 33}, {\"source\": 26, \"target\": 29}, {\"source\": 27, \"target\": 33}, {\"source\": 28, \"target\": 33}, {\"source\": 28, \"target\": 31}, {\"source\": 29, \"target\": 32}, {\"source\": 29, \"target\": 33}, {\"source\": 30, \"target\": 33}, {\"source\": 30, \"target\": 32}, {\"source\": 31, \"target\": 33}, {\"source\": 31, \"target\": 32}, {\"source\": 32, \"target\": 33}]}" | |
], | |
"text/plain": [ | |
"<IPython.core.display.Javascript object>" | |
] | |
}, | |
"execution_count": 4, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"IPython.display.Javascript(\"window._graph=\"+json.dumps(data))" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 5, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"application/javascript": [ | |
"// We load the d3.js library from the Web.\n", | |
"require.config({paths: {d3: \"http://d3js.org/d3.v3.min\"}});\n", | |
"function exec_code(){\n", | |
" var code_input = document.getElementById('code_input').value;\n", | |
" var kernel = IPython.notebook.kernel;\n", | |
" var callbacks = { 'iopub' : {'output' : handle_output}};\n", | |
" document.getElementById(\"result_output\").value = \"\"; // clear output box\n", | |
" var msg_id = kernel.execute(code_input, callbacks, {silent:false});\n", | |
" console.log(\"button pressed\");\n", | |
" // IPython.notebook.clear_output();\n", | |
" };\n", | |
"require([\"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 <div> element).\n", | |
" var width = 600,\n", | |
" height = 600,\n", | |
" r = 10;\n", | |
"\n", | |
" // We create a color scale.\n", | |
" var color = {'S': d3.rgb('gray'),\n", | |
" 'I': d3.rgb('red')\n", | |
" };\n", | |
" \n", | |
" function handle_output(out){\n", | |
" //console.log(out);\n", | |
" var res = null;\n", | |
" // if output is a print statement\n", | |
" if(out.msg_type == \"stream\"){\n", | |
" res = out.content.data;\n", | |
" }\n", | |
" // if output is a python object\n", | |
" else if(out.msg_type === \"execute_result\"){\n", | |
" res = out.content.data[\"text/plain\"];\n", | |
" }\n", | |
" // if output is a python error\n", | |
" else if(out.msg_type == \"pyerr\"){\n", | |
" res = out.content.ename + \": \" + out.content.evalue;\n", | |
" }\n", | |
" // if output is something we haven't thought of\n", | |
" else{\n", | |
" res = \"[out type not implemented]\"; \n", | |
" }\n", | |
" d3.select(\"#flex button\").text(res.replace(/['\"]+/g, '')); //[0][0].innerText = res;\n", | |
" } \n", | |
" function set_py_value(){\n", | |
" var kernel = IPython.notebook.kernel;\n", | |
" var str_nodes = JSON.stringify(graph.nodes);\n", | |
" var node_command = \"node = \" + str_nodes;\n", | |
" var msg_id = kernel.execute(node_command);\n", | |
" var callbacks = { 'iopub' : {'output' : handle_output}};\n", | |
" var msg_id = kernel.execute('f(' + str_nodes + ')', callbacks, {silent: false});\n", | |
" }\n", | |
"\n", | |
" // We create a force-directed dynamic graph layout.\n", | |
" var force = d3.layout.force()\n", | |
" .charge(-300)\n", | |
" .linkDistance(50)\n", | |
" .size([width, height])\n", | |
"\n", | |
" // In the <div> element, we create a <svg> graphic\n", | |
" // that will contain our interactive visualization.\n", | |
" var svg = d3.select(\"#d3-example\").selectAll(\"svg\")\n", | |
" .data([{'width':width,'height':height}])\n", | |
" svg.enter().append(\"svg\")\n", | |
" \n", | |
" svg.each( function(data){\n", | |
" d3.entries(data).forEach(function(value){\n", | |
" svg.attr(value.key, value.value);\n", | |
" })\n", | |
" \n", | |
" })\n", | |
" svg.exit().remove()\n", | |
" \n", | |
" var graph = _graph; // bind to the variable injected by ipython\n", | |
" \n", | |
" var link = svg.selectAll(\".link\"),\n", | |
" node = svg.selectAll(\".node\");\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", | |
" var tick_func = 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", | |
" update();\n", | |
" \n", | |
" function get_color (d) {return color[d.state];} \n", | |
" \n", | |
" function update() {\n", | |
" force.nodes(graph.nodes.map(function (n) {if (n.dead==null) {n.dead = false;}; return n;}))\n", | |
" .links(graph.links)\n", | |
" .start();\n", | |
"\n", | |
" graph.nodes = removeOldNodes(graph)\n", | |
" graph.links = removeOldLinks(graph)\n", | |
"\n", | |
" link = link.data(graph.links)\n", | |
" link.exit().remove()\n", | |
" // but links will never be added after start\n", | |
" link.enter().insert(\"line\", \".node\")\n", | |
" .attr(\"class\", \"link\");\n", | |
"\n", | |
" node = node.data(graph.nodes, function(d) {return d.name;})\n", | |
" node.exit().remove()\n", | |
" // nodes will never be added after start\n", | |
" var nodeEnter = node.enter().append(\"circle\")\n", | |
" .attr(\"class\", \"node\")\n", | |
" .attr(\"r\", r)\n", | |
" .on(\"click\", click)\n", | |
" .call(force.drag);\n", | |
"\n", | |
" node.style(\"fill\", get_color );\n", | |
" \n", | |
" nodeEnter.append(\"title\")\n", | |
" .text(function(d) { return d.name; });\n", | |
"\n", | |
" set_py_value()\n", | |
" };\n", | |
" \n", | |
" function click(d, i) {\n", | |
" if (d3.event.defaultPrevented) return; // dragged\n", | |
" var circ = d3.select(this)\n", | |
" circ.transition()\n", | |
" .attr(\"r\", 30)\n", | |
" .style(\"fill\", \"lightsteelblue\")\n", | |
" .transition()\n", | |
" .attr(\"r\", r)\n", | |
" .style(\"fill\", color[circ.state])\n", | |
" graph.nodes[circ[0][0].__data__.index].dead = true\n", | |
" update();\n", | |
" };\n", | |
" \n", | |
" // in lieu of Array#indexOf or Array#includes in modern JS/browsers\n", | |
" // or $.inArray\n", | |
" function contains(a, obj) {\n", | |
" for (var i = 0; i < a.length; i++) {\n", | |
" if (a[i] === obj) {\n", | |
" return true;\n", | |
" }\n", | |
" }\n", | |
" return false;\n", | |
" }\n", | |
" \n", | |
" function removeOldNodes(gr) {\n", | |
" var new_nodes = [];\n", | |
" for (var nix = 0; nix < gr.nodes.length; nix++) {\n", | |
" if (!gr.nodes[nix].dead) {\n", | |
" new_nodes.push(gr.nodes[nix])\n", | |
" //!(gr.nodes[nix].dead) && new_nodes.push(gr.nodes[nix])\n", | |
" };\n", | |
" };\n", | |
" return new_nodes;\n", | |
" };\n", | |
" \n", | |
" function removeOldLinks(gr) {\n", | |
" var new_links = [];\n", | |
" var nix, lix;\n", | |
" var live_ixs = gr.nodes.map(function (d) {return d.name;});\n", | |
"\n", | |
" for (lix = 0; lix < gr.links.length; lix++) {\n", | |
" if (contains(live_ixs, gr.links[lix].source.name) && contains(live_ixs, gr.links[lix].target.name)) {\n", | |
" new_links.push(gr.links[lix]);\n", | |
" };\n", | |
" };\n", | |
" return new_links\n", | |
" };\n", | |
" \n", | |
" force.on(\"tick\", tick_func);\n", | |
"\n", | |
"});" | |
], | |
"text/plain": [ | |
"<IPython.core.display.Javascript object>" | |
] | |
}, | |
"metadata": {}, | |
"output_type": "display_data" | |
} | |
], | |
"source": [ | |
"%%javascript\n", | |
"// We load the d3.js library from the Web.\n", | |
"require.config({paths: {d3: \"http://d3js.org/d3.v3.min\"}});\n", | |
"function exec_code(){\n", | |
" var code_input = document.getElementById('code_input').value;\n", | |
" var kernel = IPython.notebook.kernel;\n", | |
" var callbacks = { 'iopub' : {'output' : handle_output}};\n", | |
" document.getElementById(\"result_output\").value = \"\"; // clear output box\n", | |
" var msg_id = kernel.execute(code_input, callbacks, {silent:false});\n", | |
" console.log(\"button pressed\");\n", | |
" // IPython.notebook.clear_output();\n", | |
" };\n", | |
"require([\"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 <div> element).\n", | |
" var width = 600,\n", | |
" height = 600,\n", | |
" r = 10;\n", | |
"\n", | |
" // We create a color scale.\n", | |
" var color = {'S': d3.rgb('gray'),\n", | |
" 'I': d3.rgb('red')\n", | |
" };\n", | |
" \n", | |
" function handle_output(out){\n", | |
" //console.log(out);\n", | |
" var res = null;\n", | |
" // if output is a print statement\n", | |
" if(out.msg_type == \"stream\"){\n", | |
" res = out.content.data;\n", | |
" }\n", | |
" // if output is a python object\n", | |
" else if(out.msg_type === \"execute_result\"){\n", | |
" res = out.content.data[\"text/plain\"];\n", | |
" }\n", | |
" // if output is a python error\n", | |
" else if(out.msg_type == \"pyerr\"){\n", | |
" res = out.content.ename + \": \" + out.content.evalue;\n", | |
" }\n", | |
" // if output is something we haven't thought of\n", | |
" else{\n", | |
" res = \"[out type not implemented]\"; \n", | |
" }\n", | |
" d3.select(\"#flex button\").text(res.replace(/['\"]+/g, '')); //[0][0].innerText = res;\n", | |
" } \n", | |
" function set_py_value(){\n", | |
" var kernel = IPython.notebook.kernel;\n", | |
" var str_nodes = JSON.stringify(graph.nodes);\n", | |
" var node_command = \"node = \" + str_nodes;\n", | |
" var msg_id = kernel.execute(node_command);\n", | |
" var callbacks = { 'iopub' : {'output' : handle_output}};\n", | |
" var msg_id = kernel.execute('f(' + str_nodes + ')', callbacks, {silent: false});\n", | |
" }\n", | |
"\n", | |
" // We create a force-directed dynamic graph layout.\n", | |
" var force = d3.layout.force()\n", | |
" .charge(-300)\n", | |
" .linkDistance(50)\n", | |
" .size([width, height])\n", | |
"\n", | |
" // In the <div> element, we create a <svg> graphic\n", | |
" // that will contain our interactive visualization.\n", | |
" var svg = d3.select(\"#d3-example\").selectAll(\"svg\")\n", | |
" .data([{'width':width,'height':height}])\n", | |
" svg.enter().append(\"svg\")\n", | |
" \n", | |
" svg.each( function(data){\n", | |
" d3.entries(data).forEach(function(value){\n", | |
" svg.attr(value.key, value.value);\n", | |
" })\n", | |
" \n", | |
" })\n", | |
" svg.exit().remove()\n", | |
" \n", | |
" var graph = _graph; // bind to the variable injected by ipython\n", | |
" \n", | |
" var link = svg.selectAll(\".link\"),\n", | |
" node = svg.selectAll(\".node\");\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", | |
" var tick_func = 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", | |
" update();\n", | |
" \n", | |
" function get_color (d) {return color[d.state];} \n", | |
" \n", | |
" function update() {\n", | |
" force.nodes(graph.nodes.map(function (n) {if (n.dead==null) {n.dead = false;}; return n;}))\n", | |
" .links(graph.links)\n", | |
" .start();\n", | |
"\n", | |
" graph.nodes = removeOldNodes(graph)\n", | |
" graph.links = removeOldLinks(graph)\n", | |
"\n", | |
" link = link.data(graph.links)\n", | |
" link.exit().remove()\n", | |
" // but links will never be added after start\n", | |
" link.enter().insert(\"line\", \".node\")\n", | |
" .attr(\"class\", \"link\");\n", | |
"\n", | |
" node = node.data(graph.nodes, function(d) {return d.name;})\n", | |
" node.exit().remove()\n", | |
" // nodes will never be added after start\n", | |
" var nodeEnter = node.enter().append(\"circle\")\n", | |
" .attr(\"class\", \"node\")\n", | |
" .attr(\"r\", r)\n", | |
" .on(\"click\", click)\n", | |
" .call(force.drag);\n", | |
"\n", | |
" node.style(\"fill\", get_color );\n", | |
" \n", | |
" nodeEnter.append(\"title\")\n", | |
" .text(function(d) { return d.name; });\n", | |
"\n", | |
" set_py_value()\n", | |
" };\n", | |
" \n", | |
" function click(d, i) {\n", | |
" if (d3.event.defaultPrevented) return; // dragged\n", | |
" var circ = d3.select(this)\n", | |
" circ.transition()\n", | |
" .attr(\"r\", 30)\n", | |
" .style(\"fill\", \"lightsteelblue\")\n", | |
" .transition()\n", | |
" .attr(\"r\", r)\n", | |
" .style(\"fill\", color[circ.state])\n", | |
" graph.nodes[circ[0][0].__data__.index].dead = true\n", | |
" update();\n", | |
" };\n", | |
" \n", | |
" // in lieu of Array#indexOf or Array#includes in modern JS/browsers\n", | |
" // or $.inArray\n", | |
" function contains(a, obj) {\n", | |
" for (var i = 0; i < a.length; i++) {\n", | |
" if (a[i] === obj) {\n", | |
" return true;\n", | |
" }\n", | |
" }\n", | |
" return false;\n", | |
" }\n", | |
" \n", | |
" function removeOldNodes(gr) {\n", | |
" var new_nodes = [];\n", | |
" for (var nix = 0; nix < gr.nodes.length; nix++) {\n", | |
" if (!gr.nodes[nix].dead) {\n", | |
" new_nodes.push(gr.nodes[nix])\n", | |
" //!(gr.nodes[nix].dead) && new_nodes.push(gr.nodes[nix])\n", | |
" };\n", | |
" };\n", | |
" return new_nodes;\n", | |
" };\n", | |
" \n", | |
" function removeOldLinks(gr) {\n", | |
" var new_links = [];\n", | |
" var nix, lix;\n", | |
" var live_ixs = gr.nodes.map(function (d) {return d.name;});\n", | |
"\n", | |
" for (lix = 0; lix < gr.links.length; lix++) {\n", | |
" if (contains(live_ixs, gr.links[lix].source.name) && contains(live_ixs, gr.links[lix].target.name)) {\n", | |
" new_links.push(gr.links[lix]);\n", | |
" };\n", | |
" };\n", | |
" return new_links\n", | |
" };\n", | |
" \n", | |
" force.on(\"tick\", tick_func);\n", | |
"\n", | |
"});\n" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"%%javascript\n", | |
"\n", | |
" var flex = function(event) {\n", | |
" var new_nodes = graph.nodes.map(function(n) { n.x = n.x+Math.random()*20;\n", | |
" n.y = n.y+Math.random()*20;\n", | |
" return n;\n", | |
" });\n", | |
" force.nodes(new_nodes).links(removeOldLinks(graph))\n", | |
" .on(\"tick\", tick_func)\n", | |
" .start();\n", | |
" //svg.selectAll(\".node\")\n", | |
" // .data(new_nodes)\n", | |
" // .enter().append(\"circle\")\n", | |
" // .attr(\"class\", \"node\")\n", | |
" // .attr(\"r\", r) // radius\n", | |
" // .style(\"fill\", function(d) {\n", | |
" // The node color depends on the club.\n", | |
" // return color(d.club); \n", | |
" // })\n", | |
" // .on(\"click\", click)\n", | |
" // .call(force.drag);\n", | |
" };\n", | |
" //d3.select(\"#flex button\").on('click', flex);" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"collapsed": true | |
}, | |
"source": [ | |
"# Goal 1\n", | |
"Change a python variable of x, y data and have it auto-update the graph" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"node" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# Goal 2\n", | |
"Create a clickable button in the cell using an HTML5 button element, and attach it to something in the python space" | |
] | |
} | |
], | |
"metadata": { | |
"kernelspec": { | |
"display_name": "Python 2", | |
"language": "python", | |
"name": "python2" | |
}, | |
"language_info": { | |
"codemirror_mode": { | |
"name": "ipython", | |
"version": 2 | |
}, | |
"file_extension": ".py", | |
"mimetype": "text/x-python", | |
"name": "python", | |
"nbconvert_exporter": "python", | |
"pygments_lexer": "ipython2", | |
"version": "2.7.5" | |
} | |
}, | |
"nbformat": 4, | |
"nbformat_minor": 0 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment