├── .gitignore ├── css ├── 3d_viewer.css ├── basic_scatter.css ├── basic_axis.css ├── basic_line.css ├── force_directed_graph.css ├── day-hr-heatmap.css └── temperature_histories.css ├── PyData-D3-in-Jupyter.pdf ├── CODE_OF_CONDUCT.md ├── README.md ├── js ├── sigma-add-method-neighbors.js ├── sigma-graph.js ├── force_directed_graph.js ├── basic_line.js ├── basic_scatter.js ├── day-hr-heatmap.js ├── 3d_viewer.js └── temperature_histories.js ├── lib ├── sigmajs │ ├── plugins │ │ ├── sigma.parsers.json.min.js │ │ ├── sigma.statistics.HITS.min.js │ │ ├── sigma.plugins.neighborhoods.min.js │ │ ├── sigma.plugins.animate.min.js │ │ ├── sigma.plugins.dragNodes.min.js │ │ ├── sigma.renderers.customShapes.min.js │ │ ├── sigma.plugins.filter.min.js │ │ ├── sigma.parsers.gexf.min.js │ │ └── sigma.layout.forceAtlas2.min.js │ ├── LICENSE.txt │ └── README.md └── d3 │ └── LICENSE ├── LICENSE.txt ├── d3_lib.py ├── D3-Circle-Animation.ipynb ├── randomized_sketch.ipynb ├── hello_dom.ipynb ├── data └── stations.csv ├── bar_chart_with_update.ipynb ├── sigma_js_graph.ipynb ├── multiple_simple_examples.ipynb └── iris_scatterplot.ipynb /.gitignore: -------------------------------------------------------------------------------- 1 | *.DS_Store 2 | *.pyc 3 | *.ipynb_checkpoints 4 | 5 | -------------------------------------------------------------------------------- /css/3d_viewer.css: -------------------------------------------------------------------------------- 1 | 2 | .dot { 3 | stroke-width: 0.5; 4 | stroke: #000; 5 | } 6 | -------------------------------------------------------------------------------- /PyData-D3-in-Jupyter.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PyGoogle/PyD3/HEAD/PyData-D3-in-Jupyter.pdf -------------------------------------------------------------------------------- /css/basic_scatter.css: -------------------------------------------------------------------------------- 1 | 2 | /* Based on http://bl.ocks.org/mbostock/3887118 */ 3 | 4 | .dot { 5 | stroke: #000; 6 | } 7 | -------------------------------------------------------------------------------- /css/basic_axis.css: -------------------------------------------------------------------------------- 1 | 2 | .axis path, 3 | .axis line { 4 | fill: none; 5 | stroke: grey; 6 | stroke-width: 1; 7 | shape-rendering: crispEdges; 8 | } 9 | 10 | -------------------------------------------------------------------------------- /css/basic_line.css: -------------------------------------------------------------------------------- 1 | 2 | /* Based on http://bl.ocks.org/d3noob/b3ff6ae1c120eea654b5 */ 3 | 4 | path { 5 | stroke: steelblue; 6 | stroke-width: 2; 7 | fill: none; 8 | } 9 | 10 | 11 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct 2 | 3 | We are committed to keeping our community open and inclusive. 4 | 5 | **Our Code of Conduct can be found here**: 6 | http://opensource.stitchfix.com/code-of-conduct.html 7 | -------------------------------------------------------------------------------- /css/force_directed_graph.css: -------------------------------------------------------------------------------- 1 | 2 | /* http://bl.ocks.org/mbostock/4062045 */ 3 | 4 | .node { 5 | stroke: #fff; 6 | stroke-width: 1.5px; 7 | } 8 | 9 | .link { 10 | stroke: #999; 11 | stroke-opacity: .6; 12 | } 13 | 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # d3-jupyter-tutorial 2 | 3 | This repo contains Jupyter notebooks, along with related code and example data, for a tutorial on the use of D3 in Jupyter. 4 | 5 | The presentation file `PyData-D3-in-Jupyter.pdf` provides an entry point and overview. 6 | -------------------------------------------------------------------------------- /js/sigma-add-method-neighbors.js: -------------------------------------------------------------------------------- 1 | sigma.classes.graph.addMethod('neighbors', function(nodeId) { 2 | var k, 3 | neighbors = {}, 4 | index = this.allNeighborsIndex[nodeId] || {}; 5 | 6 | for (k in index) 7 | neighbors[k] = this.nodesIndex[k]; 8 | 9 | return neighbors; 10 | }); 11 | -------------------------------------------------------------------------------- /css/day-hr-heatmap.css: -------------------------------------------------------------------------------- 1 | rect.bordered { 2 | stroke: #E6E6E6; 3 | stroke-width:2px; 4 | } 5 | 6 | text.mono { 7 | font-size: 9pt; 8 | font-family: Consolas, courier; 9 | fill: #aaa; 10 | } 11 | 12 | text.axis-workweek { 13 | fill: #000; 14 | } 15 | 16 | text.axis-worktime { 17 | fill: #000; 18 | } -------------------------------------------------------------------------------- /lib/sigmajs/plugins/sigma.parsers.json.min.js: -------------------------------------------------------------------------------- 1 | (function(){"use strict";if("undefined"==typeof sigma)throw"sigma is not declared";sigma.utils.pkg("sigma.parsers"),sigma.utils.pkg("sigma.utils"),sigma.utils.xhr=function(){if(window.XMLHttpRequest)return new XMLHttpRequest;var a,b;if(window.ActiveXObject){a=["Msxml2.XMLHTTP.6.0","Msxml2.XMLHTTP.3.0","Msxml2.XMLHTTP","Microsoft.XMLHTTP"];for(b in a)try{return new ActiveXObject(a[b])}catch(c){}}return null},sigma.parsers.json=function(a,b,c){var d,e=sigma.utils.xhr();if(!e)throw"XMLHttpRequest not supported, cannot load the file.";e.open("GET",a,!0),e.onreadystatechange=function(){4===e.readyState&&(d=JSON.parse(e.responseText),b instanceof sigma?(b.graph.clear(),b.graph.read(d)):"object"==typeof b?(b.graph=d,b=new sigma(b)):"function"==typeof b&&(c=b,b=null),c&&c(b||d))},e.send()}}).call(this); -------------------------------------------------------------------------------- /lib/sigmajs/plugins/sigma.statistics.HITS.min.js: -------------------------------------------------------------------------------- 1 | (function(){"use strict";if("undefined"==typeof sigma)throw"sigma is not declared";sigma.classes.graph.addMethod("HITS",function(a){var b={},c=1e-4,d=[],e=[],f=this.nodes(),g=(f.length,{});a||(a=!1);for(var h in f)a?(d.push(f[h]),e.push(f[h])):(this.degree(f[h].id,"out")>0&&d.push(f[h]),this.degree(f[h].id,"in")>0&&e.push(f[h])),b[f[h].id]={authority:1,hub:1};for(var i;;){i=!0;var j=0,k=0;for(var h in e){g[e[h].id]={authority:1,hub:0};var l=[];l=a?this.allNeighborsIndex[e[h].id]:this.inNeighborsIndex[e[h].id];for(var m in l)m!=e[h].id&&(g[e[h].id].authority+=b[m].hub);j+=g[e[h].id].authority}for(var h in d){g[d[h].id]?g[d[h].id].hub=1:g[d[h].id]={authority:0,hub:1};var l=[];l=a?this.allNeighborsIndex[d[h].id]:this.outNeighborsIndex[d[h].id];for(var m in l)m!=d[h].id&&(g[d[h].id].hub+=b[m].authority);k+=g[d[h].id].hub}for(var h in e)g[e[h].id].authority/=j,Math.abs((g[e[h].id].authority-b[e[h].id].authority)/b[e[h].id].authority)>=c&&(i=!1);for(var h in d)g[d[h].id].hub/=k,Math.abs((g[d[h].id].hub-b[d[h].id].hub)/b[d[h].id].hub)>=c&&(i=!1);if(b=g,g={},i)break}return b})}).call(window); -------------------------------------------------------------------------------- /js/sigma-graph.js: -------------------------------------------------------------------------------- 1 | var g = $graph_data ; 2 | 3 | s = new sigma({graph: g, container: '$container', settings: { defaultNodeColor: '#ec5148'} }); 4 | 5 | s.graph.nodes().forEach(function(n) { 6 | n.originalColor = n.color; 7 | }); 8 | s.graph.edges().forEach(function(e) { 9 | e.originalColor = e.color; 10 | }); 11 | 12 | s.bind('clickNode', function(e) { 13 | var nodeId = e.data.node.id, 14 | toKeep = s.graph.neighbors(nodeId); 15 | toKeep[nodeId] = e.data.node; 16 | 17 | s.graph.nodes().forEach(function(n) { 18 | if (toKeep[n.id]) 19 | n.color = n.originalColor; 20 | else 21 | n.color = '#eee'; 22 | }); 23 | 24 | s.graph.edges().forEach(function(e) { 25 | if (toKeep[e.source] && toKeep[e.target]) 26 | e.color = e.originalColor; 27 | else 28 | e.color = '#eee'; 29 | }); 30 | 31 | s.refresh(); 32 | }); 33 | 34 | s.bind('clickStage', function(e) { 35 | s.graph.nodes().forEach(function(n) { 36 | n.color = n.originalColor; 37 | }); 38 | 39 | s.graph.edges().forEach(function(e) { 40 | e.color = e.originalColor; 41 | }); 42 | 43 | s.refresh(); 44 | }); 45 | -------------------------------------------------------------------------------- /lib/sigmajs/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (C) 2013-2014, Alexis Jacomy, http://sigmajs.org 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), 4 | to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 5 | and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 10 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 11 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 12 | IN THE SOFTWARE. 13 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Stitch Fix 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the Software), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /d3_lib.py: -------------------------------------------------------------------------------- 1 | import random 2 | import inspect, os 3 | from string import Template 4 | 5 | 6 | def this_dir(): 7 | this_file = inspect.getfile(inspect.currentframe()) 8 | return os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) 9 | 10 | 11 | def set_styles(css_file_names): 12 | if type(css_file_names) == str: 13 | style = open(this_dir() + '/css/' + css_file_names + '.css','r').read() 14 | else: 15 | style = '' 16 | for css_file_name in css_file_names: 17 | style += open(this_dir() + '/css/' + css_file_name + '.css','r').read() 18 | return "" 19 | 20 | 21 | def draw_graph(type, data_dict): 22 | 23 | JS_text = Template(''' 24 | 25 |
26 | 27 | 30 | 31 | ''') 32 | 33 | divnum = int(random.uniform(0,9999999999)) 34 | data_dict['divnum'] = divnum 35 | main_text_template = Template( open(this_dir() + '/js/' + type + '.js','r').read() ) 36 | main_text = main_text_template.safe_substitute(data_dict) 37 | 38 | return JS_text.safe_substitute({'divnum': divnum, 'main_text': main_text}) 39 | -------------------------------------------------------------------------------- /css/temperature_histories.css: -------------------------------------------------------------------------------- 1 | 2 | .loading-data-text { 3 | font-size: 10px; 4 | font-style: italic; 5 | } 6 | 7 | .handleText { 8 | opacity: 0.5; 9 | font-size: 10px; 10 | } 11 | 12 | .siteNameText { 13 | opacity: 0.5; 14 | font-size: 10px; 15 | } 16 | 17 | .pathCountry { 18 | stroke: white; 19 | stroke-width: 0.25px; 20 | fill: #bbb; 21 | } 22 | 23 | .pathSite { 24 | stroke: black; 25 | fill-opacity: 0.8; 26 | stroke-width: 1px; 27 | cursor: pointer; 28 | } 29 | 30 | .linegraph { 31 | stroke: black; 32 | fill-opacity: 0.8; 33 | stroke-opacity: 1e-6; 34 | stroke-width: 1px; 35 | } 36 | 37 | .pathStart { 38 | opacity: 0.5; 39 | cursor: pointer; 40 | } 41 | 42 | .tempTypeTextActive { 43 | opacity: 0.5; 44 | font-size: 10px; 45 | } 46 | 47 | .tempTypeTextInactive { 48 | opacity: 0.25; 49 | font-size: 10px; 50 | cursor: pointer; 51 | } 52 | 53 | .axis { 54 | opacity: 0.5; 55 | font-size: 10px; 56 | -webkit-user-select: none; 57 | -moz-user-select: none; 58 | user-select: none; 59 | } 60 | 61 | .axis .domain { 62 | fill: none; 63 | stroke: #555; 64 | stroke-opacity: .5; 65 | stroke-width: 1.25px; 66 | stroke-linecap: round; 67 | } 68 | 69 | .slider .handle { 70 | fill: #fff; 71 | stroke: #555; 72 | stroke-opacity: .5; 73 | stroke-width: 1.25px; 74 | cursor: grab; 75 | } 76 | -------------------------------------------------------------------------------- /lib/sigmajs/plugins/sigma.plugins.neighborhoods.min.js: -------------------------------------------------------------------------------- 1 | (function(){"use strict";if("undefined"==typeof sigma)throw"sigma is not declared";sigma.classes.graph.addMethod("neighborhood",function(a){var b,c,d,e,f,g={},h={},i={nodes:[],edges:[]};if(!this.nodes(a))return i;e=this.nodes(a),f={},f.center=!0;for(b in e)f[b]=e[b];g[a]=!0,i.nodes.push(f);for(b in this.allNeighborsIndex[a]){g[b]||(g[b]=!0,i.nodes.push(this.nodesIndex[b]));for(c in this.allNeighborsIndex[a][b])h[c]||(h[c]=!0,i.edges.push(this.edgesIndex[c]))}for(b in g)if(b!==a)for(c in g)if(c!==a&&b!==c&&this.allNeighborsIndex[b][c])for(d in this.allNeighborsIndex[b][c])h[d]||(h[d]=!0,i.edges.push(this.edgesIndex[d]));return i}),sigma.utils.pkg("sigma.plugins"),sigma.plugins.neighborhoods=function(){var a=new sigma.classes.graph;this.neighborhood=function(b){return a.neighborhood(b)},this.load=function(b,c){var d=function(){if(window.XMLHttpRequest)return new XMLHttpRequest;var a,b;if(window.ActiveXObject){a=["Msxml2.XMLHTTP.6.0","Msxml2.XMLHTTP.3.0","Msxml2.XMLHTTP","Microsoft.XMLHTTP"];for(b in a)try{return new ActiveXObject(a[b])}catch(c){}}return null}();if(!d)throw"XMLHttpRequest not supported, cannot load the data.";return d.open("GET",b,!0),d.onreadystatechange=function(){4===d.readyState&&(a.clear().read(JSON.parse(d.responseText)),c&&c())},d.send(),this},this.read=function(b){a.clear().read(b)}}}).call(window); -------------------------------------------------------------------------------- /lib/d3/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010-2015, Michael Bostock 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * The name Michael Bostock may not be used to endorse or promote products 15 | derived from this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | DISCLAIMED. IN NO EVENT SHALL MICHAEL BOSTOCK BE LIABLE FOR ANY DIRECT, 21 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 22 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 24 | OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 25 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 26 | EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | -------------------------------------------------------------------------------- /js/force_directed_graph.js: -------------------------------------------------------------------------------- 1 | 2 | // Based on http://bl.ocks.org/mbostock/4062045 3 | 4 | var width = 960, 5 | height = 500; 6 | 7 | var color = d3.scale.category20(); 8 | 9 | var force = d3.layout.force() 10 | .charge(-300) 11 | .linkDistance(50) 12 | .size([width, height]); 13 | 14 | d3.select("#maindiv${divnum}").selectAll("svg").remove(); 15 | var svg = d3.select("#maindiv${divnum}").append("svg") 16 | .attr("width", width) 17 | .attr("height", height); 18 | 19 | //d3.json("miserables.json", function(error, graph) { 20 | // if (error) throw error; 21 | var graph = $data ; 22 | 23 | force 24 | .nodes(graph.nodes) 25 | .links(graph.links) 26 | .start(); 27 | 28 | var link = svg.selectAll(".link") 29 | .data(graph.links) 30 | .enter().append("line") 31 | .attr("class", "link") 32 | .style("stroke-width", function(d) { return Math.sqrt(d.value); }); 33 | 34 | var node = svg.selectAll(".node") 35 | .data(graph.nodes) 36 | .enter().append("circle") 37 | .attr("class", "node") 38 | .attr("r", 8) 39 | .style("fill", function(d) { return color(d.group); }) 40 | .call(force.drag); 41 | 42 | node.append("title") 43 | .text(function(d) { return d.name; }); 44 | 45 | force.on("tick", function() { 46 | link.attr("x1", function(d) { return d.source.x; }) 47 | .attr("y1", function(d) { return d.source.y; }) 48 | .attr("x2", function(d) { return d.target.x; }) 49 | .attr("y2", function(d) { return d.target.y; }); 50 | 51 | node.attr("cx", function(d) { return d.x; }) 52 | .attr("cy", function(d) { return d.y; }); 53 | }); 54 | 55 | //}); 56 | 57 | -------------------------------------------------------------------------------- /lib/sigmajs/plugins/sigma.plugins.animate.min.js: -------------------------------------------------------------------------------- 1 | (function(){"use strict";function a(a){if(d[a])return d[a];var b=[0,0,0];return a.match(/^#/)?(a=(a||"").replace(/^#/,""),b=3===a.length?[parseInt(a.charAt(0)+a.charAt(0),16),parseInt(a.charAt(1)+a.charAt(1),16),parseInt(a.charAt(2)+a.charAt(2),16)]:[parseInt(a.charAt(0)+a.charAt(1),16),parseInt(a.charAt(2)+a.charAt(3),16),parseInt(a.charAt(4)+a.charAt(5),16)]):a.match(/^ *rgba? *\(/)&&(a=a.match(/^ *rgba? *\( *([0-9]*) *, *([0-9]*) *, *([0-9]*) *(,.*)?\) *$/),b=[+a[1],+a[2],+a[3]]),d[a]={r:b[0],g:b[1],b:b[2]},d[a]}function b(b,c,d){b=a(b),c=a(c);var e={r:b.r*(1-d)+c.r*d,g:b.g*(1-d)+c.g*d,b:b.b*(1-d)+c.b*d};return"rgb("+[0|e.r,0|e.g,0|e.b].join(",")+")"}if("undefined"==typeof sigma)throw"sigma is not declared";sigma.utils.pkg("sigma.plugins");var c=0,d={};sigma.plugins.animate=function(a,d,e){function f(){var c=(sigma.utils.dateNow()-k)/i;c>=1?(a.graph.nodes().forEach(function(a){for(var b in d)b in d&&(a[b]=a[d[b]])}),a.refresh(),"function"==typeof g.onComplete&&g.onComplete()):(c=j(c),a.graph.nodes().forEach(function(a){for(var e in d)e in d&&(a[e]=e.match(/color$/)?b(l[a.id][e],a[d[e]],c):a[d[e]]*c+l[a.id][e]*(1-c))}),a.refresh(),a.animations[h]=requestAnimationFrame(f))}var g=e||{},h=++c,i=g.duration||a.settings("animationsTime"),j="string"==typeof g.easing?sigma.utils.easings[g.easing]:"function"==typeof g.easing?g.easing:sigma.utils.easings.quadraticInOut,k=sigma.utils.dateNow(),l=a.graph.nodes().reduce(function(a,b){var c;a[b.id]={};for(c in d)c in b&&(a[b.id][c]=b[c]);return a},{});a.animations=a.animations||Object.create({}),sigma.plugins.kill(a),f()},sigma.plugins.kill=function(a){for(var b in a.animations||{})cancelAnimationFrame(a.animations[b])}}).call(window); -------------------------------------------------------------------------------- /lib/sigmajs/plugins/sigma.plugins.dragNodes.min.js: -------------------------------------------------------------------------------- 1 | (function(){"use strict";if("undefined"==typeof sigma)throw"sigma is not declared";sigma.utils.pkg("sigma.plugins"),sigma.plugins.dragNodes=function(a,b){if(sigma.renderers.webgl&&b instanceof sigma.renderers.webgl)throw new Error("The sigma.plugins.dragNodes is not compatible with the WebGL renderer");var c=document.body,d=b.container,e=d.lastChild,f=b.camera,g=null,h="",i=[],j=!1;h=b instanceof sigma.renderers.webgl?b.options.prefix.substr(5):b.options.prefix;var k=function(a){var b=window.getComputedStyle(a),c=function(a){return parseInt(b.getPropertyValue(a).replace("px",""))||0};return{left:a.getBoundingClientRect().left+c("padding-left"),top:a.getBoundingClientRect().top+c("padding-top")}},l=function(a){i.push(a.data.node),i.length&&!j&&(g=i[i.length-1],e.addEventListener("mousedown",n))},m=function(a){var b=i.map(function(a){return a}).indexOf(a.data.node);i.splice(b,1),i.length&&!j?g=i[i.length-1]:e.removeEventListener("mousedown",n)},n=function(){j=!0;var d=a.graph.nodes().length;d>1&&(e.removeEventListener("mousedown",n),c.addEventListener("mousemove",p),c.addEventListener("mouseup",o),b.settings({mouseEnabled:!1,enableHovering:!1}),a.refresh())},o=function(){j=!1,e.addEventListener("mousedown",n),c.removeEventListener("mousemove",p),c.removeEventListener("mouseup",o),b.settings({mouseEnabled:!0,enableHovering:!0}),a.refresh()},p=function(b){function c(){for(var c=k(d),e=b.pageX-c.left,i=b.pageY-c.top,j=Math.cos(f.angle),l=Math.sin(f.angle),m=a.graph.nodes(),n=[],o=0;2>o;o++){var p=m[o],q={x:p.x*j+p.y*l,y:p.y*j-p.x*l,renX:p[h+"x"],renY:p[h+"y"]};n.push(q)}e=(e-n[0].renX)/(n[1].renX-n[0].renX)*(n[1].x-n[0].x)+n[0].x,i=(i-n[0].renY)/(n[1].renY-n[0].renY)*(n[1].y-n[0].y)+n[0].y,g.x=e*j-i*l,g.y=i*j+e*l,a.refresh()}if(navigator.userAgent.toLowerCase().indexOf("firefox")>-1){clearTimeout(e);var e=setTimeout(c,0)}else c()};b.bind("overNode",l),b.bind("outNode",m)}}).call(window); -------------------------------------------------------------------------------- /lib/sigmajs/README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.org/jacomyal/sigma.js.png)](https://travis-ci.org/jacomyal/sigma.js) 2 | 3 | sigma.js - v1.0.3 4 | ================= 5 | 6 | Sigma is a JavaScript library dedicated to graph drawing. 7 | 8 | ### Resources 9 | 10 | [The website](http://sigmajs.org) provides a global overview of the project, and the documentation is available in the [Github Wiki](https://github.com/jacomyal/sigma.js/wiki). 11 | 12 | Also, the `plugins` and `examples` directories contain some various use-cases, that might help you understanding how to use sigma. 13 | 14 | ### How to use it 15 | 16 | To use it, clone the repository: 17 | 18 | ``` 19 | git clone git@github.com:jacomyal/sigma.js.git 20 | ``` 21 | 22 | To build the code: 23 | 24 | - Install [Node.js](http://nodejs.org/). 25 | - Install [gjslint](https://developers.google.com/closure/utilities/docs/linter_howto?hl=en). 26 | - Use `npm install` to install sigma development dependencies. 27 | - Use `npm run build` to minify the code with [Uglify](https://github.com/mishoo/UglifyJS). The minified file `sigma.min.js` will then be accessible in the `build/` folder. 28 | 29 | Also, you can customize the build by adding or removing files from the `coreJsFiles` array in `Gruntfile.js` before applying the grunt task. 30 | 31 | ### Contributing 32 | 33 | You can contribute by submitting [issues tickets](http://github.com/jacomyal/sigma.js/issues) and proposing [pull requests](http://github.com/jacomyal/sigma.js/pulls). Make sure that tests and linting pass before submitting any pull request by running the command `grunt`. 34 | 35 | The whole source code is validated by the [Google Closure Linter](https://developers.google.com/closure/utilities/) and [JSHint](http://www.jshint.com/), and the comments are written in [JSDoc](http://en.wikipedia.org/wiki/JSDoc) (tags description is available [here](https://developers.google.com/closure/compiler/docs/js-for-compiler)). 36 | -------------------------------------------------------------------------------- /js/basic_line.js: -------------------------------------------------------------------------------- 1 | 2 | // Based on http://bl.ocks.org/d3noob/b3ff6ae1c120eea654b5 : 3 | 4 | // Set the dimensions of the canvas / graph 5 | var margin = {top: 30, right: 20, bottom: 30, left: 50}, 6 | width = 600 - margin.left - margin.right, 7 | height = 270 - margin.top - margin.bottom; 8 | 9 | // Set the ranges 10 | var x = d3.scale.linear().range([0, width]); 11 | var y = d3.scale.linear().range([height, 0]); 12 | 13 | // Define the axes 14 | var xAxis = d3.svg.axis().scale(x) 15 | .orient("bottom").ticks(5); 16 | 17 | var yAxis = d3.svg.axis().scale(y) 18 | .orient("left").ticks(5); 19 | 20 | // Define the line 21 | var valueline = d3.svg.line() 22 | .x(function(d) { return x(d.x); }) 23 | .y(function(d) { return y(d.y); }); 24 | 25 | // Adds the svg canvas 26 | d3.select("#maindiv${divnum}").selectAll("svg").remove(); 27 | var svg = d3.select("#maindiv${divnum}") 28 | .append("svg") 29 | .attr("width", width + margin.left + margin.right) 30 | .attr("height", height + margin.top + margin.bottom) 31 | .append("g") 32 | .attr("transform", 33 | "translate(" + margin.left + "," + margin.top + ")"); 34 | 35 | // Get the data 36 | //d3.csv("data.csv", function(error, data) { 37 | var data = $data; 38 | 39 | data.forEach(function(d) { 40 | d.x = +d.x; 41 | d.y = +d.y; 42 | }); 43 | 44 | // Scale the range of the data 45 | x.domain(d3.extent(data, function(d) { return d.x; })); 46 | y.domain([0, d3.max(data, function(d) { return d.y; })]); 47 | 48 | // Add the valueline path 49 | svg.append("path") 50 | .attr("class", "line") 51 | .attr("d", valueline(data)); 52 | 53 | // Add the X Axis 54 | svg.append("g") 55 | .attr("class", "x axis") 56 | .attr("transform", "translate(0," + height + ")") 57 | .call(xAxis); 58 | 59 | // Add the Y Axis 60 | svg.append("g") 61 | .attr("class", "y axis") 62 | .call(yAxis); 63 | 64 | //}); 65 | -------------------------------------------------------------------------------- /js/basic_scatter.js: -------------------------------------------------------------------------------- 1 | 2 | // Based on http://bl.ocks.org/mbostock/3887118 3 | 4 | var margin = {top: 20, right: 20, bottom: 30, left: 40}, 5 | width = 600 - margin.left - margin.right, 6 | height = 270 - margin.top - margin.bottom; 7 | 8 | var x = d3.scale.linear() 9 | .range([0, width]); 10 | 11 | var y = d3.scale.linear() 12 | .range([height, 0]); 13 | 14 | var color = d3.scale.category10(); 15 | 16 | var xAxis = d3.svg.axis() 17 | .scale(x) 18 | .orient("bottom"); 19 | 20 | var yAxis = d3.svg.axis() 21 | .scale(y) 22 | .orient("left"); 23 | 24 | d3.select("#maindiv${divnum}").selectAll("svg").remove(); 25 | var svg = d3.select("#maindiv${divnum}").append("svg") 26 | .attr("width", width + margin.left + margin.right) 27 | .attr("height", height + margin.top + margin.bottom) 28 | .append("g") 29 | .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 30 | 31 | //d3.tsv("data.tsv", function(error, data) { 32 | // if (error) throw error; 33 | var data = $data; 34 | 35 | data.forEach(function(d) { 36 | d.x = +d.x; 37 | d.y = +d.y; 38 | }); 39 | 40 | x.domain(d3.extent(data, function(d) { return d.x; })).nice(); 41 | y.domain(d3.extent(data, function(d) { return d.y; })).nice(); 42 | 43 | svg.append("g") 44 | .attr("class", "x axis") 45 | .attr("transform", "translate(0," + height + ")") 46 | .call(xAxis); 47 | 48 | svg.append("g") 49 | .attr("class", "y axis") 50 | .call(yAxis); 51 | 52 | svg.selectAll(".dot") 53 | .data(data) 54 | .enter().append("circle") 55 | .attr("class", "dot") 56 | .attr("r", 3.5) 57 | .attr("cx", function(d) { return x(d.x); }) 58 | .attr("cy", function(d) { return y(d.y); }) 59 | .style("fill", function(d) { return color(d.c); }); 60 | 61 | var legend = svg.selectAll(".legend") 62 | .data(color.domain()) 63 | .enter().append("g") 64 | .attr("class", "legend") 65 | .attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; }); 66 | 67 | legend.append("rect") 68 | .attr("x", width - 18) 69 | .attr("width", 18) 70 | .attr("height", 18) 71 | .style("fill", color); 72 | 73 | legend.append("text") 74 | .attr("x", width - 24) 75 | .attr("y", 9) 76 | .attr("dy", ".35em") 77 | .style("text-anchor", "end") 78 | .text(function(d) { return d; }); 79 | 80 | //}); 81 | 82 | -------------------------------------------------------------------------------- /lib/sigmajs/plugins/sigma.renderers.customShapes.min.js: -------------------------------------------------------------------------------- 1 | (function(){"use strict";var a=[],b=function(b,c,d){a.push({name:b,drawShape:c,drawBorder:d})},c=function(){return a},d=function(a){return function(b,c,d,e,f,g){g.fillStyle=f,g.beginPath(),a(b,c,d,e,g),g.closePath(),g.fill()}},e=function(a){return function(b,c,d,e,f,g){g.strokeStyle=f,g.lineWidth=e/5,g.beginPath(),a(b,c,d,e,g),g.closePath(),g.stroke()}},f=function(a,b,c,d,e){var f=45*Math.PI/180;e.moveTo(b+d*Math.sin(f),c-d*Math.cos(f));for(var g=1;4>g;g++)e.lineTo(b+Math.sin(f+2*Math.PI*g/4)*d,c-Math.cos(f+2*Math.PI*g/4)*d)};b("square",d(f),e(f));var g=function(a,b,c,d,e){e.arc(b,c,d,0,2*Math.PI,!0)};b("circle",d(g),e(g));var h=function(a,b,c,d,e){e.moveTo(b-d,c),e.lineTo(b,c-d),e.lineTo(b+d,c),e.lineTo(b,c+d)};b("diamond",d(h),e(h));var i=function(a,b,c,d,e){var f=a.cross&&a.cross.lineWeight||5;e.moveTo(b-d,c-f),e.lineTo(b-d,c+f),e.lineTo(b-f,c+f),e.lineTo(b-f,c+d),e.lineTo(b+f,c+d),e.lineTo(b+f,c+f),e.lineTo(b+d,c+f),e.lineTo(b+d,c-f),e.lineTo(b+f,c-f),e.lineTo(b+f,c-d),e.lineTo(b-f,c-d),e.lineTo(b-f,c-f)};b("cross",d(i),e(i));var j=function(a,b,c,d,e){var f=a.equilateral&&a.equilateral.numPoints||5,g=(a.equilateral&&a.equilateral.rotate||0)*Math.PI/180,h=d;e.moveTo(b+h*Math.sin(g),c-h*Math.cos(g));for(var i=1;f>i;i++)e.lineTo(b+Math.sin(g+2*Math.PI*i/f)*h,c-Math.cos(g+2*Math.PI*i/f)*h)};b("equilateral",d(j),e(j));var k=function(a,b,c,d,e){var f=a.star&&a.star.numPoints||5,g=a.star&&a.star.innerRatio||.5,h=d,i=d*g,j=Math.PI/f;e.moveTo(b,c-d);for(var k=0;f>k;k++)e.lineTo(b+Math.sin(j+2*Math.PI*k/f)*i,c-Math.cos(j+2*Math.PI*k/f)*i),e.lineTo(b+Math.sin(2*Math.PI*(k+1)/f)*h,c-Math.cos(2*Math.PI*(k+1)/f)*h)};b("star",d(k),e(k));var l=function(a,b,c,d,e,f){f.fillStyle="yellow",f.beginPath(),f.arc(b,c,d,1.25*Math.PI,0,!1),f.arc(b,c,d,0,.75*Math.PI,!1),f.lineTo(b,c),f.closePath(),f.fill(),f.fillStyle="white",f.strokeStyle="black",f.beginPath(),f.arc(b+d/3,c-d/3,d/4,0,2*Math.PI,!1),f.closePath(),f.fill(),f.stroke(),f.fillStyle="black",f.beginPath(),f.arc(b+4*d/9,c-d/3,d/8,0,2*Math.PI,!1),f.closePath(),f.fill()};b("pacman",l,null),this.ShapeLibrary={enumerate:c,version:"0.1"}}).call(this),function(a){"use strict";if("undefined"==typeof sigma)throw"sigma is not declared";if("undefined"==typeof ShapeLibrary)throw"ShapeLibrary is not declared";sigma.utils.pkg("sigma.canvas.nodes");var b=a,c={},d=function(a){b=a},e=function(a,d,e,f,g){if(b&&a.image&&a.image.url){var h=a.image.url,i=a.image.h||1,j=a.image.w||1,k=a.image.scale||1,l=a.image.clip||1,m=c[h];m||(m=document.createElement("IMG"),m.src=h,m.onload=function(){console.log("redraw on image load"),b.refresh()},c[h]=m);var n=i>j?j/i:1,o=j>i?i/j:1,p=f*k;g.save(),g.beginPath(),g.arc(d,e,f*l,0,2*Math.PI,!0),g.closePath(),g.clip(),g.drawImage(m,d+Math.sin(-0.7855)*p*n,e-Math.cos(-0.7855)*p*o,p*n*2*Math.sin(-0.7855)*-1,p*o*2*Math.cos(-0.7855)),g.restore()}},f=function(a,b,c){sigma.canvas.nodes[a]=function(a,d,f){var g=f("prefix")||"",h=a[g+"size"],i=a.color||f("defaultNodeColor"),j=a.borderColor||i,k=a[g+"x"],l=a[g+"y"];d.save(),b&&b(a,k,l,h,i,d),c&&c(a,k,l,h,j,d),e(a,k,l,h,d),d.restore()}};ShapeLibrary.enumerate().forEach(function(a){f(a.name,a.drawShape,a.drawBorder)}),this.CustomShapes={init:d,version:"0.1"}}.call(this); -------------------------------------------------------------------------------- /js/day-hr-heatmap.js: -------------------------------------------------------------------------------- 1 | 2 | var margin = { top: 50, right: 0, bottom: 100, left: 30 }, 3 | width = 960 - margin.left - margin.right, 4 | height = 430 - margin.top - margin.bottom, 5 | gridSize = Math.floor(width / 24), 6 | legendElementWidth = gridSize*2, 7 | buckets = 9, 8 | colors = ["#ffffd9","#edf8b1","#c7e9b4","#7fcdbb","#41b6c4","#1d91c0","#225ea8","#253494","#081d58"], // alternatively colorbrewer.YlGnBu[9] 9 | days = ["Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"], 10 | times = ["1a", "2a", "3a", "4a", "5a", "6a", "7a", "8a", "9a", "10a", "11a", "12a", "1p", "2p", "3p", "4p", "5p", "6p", "7p", "8p", "9p", "10p", "11p", "12p"]; 11 | 12 | 13 | /* 14 | d3.tsv("data.tsv", 15 | function(d) { 16 | return { 17 | day: +d.day, 18 | hour: +d.hour, 19 | value: +d.value 20 | }; 21 | }, 22 | function(error, data) { 23 | */ 24 | 25 | var data = $data; 26 | 27 | var colorScale = d3.scale.quantile() 28 | .domain([0, buckets - 1, d3.max(data, function (d) { return d.value; })]) 29 | .range(colors); 30 | 31 | // var svg = d3.select("#chart").append("svg") 32 | var svg = d3.select("#maindiv${divnum}").append("svg") 33 | .attr("width", width + margin.left + margin.right) 34 | .attr("height", height + margin.top + margin.bottom) 35 | .append("g") 36 | .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 37 | 38 | var dayLabels = svg.selectAll(".dayLabel") 39 | .data(days) 40 | .enter().append("text") 41 | .text(function (d) { return d; }) 42 | .attr("x", 0) 43 | .attr("y", function (d, i) { return i * gridSize; }) 44 | .style("text-anchor", "end") 45 | .attr("transform", "translate(-6," + gridSize / 1.5 + ")") 46 | .attr("class", function (d, i) { return ((i >= 0 && i <= 4) ? "dayLabel mono axis axis-workweek" : "dayLabel mono axis"); }); 47 | 48 | var timeLabels = svg.selectAll(".timeLabel") 49 | .data(times) 50 | .enter().append("text") 51 | .text(function(d) { return d; }) 52 | .attr("x", function(d, i) { return i * gridSize; }) 53 | .attr("y", 0) 54 | .style("text-anchor", "middle") 55 | .attr("transform", "translate(" + gridSize / 2 + ", -6)") 56 | .attr("class", function(d, i) { return ((i >= 7 && i <= 16) ? "timeLabel mono axis axis-worktime" : "timeLabel mono axis"); }); 57 | 58 | var heatMap = svg.selectAll(".hour") 59 | .data(data) 60 | .enter().append("rect") 61 | .attr("x", function(d) { return (d.hour - 1) * gridSize; }) 62 | .attr("y", function(d) { return (d.day - 1) * gridSize; }) 63 | .attr("rx", 4) 64 | .attr("ry", 4) 65 | .attr("class", "hour bordered") 66 | .attr("width", gridSize) 67 | .attr("height", gridSize) 68 | .style("fill", colors[0]); 69 | 70 | heatMap.transition().duration(1000) 71 | .style("fill", function(d) { return colorScale(d.value); }); 72 | 73 | heatMap.append("title").text(function(d) { return d.value; }); 74 | 75 | var legend = svg.selectAll(".legend") 76 | .data([0].concat(colorScale.quantiles()), function(d) { return d; }) 77 | .enter().append("g") 78 | .attr("class", "legend"); 79 | 80 | legend.append("rect") 81 | .attr("x", function(d, i) { return legendElementWidth * i; }) 82 | .attr("y", height) 83 | .attr("width", legendElementWidth) 84 | .attr("height", gridSize / 2) 85 | .style("fill", function(d, i) { return colors[i]; }); 86 | 87 | legend.append("text") 88 | .attr("class", "mono") 89 | .text(function(d) { return " " + Math.round(d); }) 90 | .attr("x", function(d, i) { return legendElementWidth * i; }) 91 | .attr("y", height + gridSize); 92 | 93 | /* 94 | }); 95 | */ 96 | 97 | -------------------------------------------------------------------------------- /lib/sigmajs/plugins/sigma.plugins.filter.min.js: -------------------------------------------------------------------------------- 1 | (function(undefined){"use strict";function register(a,b,c){if(c!=undefined&&"string"!=typeof c)throw'The filter key "'+c.toString()+'" must be a string.';if(c!=undefined&&!c.length)throw"The filter key must be a non-empty string.";if("function"!=typeof a)throw'The predicate of key "'+c+'" must be a function.';if("undo"===c)throw'"undo" is a reserved key.';if(_keysIndex[c])throw'The filter "'+c+'" already exists.';c&&(_keysIndex[c]=!0),_chain.push({key:c,processor:a,predicate:b})}function unregister(a){_chain=_chain.filter(function(b){return!(b.key in a)});for(var b in a)delete _keysIndex[b]}function Filter(a){_s=a,_g=a.graph}function deepCopy(o){var copy=Object.create(null);for(var i in o)"object"==typeof o[i]&&null!==o[i]?copy[i]=deepCopy(o[i]):"function"==typeof o[i]&&null!==o[i]?eval(" copy[i] = "+o[i].toString()):copy[i]=o[i];return copy}function cloneChain(a){for(var b=a.slice(0),c=0,d=b.length;d>c;c++)b[c]=deepCopy(b[c]),"function"==typeof b[c].processor&&(b[c].processor="filter.processors."+b[c].processor.name);return b}if("undefined"==typeof sigma)throw"sigma is not declared";sigma.utils.pkg("sigma.plugins"),sigma.classes.graph.hasMethod("adjacentNodes")||sigma.classes.graph.addMethod("adjacentNodes",function(a){if("string"!=typeof a)throw"adjacentNodes: the node id must be a string.";var b,c=[];for(b in this.allNeighborsIndex[a])c.push(this.nodesIndex[b]);return c}),sigma.classes.graph.hasMethod("adjacentEdges")||sigma.classes.graph.addMethod("adjacentEdges",function(a){if("string"!=typeof a)throw"adjacentEdges: the node id must be a string.";var b,c,d=this.allNeighborsIndex[a],e=[];for(c in d)for(b in d[c])e.push(d[c][b]);return e});var _g=undefined,_s=undefined,_chain=[],_keysIndex=Object.create(null),Processors={};Processors.nodes=function(a){for(var b=_g.nodes(),c=b.length,d=_g.edges(),e=d.length;c--;)b[c].hidden=!a.call(_g,b[c])||b[c].hidden;for(;e--;)(_g.nodes(d[e].source).hidden||_g.nodes(d[e].target).hidden)&&(d[e].hidden=!0)},Processors.edges=function(a){for(var b=_g.edges(),c=b.length;c--;)b[c].hidden=!a.call(_g,b[c])||b[c].hidden},Processors.neighbors=function a(b){for(var c=_g.nodes(),d=c.length,e=_g.edges(),f=e.length,a=_g.adjacentNodes(b),g=a.length,h={};g--;)h[a[g].id]=!0;for(;d--;)c[d].id===b||c[d].id in h||(c[d].hidden=!0);for(;f--;)(_g.nodes(e[f].source).hidden||_g.nodes(e[f].target).hidden)&&(e[f].hidden=!0)},Filter.prototype.nodesBy=function(a,b){return register(Processors.nodes,a,b),this},Filter.prototype.edgesBy=function(a,b){return register(Processors.edges,a,b),this},Filter.prototype.neighborsOf=function(a,b){if("string"!=typeof a)throw'The node id "'+a.toString()+'" must be a string.';if(!a.length)throw"The node id must be a non-empty string.";return register(Processors.neighbors,a,b),this},Filter.prototype.apply=function(){for(var a=0,b=_chain.length;b>a;++a)_chain[a].processor(_chain[a].predicate);return _chain[0]&&"undo"===_chain[0].key&&_chain.shift(),_s.refresh(),this},Filter.prototype.undo=function(a){function b(){for(var a=_g.nodes(),b=a.length,c=_g.edges(),d=c.length;b--;)a[b].hidden=!1;for(;d--;)c[d].hidden=!1}var c=Object.create(null),d=arguments.length;if(1===d)if("[object Array]"===Object.prototype.toString.call(a))for(var e=0,f=a.length;f>e;e++)c[a[e]]=!0;else c[a]=!0;else if(d>1)for(var e=0;d>e;e++)c[arguments[e]]=!0;else this.clear();return unregister(c),_chain.unshift({key:"undo",processor:b}),this},Filter.prototype.clear=function(){return _chain.length=0,_keysIndex=Object.create(null),this},Filter.prototype.export=function(){var a=cloneChain(_chain);return a},Filter.prototype.import=function(a){if(a===undefined)throw"Wrong arguments.";if("[object Array]"!==Object.prototype.toString.call(a))throw'The chain" must be an array.';for(var b=cloneChain(a),c=0,d=b.length;d>c;c++){if(b[c].predicate===undefined||b[c].processor===undefined)throw"Wrong arguments.";if(b[c].key!=undefined&&"string"!=typeof b[c].key)throw'The filter key "'+b[c].key.toString()+'" must be a string.';if("function"!=typeof b[c].predicate)throw'The predicate of key "'+b[c].key+'" must be a function.';if("string"!=typeof b[c].processor)throw'The processor of key "'+b[c].key+'" must be a string.';switch(b[c].processor){case"filter.processors.nodes":b[c].processor=Processors.nodes;break;case"filter.processors.edges":b[c].processor=Processors.edges;break;case"filter.processors.neighbors":b[c].processor=Processors.neighbors;break;default:throw"Unknown processor "+b[c].processor}}return _chain=b,this};var filter=null;sigma.plugins.filter=function(a){return filter||(filter=new Filter(a)),filter}}).call(this); -------------------------------------------------------------------------------- /D3-Circle-Animation.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 72, 6 | "metadata": { 7 | "collapsed": false 8 | }, 9 | "outputs": [], 10 | "source": [ 11 | "from IPython.core.display import display, HTML\n", 12 | "from string import Template\n", 13 | "import json" 14 | ] 15 | }, 16 | { 17 | "cell_type": "code", 18 | "execution_count": 64, 19 | "metadata": { 20 | "collapsed": false 21 | }, 22 | "outputs": [ 23 | { 24 | "data": { 25 | "text/html": [ 26 | "" 27 | ], 28 | "text/plain": [ 29 | "" 30 | ] 31 | }, 32 | "execution_count": 64, 33 | "metadata": {}, 34 | "output_type": "execute_result" 35 | } 36 | ], 37 | "source": [ 38 | "HTML('')" 39 | ] 40 | }, 41 | { 42 | "cell_type": "code", 43 | "execution_count": 91, 44 | "metadata": { 45 | "collapsed": true 46 | }, 47 | "outputs": [], 48 | "source": [ 49 | "css_text = '''\n", 50 | "'''" 51 | ] 52 | }, 53 | { 54 | "cell_type": "code", 55 | "execution_count": 89, 56 | "metadata": { 57 | "collapsed": true 58 | }, 59 | "outputs": [], 60 | "source": [ 61 | "js_text_template = Template('''\n", 62 | " var bogoSVG = d3.select(\"#$bogoanimation\") \n", 63 | " .append(\"svg\")\n", 64 | " .attr(\"width\", 300)\n", 65 | " .attr(\"height\", 300); \n", 66 | "\n", 67 | " var data = $python_data ;\n", 68 | " bogoSVG.append(\"circle\")\n", 69 | " .style(\"stroke\", \"gray\")\n", 70 | " .style(\"fill\", \"cyan\")\n", 71 | " .attr(\"r\", data[0]['r'])\n", 72 | " .attr(\"cx\", data[0]['cx'])\n", 73 | " .attr(\"cy\", data[0]['cy'])\n", 74 | " .transition()\n", 75 | " .delay(100)\n", 76 | " .duration(20000) \n", 77 | " .attr(\"r\", 10)\n", 78 | " .attr(\"cx\", data[0]['cx'])\n", 79 | " .style(\"fill\", \"blue\"); \n", 80 | "''')" 81 | ] 82 | }, 83 | { 84 | "cell_type": "code", 85 | "execution_count": 86, 86 | "metadata": { 87 | "collapsed": true 88 | }, 89 | "outputs": [], 90 | "source": [ 91 | "html_template = Template('''\n", 92 | "\n", 93 | "
\n", 94 | "\n", 95 | "''')" 96 | ] 97 | }, 98 | { 99 | "cell_type": "code", 100 | "execution_count": 87, 101 | "metadata": { 102 | "collapsed": false 103 | }, 104 | "outputs": [], 105 | "source": [ 106 | "js_text = js_text_template.substitute({'python_data': json.dumps([{'r': 130, 'cx': 150, 'cy': 150}]),\n", 107 | " 'bogoanimation': 'animation'})" 108 | ] 109 | }, 110 | { 111 | "cell_type": "code", 112 | "execution_count": 92, 113 | "metadata": { 114 | "collapsed": false 115 | }, 116 | "outputs": [ 117 | { 118 | "data": { 119 | "text/html": [ 120 | "\n", 121 | "\n", 123 | "
\n", 124 | "\n" 144 | ], 145 | "text/plain": [ 146 | "" 147 | ] 148 | }, 149 | "execution_count": 92, 150 | "metadata": {}, 151 | "output_type": "execute_result" 152 | } 153 | ], 154 | "source": [ 155 | "HTML(html_template.substitute({'css_text': css_text, 'js_text': js_text}))" 156 | ] 157 | }, 158 | { 159 | "cell_type": "code", 160 | "execution_count": null, 161 | "metadata": { 162 | "collapsed": true 163 | }, 164 | "outputs": [], 165 | "source": [] 166 | }, 167 | { 168 | "cell_type": "code", 169 | "execution_count": null, 170 | "metadata": { 171 | "collapsed": true 172 | }, 173 | "outputs": [], 174 | "source": [] 175 | } 176 | ], 177 | "metadata": { 178 | "kernelspec": { 179 | "display_name": "Python 3", 180 | "language": "python", 181 | "name": "python3" 182 | }, 183 | "language_info": { 184 | "codemirror_mode": { 185 | "name": "ipython", 186 | "version": 3 187 | }, 188 | "file_extension": ".py", 189 | "mimetype": "text/x-python", 190 | "name": "python", 191 | "nbconvert_exporter": "python", 192 | "pygments_lexer": "ipython3", 193 | "version": "3.5.1" 194 | } 195 | }, 196 | "nbformat": 4, 197 | "nbformat_minor": 0 198 | } 199 | -------------------------------------------------------------------------------- /lib/sigmajs/plugins/sigma.parsers.gexf.min.js: -------------------------------------------------------------------------------- 1 | (function(a){"use strict";function b(a){var b={id:a.id,label:a.label};return a.viz&&(b.viz=a.viz),a.attributes&&(b.attributes=a.attributes),b}function c(a){var b={id:a.id,type:a.type||"undirected",label:a.label||"",source:a.source,target:a.target,weight:+a.weight||1};return a.viz&&(b.viz=a.viz),a.attributes&&(b.attributes=a.attributes),b}function d(a){function d(){var a={};return l.els.meta?(a.lastmodifieddate=l.els.meta.getAttribute("lastmodifieddate"),h.nodeListEach(l.els.meta.childNodes,function(b){a[b.tagName.toLowerCase()]=b.textContent}),a):a}function e(a){var b=[];return l.els.model[a]&&h.nodeListEach(l.els.model[a],function(a){var c={id:a.getAttribute("id")||a.getAttribute("for"),type:a.getAttribute("type")||"string",title:a.getAttribute("title")||""},d=h.nodeListToArray(a.childNodes);d.length>0&&(c.defaultValue=d[0].textContent),b.push(c)}),b.length>0?b:!1}function f(a,b){var c={},d=b.getElementsByTagName("attvalue"),e=h.nodeListToHash(d,function(a){var b=h.namedNodeMapToObject(a.attributes),c=b.id||b["for"];return{key:c,value:b.value}});return a.map(function(a){c[a.id]=!(a.id in e)&&"defaultValue"in a?h.enforceType(a.type,a.defaultValue):h.enforceType(a.type,e[a.id])}),c}function g(a){var c=[];return h.nodeListEach(l.els.nodes,function(d){var e={id:d.getAttribute("id"),label:d.getAttribute("label")||""};a&&(e.attributes=f(a,d)),l.hasViz&&(e.viz=i(d)),c.push(b(e))}),c}function i(a){var b={},c=h.getFirstElementByTagNS(a,"viz","color");if(c){var d=["r","g","b","a"].map(function(a){return c.getAttribute(a)});b.color=h.getRGB(d)}var e=h.getFirstElementByTagNS(a,"viz","position");e&&(b.position={},["x","y","z"].map(function(a){b.position[a]=+e.getAttribute(a)}));var f=h.getFirstElementByTagNS(a,"viz","size");f&&(b.size=+f.getAttribute("value"));var g=h.getFirstElementByTagNS(a,"viz","shape");return g&&(b.shape=g.getAttribute("value")),b}function j(a,b){var d=[];return h.nodeListEach(l.els.edges,function(e){var g=h.namedNodeMapToObject(e.attributes);"type"in g||(g.type=b),a&&(g.attributes=f(a,e)),l.hasViz&&(g.viz=k(e)),d.push(c(g))}),d}function k(a){var b={},c=h.getFirstElementByTagNS(a,"viz","color");if(c){var d=["r","g","b","a"].map(function(a){return c.getAttribute(a)});b.color=h.getRGB(d)}var e=h.getFirstElementByTagNS(a,"viz","shape");e&&(b.shape=e.getAttribute("value"));var f=h.getFirstElementByTagNS(a,"viz","thickness");return f&&(b.thickness=+f.getAttribute("value")),b}var l={};l.els={root:a.getElementsByTagName("gexf")[0],graph:a.getElementsByTagName("graph")[0],meta:a.getElementsByTagName("meta")[0],nodes:a.getElementsByTagName("node"),edges:a.getElementsByTagName("edge"),model:h.getModelTags(a)},l.hasViz=!!h.getAttributeNS(l.els.root,"xmlns","viz"),l.version=l.els.root.getAttribute("version")||"1.0",l.mode=l.els.graph.getAttribute("mode")||"static";var m=l.els.graph.getAttribute("defaultedgetype");l.defaultEdgetype=m||"undirected";var n=e("node"),o=e("edge"),p={version:l.version,mode:l.mode,defaultEdgeType:l.defaultEdgetype,meta:d(),model:{},nodes:g(n),edges:j(o,l.defaultEdgetype)};return n&&(p.model.node=n),o&&(p.model.edge=o),p}function e(a,b){var c=function(){if(window.XMLHttpRequest)return new XMLHttpRequest;var a,b;if(window.ActiveXObject){a=["Msxml2.XMLHTTP.6.0","Msxml2.XMLHTTP.3.0","Msxml2.XMLHTTP","Microsoft.XMLHTTP"];for(b in a)try{return new ActiveXObject(a[b])}catch(c){}}return null}();if(!c)throw"XMLHttpRequest not supported, cannot load the file.";var d,e="function"==typeof b;return c.overrideMimeType?(c.overrideMimeType("text/xml"),d=function(a){return a.responseXML}):d=function(a){var b=new DOMParser;return b.parseFromString(a.responseText,"application/xml")},c.open("GET",a,e),e&&(c.onreadystatechange=function(){4===c.readyState&&b(d(c))}),c.send(),e?c:d(c)}function f(a){return d(a)}function g(a,b){return"function"==typeof b?e(a,function(a){b(d(a))}):d(e(a))}var h={getModelTags:function(a){var b,c=a.getElementsByTagName("attributes"),d={},e=c.length;for(b=0;e>b;b++)d[c[b].getAttribute("class")]=c[b].childNodes;return d},nodeListToArray:function(a){for(var b=[],c=0,d=a.length;d>c;++c)"#text"!==a[c].nodeName&&b.push(a[c]);return b},nodeListEach:function(a,b){for(var c=0,d=a.length;d>c;++c)"#text"!==a[c].nodeName&&b(a[c])},nodeListToHash:function(a,b){for(var c={},d=0;df;f++)i=h[f],i.id=i.id,i.viz&&"object"==typeof i.viz&&(i.viz.position&&"object"==typeof i.viz.position&&(i.x=i.viz.position.x,i.y=-i.viz.position.y),i.size=i.viz.size,i.color=i.viz.color);for(h=b.edges,f=0,g=h.length;g>f;f++)i=h[f],i.id="string"==typeof i.id?i.id:a(),i.source=""+i.source,i.target=""+i.target,i.viz&&"object"==typeof i.viz&&(i.color=i.viz.color,i.size=i.viz.thickness),i.size=i.weight;if(c instanceof sigma){for(c.graph.clear(),h=b.nodes,f=0,g=h.length;g>f;f++)c.graph.addNode(h[f]);for(h=b.edges,f=0,g=h.length;g>f;f++)c.graph.addEdge(h[f])}else"object"==typeof c?(c.graph=b,c=new sigma(c)):"function"==typeof c&&(d=c,c=null);return d?void d(c||b):b}var f,g,h,i;if("string"==typeof b)gexf.fetch(b,e);else if("object"==typeof b)return e(gexf.parse(b))}}.call(this); -------------------------------------------------------------------------------- /randomized_sketch.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Randomized Sketch" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "This is a demonstration of importing a SVG and modifying it with D3." 15 | ] 16 | }, 17 | { 18 | "cell_type": "code", 19 | "execution_count": 1, 20 | "metadata": { 21 | "collapsed": true 22 | }, 23 | "outputs": [], 24 | "source": [ 25 | "from IPython.core.display import display, HTML\n", 26 | "from string import Template\n", 27 | "import pandas as pd\n", 28 | "import json, random" 29 | ] 30 | }, 31 | { 32 | "cell_type": "code", 33 | "execution_count": 2, 34 | "metadata": { 35 | "collapsed": false 36 | }, 37 | "outputs": [ 38 | { 39 | "data": { 40 | "text/html": [ 41 | "" 42 | ], 43 | "text/plain": [ 44 | "" 45 | ] 46 | }, 47 | "execution_count": 2, 48 | "metadata": {}, 49 | "output_type": "execute_result" 50 | } 51 | ], 52 | "source": [ 53 | "HTML('')" 54 | ] 55 | }, 56 | { 57 | "cell_type": "code", 58 | "execution_count": 3, 59 | "metadata": { 60 | "collapsed": false 61 | }, 62 | "outputs": [ 63 | { 64 | "data": { 65 | "text/html": [ 66 | "\n", 67 | "\n", 68 | "\n", 70 | "\n", 73 | "\n", 74 | "\n", 75 | "\n", 76 | "\n", 77 | "\n", 78 | "\n", 79 | "\n", 80 | "\n", 81 | "\n", 82 | "\n" 83 | ], 84 | "text/plain": [ 85 | "" 86 | ] 87 | }, 88 | "execution_count": 3, 89 | "metadata": {}, 90 | "output_type": "execute_result" 91 | } 92 | ], 93 | "source": [ 94 | "HTML('''\n", 95 | "\n", 96 | "\n", 98 | "\n", 101 | "\n", 102 | "\n", 103 | "\n", 104 | "\n", 105 | "\n", 106 | "\n", 107 | "\n", 108 | "\n", 109 | "\n", 110 | "\n", 111 | "''')" 112 | ] 113 | }, 114 | { 115 | "cell_type": "code", 116 | "execution_count": 4, 117 | "metadata": { 118 | "collapsed": true 119 | }, 120 | "outputs": [], 121 | "source": [ 122 | "dx_max, dy_max = 100, 70" 123 | ] 124 | }, 125 | { 126 | "cell_type": "code", 127 | "execution_count": 5, 128 | "metadata": { 129 | "collapsed": false 130 | }, 131 | "outputs": [ 132 | { 133 | "data": { 134 | "text/html": [ 135 | "" 146 | ], 147 | "text/plain": [ 148 | "" 149 | ] 150 | }, 151 | "execution_count": 5, 152 | "metadata": {}, 153 | "output_type": "execute_result" 154 | } 155 | ], 156 | "source": [ 157 | "HTML(Template('''''').substitute({'dx_max': dx_max, 'dy_max': dy_max}))" 168 | ] 169 | }, 170 | { 171 | "cell_type": "code", 172 | "execution_count": 6, 173 | "metadata": { 174 | "collapsed": false 175 | }, 176 | "outputs": [ 177 | { 178 | "data": { 179 | "text/html": [ 180 | "\n", 181 | "\n" 182 | ], 183 | "text/plain": [ 184 | "" 185 | ] 186 | }, 187 | "execution_count": 6, 188 | "metadata": {}, 189 | "output_type": "execute_result" 190 | } 191 | ], 192 | "source": [ 193 | "HTML('''\n", 194 | "\n", 195 | "''')" 196 | ] 197 | } 198 | ], 199 | "metadata": { 200 | "kernelspec": { 201 | "display_name": "Python 2", 202 | "language": "python", 203 | "name": "python2" 204 | }, 205 | "language_info": { 206 | "codemirror_mode": { 207 | "name": "ipython", 208 | "version": 2 209 | }, 210 | "file_extension": ".py", 211 | "mimetype": "text/x-python", 212 | "name": "python", 213 | "nbconvert_exporter": "python", 214 | "pygments_lexer": "ipython2", 215 | "version": "2.7.10" 216 | } 217 | }, 218 | "nbformat": 4, 219 | "nbformat_minor": 0 220 | } 221 | -------------------------------------------------------------------------------- /hello_dom.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Hello DOM!\n", 8 | "\n", 9 | "A one-step at a time introduction to using D3 in Jupyter" 10 | ] 11 | }, 12 | { 13 | "cell_type": "code", 14 | "execution_count": 1, 15 | "metadata": { 16 | "collapsed": true 17 | }, 18 | "outputs": [], 19 | "source": [ 20 | "from IPython.core.display import HTML" 21 | ] 22 | }, 23 | { 24 | "cell_type": "code", 25 | "execution_count": 2, 26 | "metadata": { 27 | "collapsed": false 28 | }, 29 | "outputs": [ 30 | { 31 | "data": { 32 | "text/html": [ 33 | "\n", 34 | "

Hello DOM!

\n" 35 | ], 36 | "text/plain": [ 37 | "" 38 | ] 39 | }, 40 | "execution_count": 2, 41 | "metadata": {}, 42 | "output_type": "execute_result" 43 | } 44 | ], 45 | "source": [ 46 | "HTML('''\n", 47 | "

Hello DOM!

\n", 48 | "''')" 49 | ] 50 | }, 51 | { 52 | "cell_type": "code", 53 | "execution_count": 3, 54 | "metadata": { 55 | "collapsed": false 56 | }, 57 | "outputs": [ 58 | { 59 | "data": { 60 | "text/html": [ 61 | "\n", 62 | "\n", 68 | "

Hello DOM!

\n" 69 | ], 70 | "text/plain": [ 71 | "" 72 | ] 73 | }, 74 | "execution_count": 3, 75 | "metadata": {}, 76 | "output_type": "execute_result" 77 | } 78 | ], 79 | "source": [ 80 | "HTML('''\n", 81 | "\n", 87 | "

Hello DOM!

\n", 88 | "''')" 89 | ] 90 | }, 91 | { 92 | "cell_type": "code", 93 | "execution_count": 4, 94 | "metadata": { 95 | "collapsed": false 96 | }, 97 | "outputs": [ 98 | { 99 | "data": { 100 | "text/html": [ 101 | "\n", 102 | "\n", 108 | "

Hello DOM!

\n", 109 | "\n" 110 | ], 111 | "text/plain": [ 112 | "" 113 | ] 114 | }, 115 | "execution_count": 4, 116 | "metadata": {}, 117 | "output_type": "execute_result" 118 | } 119 | ], 120 | "source": [ 121 | "HTML('''\n", 122 | "\n", 128 | "

Hello DOM!

\n", 129 | "\n", 130 | "''')" 131 | ] 132 | }, 133 | { 134 | "cell_type": "markdown", 135 | "metadata": {}, 136 | "source": [ 137 | "---------" 138 | ] 139 | }, 140 | { 141 | "cell_type": "code", 142 | "execution_count": 5, 143 | "metadata": { 144 | "collapsed": false 145 | }, 146 | "outputs": [ 147 | { 148 | "data": { 149 | "text/html": [ 150 | "" 151 | ], 152 | "text/plain": [ 153 | "" 154 | ] 155 | }, 156 | "execution_count": 5, 157 | "metadata": {}, 158 | "output_type": "execute_result" 159 | } 160 | ], 161 | "source": [ 162 | "HTML('')" 163 | ] 164 | }, 165 | { 166 | "cell_type": "code", 167 | "execution_count": 6, 168 | "metadata": { 169 | "collapsed": false 170 | }, 171 | "outputs": [ 172 | { 173 | "data": { 174 | "text/html": [ 175 | "\n", 176 | "\n", 181 | "
\n", 182 | "\n" 194 | ], 195 | "text/plain": [ 196 | "" 197 | ] 198 | }, 199 | "execution_count": 6, 200 | "metadata": {}, 201 | "output_type": "execute_result" 202 | } 203 | ], 204 | "source": [ 205 | "HTML('''\n", 206 | "\n", 211 | "
\n", 212 | "\n", 224 | "''')" 225 | ] 226 | }, 227 | { 228 | "cell_type": "markdown", 229 | "metadata": {}, 230 | "source": [ 231 | "-----------" 232 | ] 233 | }, 234 | { 235 | "cell_type": "code", 236 | "execution_count": 7, 237 | "metadata": { 238 | "collapsed": true 239 | }, 240 | "outputs": [], 241 | "source": [ 242 | "size_data = [15,30,45]" 243 | ] 244 | }, 245 | { 246 | "cell_type": "code", 247 | "execution_count": 8, 248 | "metadata": { 249 | "collapsed": false 250 | }, 251 | "outputs": [ 252 | { 253 | "data": { 254 | "text/html": [ 255 | "\n", 256 | "\n", 257 | "
\n", 258 | "\n" 270 | ], 271 | "text/plain": [ 272 | "" 273 | ] 274 | }, 275 | "execution_count": 8, 276 | "metadata": {}, 277 | "output_type": "execute_result" 278 | } 279 | ], 280 | "source": [ 281 | "from string import Template\n", 282 | "html_template = Template('''\n", 283 | "\n", 284 | "
\n", 285 | "\n", 297 | "''')\n", 298 | "HTML(html_template.substitute({'size_data_python': str(size_data)}))" 299 | ] 300 | } 301 | ], 302 | "metadata": { 303 | "kernelspec": { 304 | "display_name": "Python 2", 305 | "language": "python", 306 | "name": "python2" 307 | }, 308 | "language_info": { 309 | "codemirror_mode": { 310 | "name": "ipython", 311 | "version": 2 312 | }, 313 | "file_extension": ".py", 314 | "mimetype": "text/x-python", 315 | "name": "python", 316 | "nbconvert_exporter": "python", 317 | "pygments_lexer": "ipython2", 318 | "version": "2.7.10" 319 | } 320 | }, 321 | "nbformat": 4, 322 | "nbformat_minor": 0 323 | } 324 | -------------------------------------------------------------------------------- /js/3d_viewer.js: -------------------------------------------------------------------------------- 1 | 2 | var el_width = 960, 3 | el_height = 500; 4 | 5 | 6 | var margin = {top: 20, right: 20, bottom: 20, left: 20}, 7 | width = el_width * 0.75 - margin.left - margin.right, 8 | height = el_width * 0.75 - margin.top - margin.bottom; 9 | 10 | d3.select("#maindiv${divnum}").selectAll("svg").remove(); 11 | var svg = d3.select("#maindiv${divnum}").append("svg") 12 | .attr("width", width + margin.left + margin.right) 13 | .attr("height", height + margin.top + margin.bottom); 14 | 15 | 16 | // viewport division lines and labels 17 | 18 | var divider_coords = [{"x1": width / 2.0, "x2": width / 2.0, "y1": 0, "y2": height}, 19 | {"x1": 0, "x2": width, "y1": height / 2.0, "y2": height / 2.0}]; 20 | 21 | var divider_label_config = [ {"text": "Top", "x": 10, "y": 10}, 22 | {"text": "Front", "x": 10, "y": (height/2.0) + 10}, 23 | {"text": "Right", "x": (width/2.0) + 10, "y": (height/2.0) + 10} ]; 24 | 25 | var divider_g = svg.append("g") 26 | .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 27 | 28 | divider_g.selectAll(".divider") 29 | .data(divider_coords) 30 | .enter().append("line") 31 | .attr("class", "divider") 32 | .attr("x1", function(d) { return d.x1; }) 33 | .attr("x2", function(d) { return d.x2; }) 34 | .attr("y1", function(d) { return d.y1; }) 35 | .attr("y2", function(d) { return d.y2; }) 36 | .style("stroke", "black") 37 | .style("stoke-width", 2); 38 | 39 | divider_g.selectAll(".dividerlabel") 40 | .data(divider_label_config) 41 | .enter().append("text") 42 | .attr("class", "dividerlabel") 43 | .attr("x", function(d) { return d.x; }) 44 | .attr("y", function(d) { return d.y; }) 45 | .attr("dy", ".35em") 46 | .text(function(d) { return d.text; }); 47 | 48 | 49 | // viewport setup 50 | 51 | var viewport_padding = 20; 52 | 53 | var viewport_config = [ 54 | {"h": [viewport_padding, (width / 2.0) - viewport_padding], 55 | "v": [(height / 2.0) - viewport_padding, viewport_padding], 56 | "hdim": "x", "vdim": "y", "zdim": "z"}, 57 | {"h": [viewport_padding, (width / 2.0) - viewport_padding], 58 | "v": [height - viewport_padding, (height / 2.0) + viewport_padding], 59 | "hdim": "x", "vdim": "z", "zdim": "y"}, 60 | {"h": [(width / 2.0) + viewport_padding, width - viewport_padding], 61 | "v": [height - viewport_padding, (height / 2.0) + viewport_padding], 62 | "hdim": "y", "vdim": "z", "zdim": "x"} 63 | ] 64 | 65 | var viewport = []; 66 | var h = []; 67 | var v = []; 68 | for (var i=0; i 0) { 106 | hdim_pts_extent = d3.extent(data[0].points, function(d) { return d[viewport_config[i]["hdim"]]; }); 107 | vdim_pts_extent = d3.extent(data[0].points, function(d) { return d[viewport_config[i]["vdim"]]; }); 108 | } 109 | 110 | var hdim_tri1_extent = [99999,-99999]; 111 | var vdim_tri1_extent = [99999,-99999]; 112 | var hdim_tri2_extent = [99999,-99999]; 113 | var vdim_tri2_extent = [99999,-99999]; 114 | var hdim_tri3_extent = [99999,-99999]; 115 | var vdim_tri3_extent = [99999,-99999]; 116 | if (data[0].triangles.length > 0) { 117 | hdim_tri1_extent = d3.extent(data[0].triangles, function(d) { return d[viewport_config[i]["hdim"] + "1"]; }); 118 | vdim_tri1_extent = d3.extent(data[0].triangles, function(d) { return d[viewport_config[i]["vdim"] + "1"]; }); 119 | hdim_tri2_extent = d3.extent(data[0].triangles, function(d) { return d[viewport_config[i]["hdim"] + "2"]; }); 120 | vdim_tri2_extent = d3.extent(data[0].triangles, function(d) { return d[viewport_config[i]["vdim"] + "2"]; }); 121 | hdim_tri3_extent = d3.extent(data[0].triangles, function(d) { return d[viewport_config[i]["hdim"] + "3"]; }); 122 | vdim_tri3_extent = d3.extent(data[0].triangles, function(d) { return d[viewport_config[i]["vdim"] + "3"]; }); 123 | } 124 | 125 | var hdim_extent = [ Math.min( hdim_pts_extent[0], hdim_tri1_extent[0], hdim_tri2_extent[0], hdim_tri3_extent[0] ) , 126 | Math.max( hdim_pts_extent[1], hdim_tri1_extent[1], hdim_tri2_extent[1], hdim_tri3_extent[1] )]; 127 | 128 | var vdim_extent = [ Math.min( vdim_pts_extent[0], vdim_tri1_extent[0], vdim_tri2_extent[0], vdim_tri3_extent[0] ) , 129 | Math.max( vdim_pts_extent[1], vdim_tri1_extent[1], vdim_tri2_extent[1], vdim_tri3_extent[1] )]; 130 | 131 | var hdim_size = hdim_extent[1] - hdim_extent[0]; 132 | var vdim_size = vdim_extent[1] - vdim_extent[0]; 133 | 134 | if (hdim_size > vdim_size) { 135 | h[i].domain(hdim_extent); 136 | v[i].domain([ vdim_extent[0] - (hdim_size - vdim_size) / 2 , vdim_extent[1] + (hdim_size - vdim_size) / 2 ]); 137 | } else { 138 | h[i].domain([ hdim_extent[0] - (vdim_size - hdim_size) / 2 , hdim_extent[1] + (vdim_size - hdim_size) / 2 ]); 139 | v[i].domain(vdim_extent); 140 | } 141 | 142 | 143 | 144 | // triangles 145 | 146 | var check_intercept = function(x0,y0,x1,y1,x2,y2,x3,y3) { 147 | 148 | // check if parallel, if so return false 149 | if ( Math.abs((y1-y0)/(x1-x0)) == Math.abs((y3-y2)/(x3-x2)) ) { 150 | // note: should probably be checked for overlap 151 | return [false, 0, 0]; 152 | } else { 153 | var c1 = ( (y2-y0)/y1 - (x2-x0)/x1 ) / ( x3/x1 - y3/y1 ); 154 | var c0 = (x2-x0)/x1 + c1 * (x3/x1); 155 | if ( (c0 > 0) && (c0 < 1) && (c1 > 0) && (c1 < 1) ) { 156 | return [true, c0, c1]; 157 | } 158 | } 159 | return [false, 0, 0]; 160 | } 161 | 162 | // z-dimension sorting 163 | data[0].triangles.sort(function(a,b) { 164 | 165 | // for convenience 166 | var x = viewport_config[i]["hdim"]; 167 | var y = viewport_config[i]["vdim"]; 168 | var z = viewport_config[i]["zdim"]; 169 | 170 | // check for overlap in x-y plane 171 | var lines = [[1,2],[2,3],[3,1]]; 172 | lines.forEach(function(line_a){ 173 | lines.forEach(function(line_b){ 174 | 175 | // does line_a intersect line_b ? 176 | var ci = check_intercept( a[x + line_a[0]], a[y + line_a[0]], 177 | a[x + line_a[1]], a[y + line_a[1]], 178 | b[x + line_b[0]], b[y + line_b[0]], 179 | b[x + line_b[1]], b[y + line_b[1]] ); 180 | if (ci[0]) { 181 | var c0 = ci[1]; 182 | var c1 = ci[2]; 183 | var z_int_a = a[z + line_a[0]] + c0 * a[z + line_a[1]]; 184 | var z_int_b = b[z + line_b[0]] + c1 * b[z + line_b[1]]; 185 | if (z_int_a > z_int_b) { 186 | return 1; 187 | } else if (z_int_a < z_int_b) { 188 | return -1; 189 | } else { 190 | return 0; 191 | } 192 | } 193 | }); 194 | }); 195 | 196 | // if no overlap, return 0 197 | return 0; 198 | }); 199 | 200 | viewport[i].selectAll(".triangle") 201 | .data(data[0].triangles) 202 | .enter().append("polygon") 203 | .attr("class", function(d,j) { return "triangle d" + j; }) 204 | .attr("points", function(d) { 205 | var s = ""; 206 | for (var j=1; j<4; j++) { 207 | s += h[i](d[viewport_config[i]["hdim"] + j]) + ","; 208 | s += v[i](d[viewport_config[i]["vdim"] + j]) + " "; 209 | } 210 | s = s.substring(0, s.length - 1); 211 | return s; 212 | }) 213 | .style("fill", "grey") 214 | .style("stroke", "black") 215 | .style("stroke-width", 0.5) 216 | .style("fill-opacity", 0.8) 217 | .on("click", function(event) { 218 | var class_name = d3.select(this).attr("class"); 219 | d3.selectAll(".triangle").style("fill", 'grey'); 220 | d3.selectAll("." + class_name.replace("triangle ","")).style("fill", 'red'); 221 | }); 222 | 223 | // points 224 | 225 | var points = viewport[i].selectAll(".dot") 226 | .data(data[0].points) 227 | .enter().append("circle") 228 | .attr("class", "dot") 229 | .attr("r", 1.5) 230 | .attr("cx", function(d) { return h[i](d[viewport_config[i]["hdim"]]); }) 231 | .attr("cy", function(d) { return v[i](d[viewport_config[i]["vdim"]]); }) 232 | .style("fill", "steelblue"); 233 | 234 | } 235 | 236 | //}); 237 | 238 | -------------------------------------------------------------------------------- /lib/sigmajs/plugins/sigma.layout.forceAtlas2.min.js: -------------------------------------------------------------------------------- 1 | (function(undefined){"use strict";function Supervisor(sigInst,options){var _this=this,workerFn=sigInst.getForceAtlas2Worker&&sigInst.getForceAtlas2Worker();if(options=options||{},_root.URL=_root.URL||_root.webkitURL,this.sigInst=sigInst,this.graph=this.sigInst.graph,this.ppn=10,this.ppe=3,this.config={},this.shouldUseWorker=options.worker===!1?!1:!0&&webWorkers,this.workerUrl=options.workerUrl,this.started=!1,this.running=!1,this.shouldUseWorker){if(this.workerUrl)this.worker=new Worker(this.workerUrl);else{var blob=this.makeBlob(workerFn);this.worker=new Worker(URL.createObjectURL(blob))}this.worker.postMessage=this.worker.webkitPostMessage||this.worker.postMessage}else eval(workerFn);var msgName=this.worker?"message":"newCoords";(this.worker||document).addEventListener(msgName,function(t){_this.nodesByteArray=new Float32Array(t.data.nodes),_this.running&&(_this.applyLayoutChanges(),_this.sendByteArrayToWorker(),_this.sigInst.refresh())}),this.graphToByteArrays()}if("undefined"==typeof sigma)throw"sigma is not declared";var _root=this,webWorkers="Worker"in _root;Supervisor.prototype.makeBlob=function(t){var e;try{e=new Blob([t],{type:"application/javascript"})}catch(r){_root.BlobBuilder=_root.BlobBuilder||_root.WebKitBlobBuilder||_root.MozBlobBuilder,e=new BlobBuilder,e.append(t),e=e.getBlob()}return e},Supervisor.prototype.graphToByteArrays=function(){var t,e,r,o=this.graph.nodes(),i=this.graph.edges(),n=o.length*this.ppn,s=i.length*this.ppe,a={};for(this.nodesByteArray=new Float32Array(n),this.edgesByteArray=new Float32Array(s),t=e=0,r=o.length;r>t;t++)a[o[t].id]=e,this.nodesByteArray[e]=o[t].x,this.nodesByteArray[e+1]=o[t].y,this.nodesByteArray[e+2]=0,this.nodesByteArray[e+3]=0,this.nodesByteArray[e+4]=0,this.nodesByteArray[e+5]=0,this.nodesByteArray[e+6]=1+this.graph.degree(o[t].id),this.nodesByteArray[e+7]=1,this.nodesByteArray[e+8]=o[t].size,this.nodesByteArray[e+9]=0,e+=this.ppn;for(t=e=0,r=i.length;r>t;t++)this.edgesByteArray[e]=a[i[t].source],this.edgesByteArray[e+1]=a[i[t].target],this.edgesByteArray[e+2]=i[t].weight||0,e+=this.ppe},Supervisor.prototype.applyLayoutChanges=function(){for(var t=this.graph.nodes(),e=0,r=0,o=this.nodesByteArray.length;o>r;r+=this.ppn)t[e].x=this.nodesByteArray[r],t[e].y=this.nodesByteArray[r+1],e++},Supervisor.prototype.sendByteArrayToWorker=function(t){var e={action:t||"loop",nodes:this.nodesByteArray.buffer},r=[this.nodesByteArray.buffer];"start"===t&&(e.config=this.config||{},e.edges=this.edgesByteArray.buffer,r.push(this.edgesByteArray.buffer)),this.shouldUseWorker?this.worker.postMessage(e,r):_root.postMessage(e,"*")},Supervisor.prototype.start=function(){this.running||(this.running=!0,this.started?this.sendByteArrayToWorker():(this.sendByteArrayToWorker("start"),this.started=!0))},Supervisor.prototype.stop=function(){this.running&&(this.running=!1)},Supervisor.prototype.killWorker=function(){this.worker&&this.worker.terminate()},Supervisor.prototype.configure=function(t){if(this.config=t,this.started){var e={action:"config",config:this.config};this.shouldUseWorker?this.worker.postMessage(e):_root.postMessage(e,"*")}},sigma.prototype.startForceAtlas2=function(t){return this.supervisor||(this.supervisor=new Supervisor(this,t)),t&&this.supervisor.configure(t),this.supervisor.start(),this},sigma.prototype.stopForceAtlas2=function(){return this.supervisor?(this.supervisor.stop(),this):this},sigma.prototype.killForceAtlas2=function(){return this.supervisor?(this.supervisor.stop(),this.supervisor.killWorker(),this.supervisor=null,this):this},sigma.prototype.configForceAtlas2=function(t){return this.supervisor||(this.supervisor=new Supervisor(this,t)),this.supervisor.configure(t),this},sigma.prototype.isForceAtlas2Running=function(){return this.supervisor&&this.supervisor.running}}).call(this),function(undefined){"use strict";function no_crush(t){var e,r,o,i=["x","y","dx","dy","old_dx","old_dy","mass","convergence","size","fixed"],n=["source","target","weight"];for(r=0,o=i.length;o>r;r++)e=new RegExp("np\\(([^,]*), '"+i[r]+"'\\)","g"),t=t.replace(e,0===r?"$1":"$1 + "+r);for(r=0,o=n.length;o>r;r++)e=new RegExp("ep\\(([^,]*), '"+n[r]+"'\\)","g"),t=t.replace(e,0===r?"$1":"$1 + "+r);return t}function getWorkerFn(){var t=crush?crush(Worker.toString()):Worker.toString();return";("+t+").call(this);"}var _root=this,inWebWorker=!("document"in _root),Worker=function(){function t(){var t,e,r={},o=arguments.length;for(t=o-1;t>=0;t--)for(e in arguments[t])r[e]=arguments[t][e];return r}function e(t,e,o){o=o||{};s.nodeMatrix=t,s.edgeMatrix=e,s.nodesLength=s.nodeMatrix.length,s.edgesLength=s.edgeMatrix.length,r(o)}function r(e){e.barnesHutOptimize=!1,s.settings=t(e,s.settings)}function o(){var t,e,r,o,i,n,a,d,h,g,M,p,u,x,l;for(r=0;re;e++)t+=v[e],A[e]=t}if(s.settings.barnesHutOptimize);else for(o=0;o0?(l=s.settings.scalingRatio*s.nodeMatrix[o+6]*s.nodeMatrix[i+6]/x/x,s.nodeMatrix[o+2]+=M*l,s.nodeMatrix[o+3]+=p*l,s.nodeMatrix[i+2]+=M*l,s.nodeMatrix[i+3]+=p*l):0>x&&(l=100*s.settings.scalingRatio*s.nodeMatrix[o+6]*s.nodeMatrix[i+6],s.nodeMatrix[o+2]+=M*l,s.nodeMatrix[o+3]+=p*l,s.nodeMatrix[i+2]-=M*l,s.nodeMatrix[i+3]-=p*l)):(x=Math.sqrt(M*M+p*p),x>0&&(l=s.settings.scalingRatio*s.nodeMatrix[o+6]*s.nodeMatrix[i+6]/x/x,s.nodeMatrix[o+2]+=M*l,s.nodeMatrix[o+3]+=p*l,s.nodeMatrix[i+2]-=M*l,s.nodeMatrix[i+3]-=p*l));for(d=s.settings.gravity/s.settings.scalingRatio,g=s.settings.scalingRatio,r=0;r0&&(l=g*s.nodeMatrix[r+6]*d):x>0&&(l=g*s.nodeMatrix[r+6]*d/x),s.nodeMatrix[r+2]-=M*l,s.nodeMatrix[r+3]-=p*l;for(g=1*(s.settings.outboundAttractionDistribution?h:1),n=0;n0&&(l=-g*u*Math.log(1+x)/x/s.nodeMatrix[o+6]):x>0&&(l=-g*u*Math.log(1+x)/x):s.settings.outboundAttractionDistribution?x>0&&(l=-g*u/s.nodeMatrix[o+6]):x>0&&(l=-g*u)):(x=Math.sqrt(Math.pow(M,2)+Math.pow(p,2)),s.settings.linLogMode?s.settings.outboundAttractionDistribution?x>0&&(l=-g*u*Math.log(1+x)/x/s.nodeMatrix[o+6]):x>0&&(l=-g*u*Math.log(1+x)/x):s.settings.outboundAttractionDistribution?(x=1,l=-g*u/s.nodeMatrix[o+6]):(x=1,l=-g*u)),x>0&&(s.nodeMatrix[o+2]+=M*l,s.nodeMatrix[o+3]+=p*l,s.nodeMatrix[i+2]-=M*l,s.nodeMatrix[i+3]-=p*l);var L,F,_,U;if(s.settings.adjustSizes)for(r=0;rs.maxForce&&(s.nodeMatrix[r+2]=s.nodeMatrix[r+2]*s.maxForce/L,s.nodeMatrix[r+3]=s.nodeMatrix[r+3]*s.maxForce/L),F=s.nodeMatrix[r+6]*Math.sqrt((s.nodeMatrix[r+4]-s.nodeMatrix[r+2])*(s.nodeMatrix[r+4]-s.nodeMatrix[r+2])+(s.nodeMatrix[r+5]-s.nodeMatrix[r+3])*(s.nodeMatrix[r+5]-s.nodeMatrix[r+3])),_=Math.sqrt((s.nodeMatrix[r+4]+s.nodeMatrix[r+2])*(s.nodeMatrix[r+4]+s.nodeMatrix[r+2])+(s.nodeMatrix[r+5]+s.nodeMatrix[r+3])*(s.nodeMatrix[r+5]+s.nodeMatrix[r+3]))/2,U=.1*Math.log(1+_)/(1+Math.sqrt(F)),s.nodeMatrix[r]=s.nodeMatrix[r]+s.nodeMatrix[r+2]*(U/s.settings.slowDown),s.nodeMatrix[r+1]=s.nodeMatrix[r+1]+s.nodeMatrix[r+3]*(U/s.settings.slowDown));else for(r=0;r" 49 | ], 50 | "text/plain": [ 51 | "" 52 | ] 53 | }, 54 | "execution_count": 2, 55 | "metadata": {}, 56 | "output_type": "execute_result" 57 | } 58 | ], 59 | "source": [ 60 | "HTML('')" 61 | ] 62 | }, 63 | { 64 | "cell_type": "markdown", 65 | "metadata": {}, 66 | "source": [ 67 | "#### Graph Config" 68 | ] 69 | }, 70 | { 71 | "cell_type": "code", 72 | "execution_count": 3, 73 | "metadata": { 74 | "collapsed": true 75 | }, 76 | "outputs": [], 77 | "source": [ 78 | "html_template = Template('''\n", 79 | "\n", 80 | "
\n", 81 | "\n", 82 | "''')" 83 | ] 84 | }, 85 | { 86 | "cell_type": "code", 87 | "execution_count": 4, 88 | "metadata": { 89 | "collapsed": true 90 | }, 91 | "outputs": [], 92 | "source": [ 93 | "css_text = '''\n", 94 | "\n", 95 | ".bar {\n", 96 | " fill: steelblue;\n", 97 | "}\n", 98 | "\n", 99 | ".bar:hover {\n", 100 | " fill: brown;\n", 101 | "}\n", 102 | "\n", 103 | ".axis {\n", 104 | " font: 10px sans-serif;\n", 105 | "}\n", 106 | "\n", 107 | ".axis path,\n", 108 | ".axis line {\n", 109 | " fill: none;\n", 110 | " stroke: #000;\n", 111 | " shape-rendering: crispEdges;\n", 112 | "}\n", 113 | "\n", 114 | ".x.axis path {\n", 115 | " display: none;\n", 116 | "}\n", 117 | "\n", 118 | "'''" 119 | ] 120 | }, 121 | { 122 | "cell_type": "code", 123 | "execution_count": 5, 124 | "metadata": { 125 | "collapsed": true 126 | }, 127 | "outputs": [], 128 | "source": [ 129 | "js_text_template = Template('''\n", 130 | "\n", 131 | "var margin = {top: 20, right: 20, bottom: 30, left: 40},\n", 132 | " width = 500 - margin.left - margin.right,\n", 133 | " height = 300 - margin.top - margin.bottom;\n", 134 | "\n", 135 | "var x = d3.scale.ordinal()\n", 136 | " .rangeRoundBands([0, width], .1);\n", 137 | "\n", 138 | "var y = d3.scale.linear()\n", 139 | " .range([height, 0]);\n", 140 | "\n", 141 | "var xAxis = d3.svg.axis()\n", 142 | " .scale(x)\n", 143 | " .orient(\"bottom\");\n", 144 | "\n", 145 | "var yAxis = d3.svg.axis()\n", 146 | " .scale(y)\n", 147 | " .orient(\"left\");\n", 148 | "\n", 149 | "var svg = d3.select(\"#graph-div\").append(\"svg\")\n", 150 | " .attr(\"width\", width + margin.left + margin.right)\n", 151 | " .attr(\"height\", height + margin.top + margin.bottom)\n", 152 | " .append(\"g\")\n", 153 | " .attr(\"transform\", \"translate(\" + margin.left + \",\" + margin.top + \")\");\n", 154 | "\n", 155 | "var data = $data ;\n", 156 | "\n", 157 | " x.domain(data.map(function(d) { return d.letter; }));\n", 158 | " y.domain([0, d3.max(data, function(d) { return d.y; })]);\n", 159 | "\n", 160 | " svg.append(\"g\")\n", 161 | " .attr(\"class\", \"x axis\")\n", 162 | " .attr(\"transform\", \"translate(0,\" + height + \")\")\n", 163 | " .call(xAxis);\n", 164 | "\n", 165 | " svg.append(\"g\")\n", 166 | " .attr(\"class\", \"y axis\")\n", 167 | " .call(yAxis);\n", 168 | "\n", 169 | " svg.selectAll(\".bar\")\n", 170 | " .data(data)\n", 171 | " .enter().append(\"rect\")\n", 172 | " .attr(\"class\", \"bar\")\n", 173 | " .attr(\"x\", function(d) { return x(d.letter); })\n", 174 | " .attr(\"width\", x.rangeBand())\n", 175 | " .attr(\"y\", function(d) { return y(d.y); })\n", 176 | " .attr(\"height\", function(d) { return height - y(d.y); });\n", 177 | "\n", 178 | "''')" 179 | ] 180 | }, 181 | { 182 | "cell_type": "code", 183 | "execution_count": 6, 184 | "metadata": { 185 | "collapsed": true 186 | }, 187 | "outputs": [], 188 | "source": [ 189 | "js_text_template_2 = Template('''\n", 190 | "\n", 191 | "var bars = svg.selectAll(\".bar\").data($data);\n", 192 | " \n", 193 | "bars\n", 194 | " .transition()\n", 195 | " .attr(\"y\", function(d) { return y(d.y); })\n", 196 | " .attr(\"height\", function(d) { return height - y(d.y); });\n", 197 | "\n", 198 | "''')" 199 | ] 200 | }, 201 | { 202 | "cell_type": "markdown", 203 | "metadata": {}, 204 | "source": [ 205 | "#### Initial Data, Graph and Update" 206 | ] 207 | }, 208 | { 209 | "cell_type": "code", 210 | "execution_count": 7, 211 | "metadata": { 212 | "collapsed": false 213 | }, 214 | "outputs": [ 215 | { 216 | "data": { 217 | "text/html": [ 218 | "
\n", 219 | "\n", 220 | " \n", 221 | " \n", 222 | " \n", 223 | " \n", 224 | " \n", 225 | " \n", 226 | " \n", 227 | " \n", 228 | " \n", 229 | " \n", 230 | " \n", 231 | " \n", 232 | " \n", 233 | " \n", 234 | " \n", 235 | " \n", 236 | " \n", 237 | " \n", 238 | " \n", 239 | " \n", 240 | " \n", 241 | " \n", 242 | " \n", 243 | " \n", 244 | " \n", 245 | " \n", 246 | " \n", 247 | " \n", 248 | " \n", 249 | "
lettery
0A1
1B1
2C1
3D1
\n", 250 | "
" 251 | ], 252 | "text/plain": [ 253 | " letter y\n", 254 | "0 A 1\n", 255 | "1 B 1\n", 256 | "2 C 1\n", 257 | "3 D 1" 258 | ] 259 | }, 260 | "execution_count": 7, 261 | "metadata": {}, 262 | "output_type": "execute_result" 263 | } 264 | ], 265 | "source": [ 266 | "data = pd.DataFrame({'letter': ['A','B','C','D'], 'y': [1,1,1,1]})\n", 267 | "data.head()" 268 | ] 269 | }, 270 | { 271 | "cell_type": "code", 272 | "execution_count": 8, 273 | "metadata": { 274 | "collapsed": false 275 | }, 276 | "outputs": [ 277 | { 278 | "data": { 279 | "text/html": [ 280 | "\n", 281 | "\n", 307 | "
\n", 308 | "\n" 358 | ], 359 | "text/plain": [ 360 | "" 361 | ] 362 | }, 363 | "execution_count": 8, 364 | "metadata": {}, 365 | "output_type": "execute_result" 366 | } 367 | ], 368 | "source": [ 369 | "js_text = js_text_template.substitute({'data': json.dumps(data.to_dict(orient='records'))})\n", 370 | "HTML(html_template.substitute({'css_text': css_text, 'js_text': js_text}))" 371 | ] 372 | }, 373 | { 374 | "cell_type": "code", 375 | "execution_count": 9, 376 | "metadata": { 377 | "collapsed": false 378 | }, 379 | "outputs": [ 380 | { 381 | "data": { 382 | "text/html": [ 383 | "" 393 | ], 394 | "text/plain": [ 395 | "" 396 | ] 397 | }, 398 | "execution_count": 9, 399 | "metadata": {}, 400 | "output_type": "execute_result" 401 | } 402 | ], 403 | "source": [ 404 | "data['y'] = [random.uniform(0,1) for d in data['y']]\n", 405 | "js_text = js_text_template_2.substitute({'data': json.dumps(data.to_dict(orient='records'))})\n", 406 | "HTML('')" 407 | ] 408 | }, 409 | { 410 | "cell_type": "markdown", 411 | "metadata": {}, 412 | "source": [ 413 | "Re-run this last cell (ctrl-Enter lets you run it and stay put) and watch it transition the graph above it. " 414 | ] 415 | } 416 | ], 417 | "metadata": { 418 | "kernelspec": { 419 | "display_name": "Python 2", 420 | "language": "python", 421 | "name": "python2" 422 | }, 423 | "language_info": { 424 | "codemirror_mode": { 425 | "name": "ipython", 426 | "version": 2 427 | }, 428 | "file_extension": ".py", 429 | "mimetype": "text/x-python", 430 | "name": "python", 431 | "nbconvert_exporter": "python", 432 | "pygments_lexer": "ipython2", 433 | "version": "2.7.10" 434 | } 435 | }, 436 | "nbformat": 4, 437 | "nbformat_minor": 0 438 | } 439 | -------------------------------------------------------------------------------- /js/temperature_histories.js: -------------------------------------------------------------------------------- 1 | 2 | // context 3 | 4 | var svgID = "graph-svg"; 5 | var width = $("#graph-svg").width(); //750; 6 | var height = 500; 7 | 8 | 9 | // graph code 10 | 11 | 12 | 13 | // configuration variables 14 | 15 | currentSite = "718160"; 16 | 17 | currentYM = "1990-1"; 18 | 19 | currentType = "ave"; 20 | currentTypeIA1 = "min"; 21 | currentTypeIA2 = "max"; 22 | 23 | activeTypeText = { "ave": "AVERAGE TEMPERATURE", 24 | "min": "MINIMUM TEMPERATURE", 25 | "max": "MAXIMUM TEMPERATURE" } 26 | 27 | inactiveTypeText = { "ave": "AVE", 28 | "min": "MIN", 29 | "max": "MAX" } 30 | 31 | var tempTicks = [0,10,20,30,40,50,60,70,80,90,100]; 32 | var colors = ["#9e0142","#d53e4f","#f46d43","#fdae61","#fee08b","#ffffbf","#e6f598","#abdda4","#66c2a5","#3288bd","#5e4fa2"]; 33 | 34 | monthStr = ["JAN","FEB","MAR","APR","MAY","JUN","JUL","AUG","SEP","OCT","NOV","DEC"]; 35 | 36 | var mapWidth = 600; 37 | var mapHeight = 320; 38 | 39 | var leftMargin = Math.max(0,(width-600) / 2); //75; 40 | 41 | var mapScale = 90; 42 | var mapCenter = [0,-30]; 43 | var mapTranslate = [280,250]; 44 | 45 | var animateTextX = leftMargin + 290; 46 | var animateTextY = 346; 47 | var startTriangleX = (leftMargin + 300); 48 | var startTriangleY = 338; 49 | 50 | var xAxisRange = [leftMargin + 20, leftMargin + 550]; 51 | var xAxisY = 358; 52 | var yAxisRange = [475, 380]; 53 | 54 | var handleX = leftMargin + 200; 55 | var handleY1 = 358; 56 | var handleY2 = 495; 57 | var handleTextX = leftMargin + 210; 58 | var handleTextY = 375; 59 | var siteNameTextX = leftMargin + 560; 60 | var siteNameTextY = 325; 61 | var siteNameTextAnchor = "end"; 62 | var tempTypeText1X = leftMargin + 10; 63 | var tempTypeText2X = leftMargin + 10; 64 | var tempTypeText3X = leftMargin + 10; 65 | var tempTypeText1Y = 325; 66 | var tempTypeText2Y = 310; 67 | var tempTypeText3Y = 295; 68 | var colorLegendX = leftMargin + 565; 69 | 70 | if (width < 600) { 71 | mapWidth = Math.max(500,width); 72 | var modi = Math.min(1,(600-width)/(600-500)); 73 | mapHeight = 320 - 160*modi; 74 | mapScale = 90-(45*modi); 75 | mapTranslate = [280-(140*modi),250-(125*modi)]; 76 | xAxisRange = [15, width - 55]; 77 | colorLegendX = width - 45; 78 | tempTypeText1X = 5; 79 | tempTypeText2X = 5; 80 | tempTypeText3X = 35; 81 | tempTypeText1Y = 310; 82 | tempTypeText2Y = 295; 83 | tempTypeText3Y = 295; 84 | startTriangleX = (width - 37) / 2; 85 | siteNameTextX = 5; 86 | siteNameTextAnchor = "start"; 87 | 88 | handleY1 = mapHeight + 30 + 38; 89 | handleY2 = mapHeight + 30 + 175; 90 | handleTextY = mapHeight + 30 + 55; 91 | siteNameTextY = mapHeight + 30 + 5; 92 | tempTypeText1Y = mapHeight + 30 - 10; 93 | tempTypeText2Y = mapHeight + 30 - 25; 94 | tempTypeText3Y = mapHeight + 30 - 25; 95 | xAxisY = mapHeight + 30 + 38; 96 | yAxisRange = [mapHeight + 30+ 155, mapHeight + 30 + 60]; 97 | startTriangleY = mapHeight + 30 + 18; 98 | $("#graph-svg").height(mapHeight + 30 + 180); 99 | 100 | } 101 | 102 | 103 | // segments / groupings of svg 104 | 105 | var svg = d3.select("#"+svgID); 106 | 107 | svg.append("g").append("svg") 108 | .attr("id","map") 109 | .attr("width",mapWidth) 110 | .attr("height",mapHeight) 111 | .attr("transform", "translate(" + leftMargin + ",0)"); 112 | 113 | d3.select("#map").append("g") 114 | .attr("id","mapCountries"); 115 | 116 | d3.select("#map").append("g") 117 | .attr("id","mapSites"); 118 | 119 | svg.append("g") 120 | .attr("id","linegraphs"); 121 | 122 | 123 | // slider and axes configuration 124 | 125 | var x = d3.scale.linear() 126 | .domain([1945, 2010]) 127 | .range(xAxisRange) 128 | .clamp(true); 129 | 130 | var y = d3.scale.linear() 131 | .domain([0, 100]) 132 | .range(yAxisRange); 133 | 134 | var brush = d3.svg.brush() 135 | .x(x) 136 | .extent([0, 0]); 137 | 138 | 139 | // map variables 140 | 141 | var projection = d3.geo.mercator() 142 | .center(mapCenter) 143 | .scale(mapScale) 144 | .rotate([0,0]) 145 | .translate(mapTranslate); 146 | 147 | var path = d3.geo.path() 148 | .projection(projection) 149 | .pointRadius(1); 150 | 151 | var color = d3.scale.linear() 152 | .domain(tempTicks.reverse()) 153 | .range(colors) 154 | .interpolate(d3.interpolateHcl); 155 | 156 | 157 | 158 | // read files, draw map, initiate slider, slider function 159 | 160 | mapdata = $worldmapdata ; 161 | sitesdata = $sitesdata ; 162 | 163 | 164 | // draw axes, slider, etc 165 | 166 | svg.append("g") 167 | .attr("class", "x axis") 168 | .attr("transform", "translate(0," + xAxisY + ")") 169 | .call(d3.svg.axis() 170 | .scale(x) 171 | .orient("top") 172 | .tickFormat(function(d) { if (d == 1945 || d == 2010) {return d}; }) 173 | .tickSize(0) 174 | .tickPadding(12)) 175 | .select(".domain") 176 | .select(function() { return this.parentNode.appendChild(this.cloneNode(true)); }); 177 | 178 | var slider = svg.append("g") 179 | .attr("class", "slider") 180 | .call(brush); 181 | 182 | slider.selectAll(".extent,.resize") 183 | .remove(); 184 | 185 | var handle = slider.append("line") 186 | .attr("class", "handle") 187 | .attr("x1", handleX).attr("y1", handleY1) 188 | .attr("x2", handleX).attr("y2", handleY2); 189 | 190 | var handleText = slider.append("text") 191 | .attr("class", "handleText") 192 | .attr("x", handleTextX).attr("y", handleTextY) 193 | .attr("text-anchor", "start") 194 | .text(""); 195 | 196 | var siteNameText = svg.append("text") 197 | .attr("class", "siteNameText") 198 | .attr("id", "siteText" ) 199 | .attr("x", siteNameTextX).attr("y", siteNameTextY) 200 | .attr("text-anchor", siteNameTextAnchor) 201 | .text(""); 202 | 203 | var tempTypeText1 = svg.append("text") 204 | .attr("class", "tempTypeTextActive") 205 | .attr("id", "tempTypeText1" ) 206 | .attr("x", tempTypeText1X).attr("y", tempTypeText1Y) 207 | .attr("text-anchor", "start") 208 | .text("AVERAGE TEMPERATURE"); 209 | 210 | var tempTypeText2 = svg.append("text") 211 | .attr("class", "tempTypeTextInactive") 212 | .attr("id", "tempTypeText2" ) 213 | .attr("x", tempTypeText2X).attr("y", tempTypeText2Y) 214 | .attr("text-anchor", "start") 215 | .text("MIN") 216 | .on("click", function(e){ 217 | var save = currentType; 218 | currentType = currentTypeIA1; 219 | currentTypeIA1 = save; 220 | d3.select("#tempTypeText2").text(inactiveTypeText[currentTypeIA1]); 221 | d3.select("#tempTypeText1").text(activeTypeText[currentType]); 222 | updateLinegraph(currentSite,currentType); 223 | updateMapColors(currentYM); 224 | }); 225 | 226 | var tempTypeText3 = svg.append("text") 227 | .attr("class", "tempTypeTextInactive") 228 | .attr("id", "tempTypeText3" ) 229 | .attr("x", tempTypeText3X).attr("y", tempTypeText3Y) 230 | .attr("text-anchor", "start") 231 | .text("MAX") 232 | .on("click", function(e){ 233 | var save = currentType; 234 | currentType = currentTypeIA2; 235 | currentTypeIA2 = save; 236 | d3.select("#tempTypeText3").text(inactiveTypeText[currentTypeIA2]); 237 | d3.select("#tempTypeText1").text(activeTypeText[currentType]); 238 | updateLinegraph(currentSite,currentType); 239 | updateMapColors(currentYM); 240 | }); 241 | 242 | svg.append("g") 243 | .attr("class", "y axis") 244 | .attr("transform", "translate(" + colorLegendX + ",0)") 245 | .call(d3.svg.axis() 246 | .scale(y) 247 | .orient("right") 248 | .tickFormat(function(d) { 249 | if (d == 0 || d == 20 || d == 40 || d == 60 || d == 80) {return d} 250 | else if (d == 100) {return "" + d + "F"}; 251 | }) 252 | .tickSize(0) 253 | .tickPadding(12)); 254 | 255 | var colorList = []; 256 | for (var i = 0; i <= 100; i+=1) { 257 | colorList.push(i); 258 | } 259 | 260 | d3.select("#linegraphs").selectAll(".colorLegend") 261 | .data(colorList) 262 | .enter().append("circle") 263 | .attr("class", "colorLegend") 264 | .attr("r",2) 265 | .attr("fill", function(d) { return color(d); }) 266 | .attr("cy", function(d){ return y(d); }) 267 | .attr("cx", function(d){ return colorLegendX; }); 268 | 269 | 270 | // draw map and sites 271 | 272 | d3.select("#mapCountries").selectAll(".pathCountry") 273 | .data(mapdata.features) 274 | .enter().append("path") 275 | .attr("class", "pathCountry") 276 | .attr("d", path); 277 | 278 | d3.select("#mapSites").selectAll(".pathSite") 279 | .data(sitesdata) 280 | .enter() 281 | .append("circle") 282 | .attr("class","pathSite") 283 | .attr("r",3) 284 | .attr("stroke-opacity",1e-6) 285 | .attr("USAF", function(d) {return d.ID;}) 286 | .attr("station_name", function(d) {return d.station_name;}) 287 | .attr("country_name", function(d) {return d.country_name;}) 288 | .attr("transform", function(d) {return "translate(" + projection([d.lon,d.lat]) + ")";}) 289 | .on("click", function(e){ 290 | 291 | // determine which point is selected 292 | pt = d3.select(this)[0][0].attributes; 293 | USAF = pt.USAF.value; 294 | station_name = pt.station_name.value; 295 | country_name = pt.country_name.value; 296 | 297 | // write to text line 298 | d3.select("#siteText").text(station_name + ", " + country_name); 299 | 300 | // demarcate point 301 | d3.selectAll(".pathSite").style("stroke-opacity",1e-6); 302 | d3.select(this).style("stroke-opacity",1); 303 | 304 | // update graph 305 | updateLinegraph(USAF,currentType); 306 | 307 | // update currentSite variable 308 | currentSite = USAF; 309 | 310 | }); 311 | 312 | // function: update linegraph 313 | 314 | function updateLinegraph(USAF,tempType) { 315 | 316 | var v = sitesdata.filter(function(k){ return k.ID == USAF; }); 317 | 318 | var linearray = $.map(v[0]["temps"], function(value, index) { 319 | value["year"] = Number(index.split("-")[0]) + (Number(index.split("-")[1]) - 1) / 12; 320 | value["dateText"] = monthStr[Number(index.split("-")[1]) - 1] + " " + index.split("-")[0] ; 321 | return [value]; 322 | }); 323 | 324 | var c = d3.select("#linegraphs").selectAll(".linegraph") 325 | .data(linearray); 326 | c.enter().append("circle"); 327 | c.exit().remove(); 328 | c 329 | .attr("class", "linegraph") 330 | .attr("r",2) 331 | .attr("fill", function(d) { 332 | var v = d[tempType] ; 333 | return color(v); 334 | }) 335 | .attr("cy", function(d){ return y(d[tempType]); }) 336 | .attr("cx", function(d){ return x(d.year); }) 337 | .attr("title", function(d){ 338 | return d.dateText + " : " + (d[tempType]).toFixed(2) + "F"; 339 | }); 340 | 341 | } 342 | 343 | // initialize linegraph 344 | var s = d3.select("#mapSites").selectAll(".pathSite"); 345 | var pt = s.filter(function(k){ return k.ID == currentSite; }); 346 | station_name = pt[0][0].attributes.station_name.value; 347 | country_name = pt[0][0].attributes.country_name.value; 348 | d3.select("#siteText").text(station_name + ", " + country_name); 349 | pt.style("stroke-opacity",1); 350 | updateLinegraph(currentSite,currentType); 351 | 352 | 353 | // function: on slider movement 354 | 355 | function brushed() { 356 | 357 | // get year and monthNum from slider movement 358 | var value = brush.extent()[0]; 359 | if (d3.event.sourceEvent) { // not a programmatic event 360 | value = x.invert(d3.mouse(this)[0]); 361 | brush.extent([value, value]); 362 | } 363 | var year = Math.floor(value); 364 | var monthNum = Math.floor((value - year)*12); 365 | 366 | // update handle location and handle text 367 | handle 368 | .attr("x1", x(value)) 369 | .attr("x2", x(value)); 370 | handleText 371 | .attr("x", x(value) + 5) 372 | .text(monthStr[monthNum] + " " + year); 373 | 374 | // update sliderlocation variable for animation 375 | sliderlocation = value; 376 | currentYM = "" + year + "-" + (monthNum+1); 377 | 378 | // update fill colors of site points 379 | updateMapColors(currentYM); 380 | 381 | }; 382 | 383 | function updateMapColors(ym) { 384 | 385 | d3.select("#mapSites").selectAll(".pathSite") 386 | .attr("fill", function(d) { 387 | if (ym in d.temps) { 388 | var v = d.temps[ym][currentType] ; 389 | return color(v); 390 | } else { 391 | return "#999"; 392 | } 393 | }); 394 | 395 | }; 396 | 397 | // initialize slider 398 | brush.on("brush", brushed); 399 | sliderlocation = 1990.0; 400 | slider 401 | .call(brush.extent([sliderlocation, sliderlocation])) 402 | .call(brush.event); 403 | 404 | // animation button 405 | var line = d3.svg.line() 406 | .x(function(d) { return d.x; }) 407 | .y(function(d) { return d.y; }) 408 | .interpolate("linear"); 409 | startTriangle = [ { "x": 0, "y": 0}, { "x": 0, "y": 10}, { "x": 8, "y": 5} ]; 410 | stopRectangle = [ { "x": 0, "y": 0}, { "x": 0, "y": 10}, { "x": 10, "y": 10}, { "x": 10, "y": 0} ]; 411 | animationOn = false; 412 | animationObj = {}; 413 | function animator() { 414 | slider 415 | .call(brush.extent([sliderlocation, sliderlocation])) 416 | .call(brush.event); 417 | if (sliderlocation >= 2010.0) { 418 | animationOn = false; 419 | clearInterval(animationObj); 420 | var p = d3.select("#linegraphs").selectAll(".pathStart").data([startTriangle]); 421 | p.enter().append("path"); 422 | p.exit().remove(); 423 | p.attr("d", function(d){ return line(d) + "Z";}); 424 | } else { 425 | sliderlocation += 1.0/12.0; 426 | } 427 | }; 428 | d3.select("#linegraphs").append("path") 429 | .data([startTriangle]) 430 | .attr("class", "pathStart") 431 | .attr("d", function(d){ return line(d);}) 432 | .attr("transform", "translate(" + startTriangleX + "," + startTriangleY + ")") 433 | .on("click", function(e) { 434 | if (animationOn) { 435 | animationOn = false; 436 | clearInterval(animationObj); 437 | d3.select(this).data([startTriangle]) 438 | .attr("d", function(d){ return line(d);}); 439 | } else { 440 | animationOn = true; 441 | d3.select(this).data([stopRectangle]) 442 | .attr("d", function(d){ return line(d);}); 443 | animationObj = setInterval( function () {animator()}, 1 ); 444 | } 445 | }); 446 | 447 | if (width > 600) { 448 | var animateText = svg.append("text") 449 | .attr("class", "siteNameText") 450 | .attr("x", animateTextX).attr("y", animateTextY) 451 | .attr("text-anchor", "end") 452 | .text("animate"); 453 | } 454 | 455 | 456 | 457 | 458 | -------------------------------------------------------------------------------- /sigma_js_graph.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Network Diagram with Sigma.js" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "This example uses [sigma.js](http://sigmajs.org/) to visualize a network produced in python." 15 | ] 16 | }, 17 | { 18 | "cell_type": "markdown", 19 | "metadata": {}, 20 | "source": [ 21 | "#### Notebook Config" 22 | ] 23 | }, 24 | { 25 | "cell_type": "code", 26 | "execution_count": 1, 27 | "metadata": { 28 | "collapsed": true 29 | }, 30 | "outputs": [], 31 | "source": [ 32 | "from IPython.core.display import display, HTML\n", 33 | "from string import Template\n", 34 | "import pandas as pd\n", 35 | "import json, random" 36 | ] 37 | }, 38 | { 39 | "cell_type": "code", 40 | "execution_count": 2, 41 | "metadata": { 42 | "collapsed": false 43 | }, 44 | "outputs": [ 45 | { 46 | "data": { 47 | "text/html": [ 48 | "\n", 49 | "\n", 50 | "\n" 51 | ], 52 | "text/plain": [ 53 | "" 54 | ] 55 | }, 56 | "execution_count": 2, 57 | "metadata": {}, 58 | "output_type": "execute_result" 59 | } 60 | ], 61 | "source": [ 62 | "HTML('''\n", 63 | "\n", 64 | "\n", 65 | "''')" 66 | ] 67 | }, 68 | { 69 | "cell_type": "markdown", 70 | "metadata": {}, 71 | "source": [ 72 | "#### Network Construction" 73 | ] 74 | }, 75 | { 76 | "cell_type": "code", 77 | "execution_count": 3, 78 | "metadata": { 79 | "collapsed": true 80 | }, 81 | "outputs": [], 82 | "source": [ 83 | "random.seed(42)\n", 84 | "\n", 85 | "n_nodes = 40\n", 86 | "n_edges = 200\n", 87 | "\n", 88 | "graph_data = { 'nodes': [], 'edges': [] }\n", 89 | "\n", 90 | "for i in range(n_nodes):\n", 91 | " graph_data['nodes'].append({\n", 92 | " \"id\": \"n\" + str(i),\n", 93 | " \"label\": \"n\" + str(i),\n", 94 | " \"x\": random.uniform(0,1),\n", 95 | " \"y\": random.uniform(0,1),\n", 96 | " \"size\": random.uniform(0.2,1)\n", 97 | " })\n", 98 | "\n", 99 | "for j in range(n_edges):\n", 100 | " x_center = random.uniform(0,1)\n", 101 | " y_center = random.uniform(0,1)\n", 102 | " x_dist = random.uniform(0.1,0.5)\n", 103 | " y_dist = random.uniform(0.2,0.5)\n", 104 | " neighborhood = []\n", 105 | " for node in graph_data['nodes']:\n", 106 | " if abs(node['x'] - x_center) < x_dist:\n", 107 | " if abs(node['y'] - y_center) < y_dist:\n", 108 | " neighborhood.append(int(node['id'].replace('n','')))\n", 109 | " if len(neighborhood) >= 2:\n", 110 | " ends = random.sample(neighborhood,2)\n", 111 | " graph_data['edges'].append({\n", 112 | " \"id\": \"e\" + str(j),\n", 113 | " \"source\": \"n\" + str(ends[0]),\n", 114 | " \"target\": \"n\" + str(ends[1])\n", 115 | " })" 116 | ] 117 | }, 118 | { 119 | "cell_type": "code", 120 | "execution_count": 4, 121 | "metadata": { 122 | "collapsed": false 123 | }, 124 | "outputs": [ 125 | { 126 | "data": { 127 | "text/html": [ 128 | "
\n", 129 | "\n", 130 | " \n", 131 | " \n", 132 | " \n", 133 | " \n", 134 | " \n", 135 | " \n", 136 | " \n", 137 | " \n", 138 | " \n", 139 | " \n", 140 | " \n", 141 | " \n", 142 | " \n", 143 | " \n", 144 | " \n", 145 | " \n", 146 | " \n", 147 | " \n", 148 | " \n", 149 | " \n", 150 | " \n", 151 | " \n", 152 | " \n", 153 | " \n", 154 | " \n", 155 | " \n", 156 | " \n", 157 | " \n", 158 | " \n", 159 | " \n", 160 | " \n", 161 | " \n", 162 | " \n", 163 | " \n", 164 | " \n", 165 | " \n", 166 | " \n", 167 | " \n", 168 | " \n", 169 | " \n", 170 | " \n", 171 | " \n", 172 | " \n", 173 | " \n", 174 | " \n", 175 | " \n", 176 | " \n", 177 | " \n", 178 | " \n", 179 | " \n", 180 | " \n", 181 | " \n", 182 | "
idlabelsizexy
0n0n00.4200230.6394270.025011
1n1n10.7413600.2232110.736471
2n2n20.5375370.8921800.086939
3n3n30.6042840.0297970.218638
4n4n40.7199080.0265360.198838
\n", 183 | "
" 184 | ], 185 | "text/plain": [ 186 | " id label size x y\n", 187 | "0 n0 n0 0.420023 0.639427 0.025011\n", 188 | "1 n1 n1 0.741360 0.223211 0.736471\n", 189 | "2 n2 n2 0.537537 0.892180 0.086939\n", 190 | "3 n3 n3 0.604284 0.029797 0.218638\n", 191 | "4 n4 n4 0.719908 0.026536 0.198838" 192 | ] 193 | }, 194 | "execution_count": 4, 195 | "metadata": {}, 196 | "output_type": "execute_result" 197 | } 198 | ], 199 | "source": [ 200 | "pd.DataFrame(graph_data['nodes']).head()" 201 | ] 202 | }, 203 | { 204 | "cell_type": "code", 205 | "execution_count": 5, 206 | "metadata": { 207 | "collapsed": false 208 | }, 209 | "outputs": [ 210 | { 211 | "data": { 212 | "text/html": [ 213 | "
\n", 214 | "\n", 215 | " \n", 216 | " \n", 217 | " \n", 218 | " \n", 219 | " \n", 220 | " \n", 221 | " \n", 222 | " \n", 223 | " \n", 224 | " \n", 225 | " \n", 226 | " \n", 227 | " \n", 228 | " \n", 229 | " \n", 230 | " \n", 231 | " \n", 232 | " \n", 233 | " \n", 234 | " \n", 235 | " \n", 236 | " \n", 237 | " \n", 238 | " \n", 239 | " \n", 240 | " \n", 241 | " \n", 242 | " \n", 243 | " \n", 244 | " \n", 245 | " \n", 246 | " \n", 247 | " \n", 248 | " \n", 249 | " \n", 250 | " \n", 251 | " \n", 252 | " \n", 253 | " \n", 254 | " \n", 255 | "
idsourcetarget
0e0n5n12
1e1n25n1
2e2n10n20
3e3n6n29
4e4n15n17
\n", 256 | "
" 257 | ], 258 | "text/plain": [ 259 | " id source target\n", 260 | "0 e0 n5 n12\n", 261 | "1 e1 n25 n1\n", 262 | "2 e2 n10 n20\n", 263 | "3 e3 n6 n29\n", 264 | "4 e4 n15 n17" 265 | ] 266 | }, 267 | "execution_count": 5, 268 | "metadata": {}, 269 | "output_type": "execute_result" 270 | } 271 | ], 272 | "source": [ 273 | "pd.DataFrame(graph_data['edges']).head()" 274 | ] 275 | }, 276 | { 277 | "cell_type": "markdown", 278 | "metadata": {}, 279 | "source": [ 280 | "#### Visualization" 281 | ] 282 | }, 283 | { 284 | "cell_type": "code", 285 | "execution_count": 6, 286 | "metadata": { 287 | "collapsed": false 288 | }, 289 | "outputs": [ 290 | { 291 | "data": { 292 | "text/html": [ 293 | "\n", 294 | "
\n", 295 | "\n" 340 | ], 341 | "text/plain": [ 342 | "" 343 | ] 344 | }, 345 | "execution_count": 6, 346 | "metadata": {}, 347 | "output_type": "execute_result" 348 | } 349 | ], 350 | "source": [ 351 | "js_text_template = Template(open('js/sigma-graph.js','r').read())\n", 352 | "\n", 353 | "js_text = js_text_template.substitute({'graph_data': json.dumps(graph_data),\n", 354 | " 'container': 'graph-div'})\n", 355 | "\n", 356 | "html_template = Template('''\n", 357 | "
\n", 358 | "\n", 359 | "''')\n", 360 | "HTML(html_template.substitute({'js_text': js_text}))" 361 | ] 362 | }, 363 | { 364 | "cell_type": "markdown", 365 | "metadata": { 366 | "collapsed": true 367 | }, 368 | "source": [ 369 | "Note that you can zoom and pan (click and move) to navigate the graph. Also note that if you click on a node, it highlights it and the nodes to which it is directly connected, along with all of the edges within this neighborhood." 370 | ] 371 | } 372 | ], 373 | "metadata": { 374 | "kernelspec": { 375 | "display_name": "Python 2", 376 | "language": "python", 377 | "name": "python2" 378 | }, 379 | "language_info": { 380 | "codemirror_mode": { 381 | "name": "ipython", 382 | "version": 2 383 | }, 384 | "file_extension": ".py", 385 | "mimetype": "text/x-python", 386 | "name": "python", 387 | "nbconvert_exporter": "python", 388 | "pygments_lexer": "ipython2", 389 | "version": "2.7.10" 390 | } 391 | }, 392 | "nbformat": 4, 393 | "nbformat_minor": 0 394 | } 395 | -------------------------------------------------------------------------------- /multiple_simple_examples.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Multiple Simple D3 Examples using d3_lib.py" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "This notebook demonstrates the use of single-line calls to D3 visualizations via the simple d3_lib.py file and referenced css and js files." 15 | ] 16 | }, 17 | { 18 | "cell_type": "markdown", 19 | "metadata": {}, 20 | "source": [ 21 | "#### Configuration for D3" 22 | ] 23 | }, 24 | { 25 | "cell_type": "code", 26 | "execution_count": 1, 27 | "metadata": { 28 | "collapsed": true 29 | }, 30 | "outputs": [], 31 | "source": [ 32 | "from IPython.core.display import HTML\n", 33 | "import d3_lib" 34 | ] 35 | }, 36 | { 37 | "cell_type": "code", 38 | "execution_count": 2, 39 | "metadata": { 40 | "collapsed": false 41 | }, 42 | "outputs": [ 43 | { 44 | "data": { 45 | "text/html": [ 46 | "" 102 | ], 103 | "text/plain": [ 104 | "" 105 | ] 106 | }, 107 | "execution_count": 2, 108 | "metadata": {}, 109 | "output_type": "execute_result" 110 | } 111 | ], 112 | "source": [ 113 | "HTML(d3_lib.set_styles(['basic_axis','basic_line','basic_scatter','force_directed_graph','day-hr-heatmap']))" 114 | ] 115 | }, 116 | { 117 | "cell_type": "code", 118 | "execution_count": 3, 119 | "metadata": { 120 | "collapsed": false 121 | }, 122 | "outputs": [ 123 | { 124 | "data": { 125 | "text/html": [ 126 | "" 127 | ], 128 | "text/plain": [ 129 | "" 130 | ] 131 | }, 132 | "execution_count": 3, 133 | "metadata": {}, 134 | "output_type": "execute_result" 135 | } 136 | ], 137 | "source": [ 138 | "HTML('')" 139 | ] 140 | }, 141 | { 142 | "cell_type": "markdown", 143 | "metadata": {}, 144 | "source": [ 145 | "#### Line plot" 146 | ] 147 | }, 148 | { 149 | "cell_type": "code", 150 | "execution_count": 4, 151 | "metadata": { 152 | "collapsed": true 153 | }, 154 | "outputs": [], 155 | "source": [ 156 | "import pandas as pd\n", 157 | "import random\n", 158 | "random.seed(42)" 159 | ] 160 | }, 161 | { 162 | "cell_type": "code", 163 | "execution_count": 5, 164 | "metadata": { 165 | "collapsed": false 166 | }, 167 | "outputs": [], 168 | "source": [ 169 | "data = []\n", 170 | "for i in range(20):\n", 171 | " data.append({'x': i, 'y': random.uniform(0,1), 'c': int(random.uniform(0,3))})" 172 | ] 173 | }, 174 | { 175 | "cell_type": "markdown", 176 | "metadata": {}, 177 | "source": [ 178 | "Based on http://bl.ocks.org/d3noob/b3ff6ae1c120eea654b5 :" 179 | ] 180 | }, 181 | { 182 | "cell_type": "code", 183 | "execution_count": 6, 184 | "metadata": { 185 | "collapsed": false 186 | }, 187 | "outputs": [ 188 | { 189 | "data": { 190 | "text/html": [ 191 | "\n", 192 | " \n", 193 | "
\n", 194 | " \n", 195 | " \n", 262 | "\n", 263 | " " 264 | ], 265 | "text/plain": [ 266 | "" 267 | ] 268 | }, 269 | "execution_count": 6, 270 | "metadata": {}, 271 | "output_type": "execute_result" 272 | } 273 | ], 274 | "source": [ 275 | "HTML(d3_lib.draw_graph('basic_line',{'data': data}))" 276 | ] 277 | }, 278 | { 279 | "cell_type": "markdown", 280 | "metadata": {}, 281 | "source": [ 282 | "#### Scatterplot with same data" 283 | ] 284 | }, 285 | { 286 | "cell_type": "markdown", 287 | "metadata": {}, 288 | "source": [ 289 | "Based on http://bl.ocks.org/mbostock/3887118 :" 290 | ] 291 | }, 292 | { 293 | "cell_type": "code", 294 | "execution_count": 7, 295 | "metadata": { 296 | "collapsed": false 297 | }, 298 | "outputs": [ 299 | { 300 | "data": { 301 | "text/html": [ 302 | "\n", 303 | " \n", 304 | "
\n", 305 | " \n", 306 | " \n", 390 | "\n", 391 | " " 392 | ], 393 | "text/plain": [ 394 | "" 395 | ] 396 | }, 397 | "execution_count": 7, 398 | "metadata": {}, 399 | "output_type": "execute_result" 400 | } 401 | ], 402 | "source": [ 403 | "HTML(d3_lib.draw_graph('basic_scatter',{'data': data}))" 404 | ] 405 | }, 406 | { 407 | "cell_type": "markdown", 408 | "metadata": {}, 409 | "source": [ 410 | "#### Graph visualization" 411 | ] 412 | }, 413 | { 414 | "cell_type": "markdown", 415 | "metadata": {}, 416 | "source": [ 417 | "Based on http://bl.ocks.org/mbostock/4062045" 418 | ] 419 | }, 420 | { 421 | "cell_type": "code", 422 | "execution_count": 8, 423 | "metadata": { 424 | "collapsed": false 425 | }, 426 | "outputs": [], 427 | "source": [ 428 | "n_nodes = 30\n", 429 | "p_edge = 0.05\n", 430 | "graph = {\"nodes\": [], \"links\": []}\n", 431 | "for i in range(n_nodes):\n", 432 | " graph[\"nodes\"].append( {\"name\": \"i\" + str(i), \"group\": int(random.uniform(1,11))} )\n", 433 | "for i in range(n_nodes):\n", 434 | " for j in range(n_nodes):\n", 435 | " if random.uniform(0,1) < p_edge:\n", 436 | " graph[\"links\"].append( {\"source\": i, \"target\": j, \"value\": random.uniform(0.5,3)} )" 437 | ] 438 | }, 439 | { 440 | "cell_type": "code", 441 | "execution_count": 9, 442 | "metadata": { 443 | "collapsed": false 444 | }, 445 | "outputs": [ 446 | { 447 | "data": { 448 | "text/html": [ 449 | "\n", 450 | " \n", 451 | "
\n", 452 | " \n", 453 | " \n", 512 | "\n", 513 | " " 514 | ], 515 | "text/plain": [ 516 | "" 517 | ] 518 | }, 519 | "execution_count": 9, 520 | "metadata": {}, 521 | "output_type": "execute_result" 522 | } 523 | ], 524 | "source": [ 525 | "HTML(d3_lib.draw_graph('force_directed_graph',{'data': graph}))" 526 | ] 527 | }, 528 | { 529 | "cell_type": "markdown", 530 | "metadata": {}, 531 | "source": [ 532 | "#### Day-Hour heatmap" 533 | ] 534 | }, 535 | { 536 | "cell_type": "markdown", 537 | "metadata": {}, 538 | "source": [ 539 | "Based on http://bl.ocks.org/tjdecke/5558084" 540 | ] 541 | }, 542 | { 543 | "cell_type": "code", 544 | "execution_count": 10, 545 | "metadata": { 546 | "collapsed": false 547 | }, 548 | "outputs": [], 549 | "source": [ 550 | "data = []\n", 551 | "for d in range(1,8):\n", 552 | " for h in range(1,25):\n", 553 | " data.append({'day': d, 'hour': h, 'value': int(random.gauss(0,100))})" 554 | ] 555 | }, 556 | { 557 | "cell_type": "code", 558 | "execution_count": 11, 559 | "metadata": { 560 | "collapsed": false 561 | }, 562 | "outputs": [ 563 | { 564 | "data": { 565 | "text/html": [ 566 | "\n", 567 | " \n", 568 | "
\n", 569 | " \n", 570 | " \n", 669 | "\n", 670 | " " 671 | ], 672 | "text/plain": [ 673 | "" 674 | ] 675 | }, 676 | "execution_count": 11, 677 | "metadata": {}, 678 | "output_type": "execute_result" 679 | } 680 | ], 681 | "source": [ 682 | "HTML(d3_lib.draw_graph('day-hr-heatmap',{'data': data}))" 683 | ] 684 | } 685 | ], 686 | "metadata": { 687 | "kernelspec": { 688 | "display_name": "Python 2", 689 | "language": "python", 690 | "name": "python2" 691 | }, 692 | "language_info": { 693 | "codemirror_mode": { 694 | "name": "ipython", 695 | "version": 2 696 | }, 697 | "file_extension": ".py", 698 | "mimetype": "text/x-python", 699 | "name": "python", 700 | "nbconvert_exporter": "python", 701 | "pygments_lexer": "ipython2", 702 | "version": "2.7.10" 703 | } 704 | }, 705 | "nbformat": 4, 706 | "nbformat_minor": 0 707 | } 708 | -------------------------------------------------------------------------------- /iris_scatterplot.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Iris Scatterplot\n", 8 | "### A simple example of using a bl.ock as the basis for a D3 visualization in Jupyter" 9 | ] 10 | }, 11 | { 12 | "cell_type": "markdown", 13 | "metadata": {}, 14 | "source": [ 15 | "Using this [bl.ocks example](http://bl.ocks.org/mbostock/3887118) as a template, we will construct a scatterplot of the canonical Iris dataset." 16 | ] 17 | }, 18 | { 19 | "cell_type": "markdown", 20 | "metadata": {}, 21 | "source": [ 22 | "#### Notebook Config" 23 | ] 24 | }, 25 | { 26 | "cell_type": "code", 27 | "execution_count": 1, 28 | "metadata": { 29 | "collapsed": true 30 | }, 31 | "outputs": [], 32 | "source": [ 33 | "from IPython.core.display import display, HTML\n", 34 | "from string import Template\n", 35 | "import pandas as pd\n", 36 | "import json, random" 37 | ] 38 | }, 39 | { 40 | "cell_type": "code", 41 | "execution_count": 2, 42 | "metadata": { 43 | "collapsed": false 44 | }, 45 | "outputs": [ 46 | { 47 | "data": { 48 | "text/html": [ 49 | "" 50 | ], 51 | "text/plain": [ 52 | "" 53 | ] 54 | }, 55 | "execution_count": 2, 56 | "metadata": {}, 57 | "output_type": "execute_result" 58 | } 59 | ], 60 | "source": [ 61 | "HTML('')" 62 | ] 63 | }, 64 | { 65 | "cell_type": "markdown", 66 | "metadata": {}, 67 | "source": [ 68 | "#### Data" 69 | ] 70 | }, 71 | { 72 | "cell_type": "markdown", 73 | "metadata": {}, 74 | "source": [ 75 | "The bl.ocks example uses a tsv file with the iris dataset. If you click on the block number at the top of the bl.ocks post, it will take you to the [github gist](https://gist.github.com/mbostock/3887118) upon which this bl.ocks entry is based. From there you can navigate to the raw version of the tsv file, and read that into a Pandas dataframe, as below. (Mind you, there are also many many other ways of getting this canonical dataset.)" 76 | ] 77 | }, 78 | { 79 | "cell_type": "code", 80 | "execution_count": 3, 81 | "metadata": { 82 | "collapsed": false 83 | }, 84 | "outputs": [ 85 | { 86 | "data": { 87 | "text/html": [ 88 | "
\n", 89 | "\n", 90 | " \n", 91 | " \n", 92 | " \n", 93 | " \n", 94 | " \n", 95 | " \n", 96 | " \n", 97 | " \n", 98 | " \n", 99 | " \n", 100 | " \n", 101 | " \n", 102 | " \n", 103 | " \n", 104 | " \n", 105 | " \n", 106 | " \n", 107 | " \n", 108 | " \n", 109 | " \n", 110 | " \n", 111 | " \n", 112 | " \n", 113 | " \n", 114 | " \n", 115 | " \n", 116 | " \n", 117 | " \n", 118 | " \n", 119 | " \n", 120 | " \n", 121 | " \n", 122 | " \n", 123 | " \n", 124 | " \n", 125 | " \n", 126 | " \n", 127 | " \n", 128 | " \n", 129 | " \n", 130 | " \n", 131 | " \n", 132 | " \n", 133 | " \n", 134 | " \n", 135 | " \n", 136 | " \n", 137 | " \n", 138 | " \n", 139 | " \n", 140 | " \n", 141 | " \n", 142 | "
sepalLengthsepalWidthpetalLengthpetalWidthspecies
05.13.51.40.2setosa
14.93.01.40.2setosa
24.73.21.30.2setosa
34.63.11.50.2setosa
45.03.61.40.2setosa
\n", 143 | "
" 144 | ], 145 | "text/plain": [ 146 | " sepalLength sepalWidth petalLength petalWidth species\n", 147 | "0 5.1 3.5 1.4 0.2 setosa\n", 148 | "1 4.9 3.0 1.4 0.2 setosa\n", 149 | "2 4.7 3.2 1.3 0.2 setosa\n", 150 | "3 4.6 3.1 1.5 0.2 setosa\n", 151 | "4 5.0 3.6 1.4 0.2 setosa" 152 | ] 153 | }, 154 | "execution_count": 3, 155 | "metadata": {}, 156 | "output_type": "execute_result" 157 | } 158 | ], 159 | "source": [ 160 | "filename = 'https://gist.githubusercontent.com/mbostock/3887118/raw/2e68ffbeb23fe4dadd9b0f6bca62e9def6ee9e17/data.tsv'\n", 161 | "iris = pd.read_csv(filename,sep=\"\\t\")\n", 162 | "iris.head()" 163 | ] 164 | }, 165 | { 166 | "cell_type": "markdown", 167 | "metadata": {}, 168 | "source": [ 169 | "A trick of the D3 trade is to know that its file readers usually output the data in the form of an array of dictionaries. As such, we will reformat our tabular data that way in preparation for it to be used in the graph below." 170 | ] 171 | }, 172 | { 173 | "cell_type": "code", 174 | "execution_count": 4, 175 | "metadata": { 176 | "collapsed": false 177 | }, 178 | "outputs": [ 179 | { 180 | "data": { 181 | "text/plain": [ 182 | "[{'petalLength': 1.4,\n", 183 | " 'petalWidth': 0.2,\n", 184 | " 'sepalLength': 5.1,\n", 185 | " 'sepalWidth': 3.5,\n", 186 | " 'species': 'setosa'},\n", 187 | " {'petalLength': 1.4,\n", 188 | " 'petalWidth': 0.2,\n", 189 | " 'sepalLength': 4.9,\n", 190 | " 'sepalWidth': 3.0,\n", 191 | " 'species': 'setosa'},\n", 192 | " {'petalLength': 1.3,\n", 193 | " 'petalWidth': 0.2,\n", 194 | " 'sepalLength': 4.7,\n", 195 | " 'sepalWidth': 3.2,\n", 196 | " 'species': 'setosa'},\n", 197 | " {'petalLength': 1.5,\n", 198 | " 'petalWidth': 0.2,\n", 199 | " 'sepalLength': 4.6,\n", 200 | " 'sepalWidth': 3.1,\n", 201 | " 'species': 'setosa'},\n", 202 | " {'petalLength': 1.4,\n", 203 | " 'petalWidth': 0.2,\n", 204 | " 'sepalLength': 5.0,\n", 205 | " 'sepalWidth': 3.6,\n", 206 | " 'species': 'setosa'}]" 207 | ] 208 | }, 209 | "execution_count": 4, 210 | "metadata": {}, 211 | "output_type": "execute_result" 212 | } 213 | ], 214 | "source": [ 215 | "iris_array_of_dicts = iris.to_dict(orient='records')\n", 216 | "iris_array_of_dicts[:5]" 217 | ] 218 | }, 219 | { 220 | "cell_type": "markdown", 221 | "metadata": {}, 222 | "source": [ 223 | "#### CSS and JavaScript based on bl.ocks example" 224 | ] 225 | }, 226 | { 227 | "cell_type": "markdown", 228 | "metadata": {}, 229 | "source": [ 230 | "Note that in the below css_text, we have removed the 'body' style reference from the original bl.ocks text. This is to avoid this style changing the rest of the notebook." 231 | ] 232 | }, 233 | { 234 | "cell_type": "code", 235 | "execution_count": 5, 236 | "metadata": { 237 | "collapsed": true 238 | }, 239 | "outputs": [], 240 | "source": [ 241 | "css_text = '''\n", 242 | ".axis path,\n", 243 | ".axis line {\n", 244 | " fill: none;\n", 245 | " stroke: #000;\n", 246 | " shape-rendering: crispEdges;\n", 247 | "}\n", 248 | "\n", 249 | ".dot {\n", 250 | " stroke: #000;\n", 251 | "}\n", 252 | "'''" 253 | ] 254 | }, 255 | { 256 | "cell_type": "markdown", 257 | "metadata": {}, 258 | "source": [ 259 | "The javascript below was copied directly from the bl.ocks script text, and then six lines were changed, as noted by // **** (the double-backslash is a comment in javascript, so these lines will not be executed). The first set of changes is to the width and height of the image. The second change is simply to reference a different DOM element as the starting point. The remaining changes are to replace the data-file reading step with a direct infusion of data into the script. (Note that the $ characters denote replacement points in the Template object.) " 260 | ] 261 | }, 262 | { 263 | "cell_type": "code", 264 | "execution_count": 6, 265 | "metadata": { 266 | "collapsed": true 267 | }, 268 | "outputs": [], 269 | "source": [ 270 | "js_text_template = Template('''\n", 271 | "var margin = {top: 20, right: 20, bottom: 30, left: 40},\n", 272 | "// **** width = 960 - margin.left - margin.right, ****\n", 273 | "// **** height = 500 - margin.top - margin.bottom; ****\n", 274 | " width = 720 - margin.left - margin.right,\n", 275 | " height = 375 - margin.top - margin.bottom;\n", 276 | "\n", 277 | "var x = d3.scale.linear()\n", 278 | " .range([0, width]);\n", 279 | "\n", 280 | "var y = d3.scale.linear()\n", 281 | " .range([height, 0]);\n", 282 | "\n", 283 | "var color = d3.scale.category10();\n", 284 | "\n", 285 | "var xAxis = d3.svg.axis()\n", 286 | " .scale(x)\n", 287 | " .orient(\"bottom\");\n", 288 | "\n", 289 | "var yAxis = d3.svg.axis()\n", 290 | " .scale(y)\n", 291 | " .orient(\"left\");\n", 292 | "\n", 293 | "// **** var svg = d3.select(\"body\").append(\"svg\") ****\n", 294 | "var svg = d3.select(\"#$graphdiv\").append(\"svg\")\n", 295 | " .attr(\"width\", width + margin.left + margin.right)\n", 296 | " .attr(\"height\", height + margin.top + margin.bottom)\n", 297 | " .append(\"g\")\n", 298 | " .attr(\"transform\", \"translate(\" + margin.left + \",\" + margin.top + \")\");\n", 299 | "\n", 300 | "// **** d3.tsv(\"data.tsv\", function(error, data) { ****\n", 301 | "// **** if (error) throw error; ****\n", 302 | "\n", 303 | "var data = $python_data ;\n", 304 | "\n", 305 | " data.forEach(function(d) {\n", 306 | " d.sepalLength = +d.sepalLength;\n", 307 | " d.sepalWidth = +d.sepalWidth;\n", 308 | " });\n", 309 | "\n", 310 | " x.domain(d3.extent(data, function(d) { return d.sepalWidth; })).nice();\n", 311 | " y.domain(d3.extent(data, function(d) { return d.sepalLength; })).nice();\n", 312 | "\n", 313 | " svg.append(\"g\")\n", 314 | " .attr(\"class\", \"x axis\")\n", 315 | " .attr(\"transform\", \"translate(0,\" + height + \")\")\n", 316 | " .call(xAxis)\n", 317 | " .append(\"text\")\n", 318 | " .attr(\"class\", \"label\")\n", 319 | " .attr(\"x\", width)\n", 320 | " .attr(\"y\", -6)\n", 321 | " .style(\"text-anchor\", \"end\")\n", 322 | " .text(\"Sepal Width (cm)\");\n", 323 | "\n", 324 | " svg.append(\"g\")\n", 325 | " .attr(\"class\", \"y axis\")\n", 326 | " .call(yAxis)\n", 327 | " .append(\"text\")\n", 328 | " .attr(\"class\", \"label\")\n", 329 | " .attr(\"transform\", \"rotate(-90)\")\n", 330 | " .attr(\"y\", 6)\n", 331 | " .attr(\"dy\", \".71em\")\n", 332 | " .style(\"text-anchor\", \"end\")\n", 333 | " .text(\"Sepal Length (cm)\")\n", 334 | "\n", 335 | " svg.selectAll(\".dot\")\n", 336 | " .data(data)\n", 337 | " .enter().append(\"circle\")\n", 338 | " .attr(\"class\", \"dot\")\n", 339 | " .attr(\"r\", 3.5)\n", 340 | " .attr(\"cx\", function(d) { return x(d.sepalWidth); })\n", 341 | " .attr(\"cy\", function(d) { return y(d.sepalLength); })\n", 342 | " .style(\"fill\", function(d) { return color(d.species); });\n", 343 | "\n", 344 | " var legend = svg.selectAll(\".legend\")\n", 345 | " .data(color.domain())\n", 346 | " .enter().append(\"g\")\n", 347 | " .attr(\"class\", \"legend\")\n", 348 | " .attr(\"transform\", function(d, i) { return \"translate(0,\" + i * 20 + \")\"; });\n", 349 | "\n", 350 | " legend.append(\"rect\")\n", 351 | " .attr(\"x\", width - 18)\n", 352 | " .attr(\"width\", 18)\n", 353 | " .attr(\"height\", 18)\n", 354 | " .style(\"fill\", color);\n", 355 | "\n", 356 | " legend.append(\"text\")\n", 357 | " .attr(\"x\", width - 24)\n", 358 | " .attr(\"y\", 9)\n", 359 | " .attr(\"dy\", \".35em\")\n", 360 | " .style(\"text-anchor\", \"end\")\n", 361 | " .text(function(d) { return d; });\n", 362 | "\n", 363 | "// **** }); ****\n", 364 | "\n", 365 | "''')" 366 | ] 367 | }, 368 | { 369 | "cell_type": "markdown", 370 | "metadata": {}, 371 | "source": [ 372 | "#### And finally, the viz" 373 | ] 374 | }, 375 | { 376 | "cell_type": "code", 377 | "execution_count": 7, 378 | "metadata": { 379 | "collapsed": false 380 | }, 381 | "outputs": [ 382 | { 383 | "data": { 384 | "text/html": [ 385 | "\n", 386 | "\n", 398 | "
\n", 399 | "\n" 495 | ], 496 | "text/plain": [ 497 | "" 498 | ] 499 | }, 500 | "execution_count": 7, 501 | "metadata": {}, 502 | "output_type": "execute_result" 503 | } 504 | ], 505 | "source": [ 506 | "html_template = Template('''\n", 507 | "\n", 508 | "
\n", 509 | "\n", 510 | "''')\n", 511 | "js_text = js_text_template.substitute({'python_data': json.dumps(iris_array_of_dicts),\n", 512 | " 'graphdiv': 'graph-div'})\n", 513 | "HTML(html_template.substitute({'css_text': css_text, 'js_text': js_text}))" 514 | ] 515 | } 516 | ], 517 | "metadata": { 518 | "kernelspec": { 519 | "display_name": "Python 2", 520 | "language": "python", 521 | "name": "python2" 522 | }, 523 | "language_info": { 524 | "codemirror_mode": { 525 | "name": "ipython", 526 | "version": 2 527 | }, 528 | "file_extension": ".py", 529 | "mimetype": "text/x-python", 530 | "name": "python", 531 | "nbconvert_exporter": "python", 532 | "pygments_lexer": "ipython2", 533 | "version": "2.7.10" 534 | } 535 | }, 536 | "nbformat": 4, 537 | "nbformat_minor": 0 538 | } 539 | --------------------------------------------------------------------------------