├── .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 | [](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"
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",
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 | " letter | \n",
224 | " y | \n",
225 | "
\n",
226 | " \n",
227 | " \n",
228 | " \n",
229 | " | 0 | \n",
230 | " A | \n",
231 | " 1 | \n",
232 | "
\n",
233 | " \n",
234 | " | 1 | \n",
235 | " B | \n",
236 | " 1 | \n",
237 | "
\n",
238 | " \n",
239 | " | 2 | \n",
240 | " C | \n",
241 | " 1 | \n",
242 | "
\n",
243 | " \n",
244 | " | 3 | \n",
245 | " D | \n",
246 | " 1 | \n",
247 | "
\n",
248 | " \n",
249 | "
\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 | " id | \n",
134 | " label | \n",
135 | " size | \n",
136 | " x | \n",
137 | " y | \n",
138 | "
\n",
139 | " \n",
140 | " \n",
141 | " \n",
142 | " | 0 | \n",
143 | " n0 | \n",
144 | " n0 | \n",
145 | " 0.420023 | \n",
146 | " 0.639427 | \n",
147 | " 0.025011 | \n",
148 | "
\n",
149 | " \n",
150 | " | 1 | \n",
151 | " n1 | \n",
152 | " n1 | \n",
153 | " 0.741360 | \n",
154 | " 0.223211 | \n",
155 | " 0.736471 | \n",
156 | "
\n",
157 | " \n",
158 | " | 2 | \n",
159 | " n2 | \n",
160 | " n2 | \n",
161 | " 0.537537 | \n",
162 | " 0.892180 | \n",
163 | " 0.086939 | \n",
164 | "
\n",
165 | " \n",
166 | " | 3 | \n",
167 | " n3 | \n",
168 | " n3 | \n",
169 | " 0.604284 | \n",
170 | " 0.029797 | \n",
171 | " 0.218638 | \n",
172 | "
\n",
173 | " \n",
174 | " | 4 | \n",
175 | " n4 | \n",
176 | " n4 | \n",
177 | " 0.719908 | \n",
178 | " 0.026536 | \n",
179 | " 0.198838 | \n",
180 | "
\n",
181 | " \n",
182 | "
\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 | " id | \n",
219 | " source | \n",
220 | " target | \n",
221 | "
\n",
222 | " \n",
223 | " \n",
224 | " \n",
225 | " | 0 | \n",
226 | " e0 | \n",
227 | " n5 | \n",
228 | " n12 | \n",
229 | "
\n",
230 | " \n",
231 | " | 1 | \n",
232 | " e1 | \n",
233 | " n25 | \n",
234 | " n1 | \n",
235 | "
\n",
236 | " \n",
237 | " | 2 | \n",
238 | " e2 | \n",
239 | " n10 | \n",
240 | " n20 | \n",
241 | "
\n",
242 | " \n",
243 | " | 3 | \n",
244 | " e3 | \n",
245 | " n6 | \n",
246 | " n29 | \n",
247 | "
\n",
248 | " \n",
249 | " | 4 | \n",
250 | " e4 | \n",
251 | " n15 | \n",
252 | " n17 | \n",
253 | "
\n",
254 | " \n",
255 | "
\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 | " sepalLength | \n",
94 | " sepalWidth | \n",
95 | " petalLength | \n",
96 | " petalWidth | \n",
97 | " species | \n",
98 | "
\n",
99 | " \n",
100 | " \n",
101 | " \n",
102 | " | 0 | \n",
103 | " 5.1 | \n",
104 | " 3.5 | \n",
105 | " 1.4 | \n",
106 | " 0.2 | \n",
107 | " setosa | \n",
108 | "
\n",
109 | " \n",
110 | " | 1 | \n",
111 | " 4.9 | \n",
112 | " 3.0 | \n",
113 | " 1.4 | \n",
114 | " 0.2 | \n",
115 | " setosa | \n",
116 | "
\n",
117 | " \n",
118 | " | 2 | \n",
119 | " 4.7 | \n",
120 | " 3.2 | \n",
121 | " 1.3 | \n",
122 | " 0.2 | \n",
123 | " setosa | \n",
124 | "
\n",
125 | " \n",
126 | " | 3 | \n",
127 | " 4.6 | \n",
128 | " 3.1 | \n",
129 | " 1.5 | \n",
130 | " 0.2 | \n",
131 | " setosa | \n",
132 | "
\n",
133 | " \n",
134 | " | 4 | \n",
135 | " 5.0 | \n",
136 | " 3.6 | \n",
137 | " 1.4 | \n",
138 | " 0.2 | \n",
139 | " setosa | \n",
140 | "
\n",
141 | " \n",
142 | "
\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 |
--------------------------------------------------------------------------------