Added modified d3-sankey.js library to repository. Now can handle alignment changes.
Project: http://git-wip-us.apache.org/repos/asf/incubator-senssoft-tap/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-senssoft-tap/commit/607675ba Tree: http://git-wip-us.apache.org/repos/asf/incubator-senssoft-tap/tree/607675ba Diff: http://git-wip-us.apache.org/repos/asf/incubator-senssoft-tap/diff/607675ba Branch: refs/heads/ryan-sankey Commit: 607675ba59d53504d688c7741c4097ad0f5c8568 Parents: 587c877 Author: Ryan-Brill <rbr...@draper.com> Authored: Fri Sep 1 13:30:09 2017 -0400 Committer: Ryan-Brill <rbr...@draper.com> Committed: Fri Sep 1 13:30:09 2017 -0400 ---------------------------------------------------------------------- Sankey/csvSankey-v4/d3-sankey.js | 357 +++ Sankey/csvSankey-v4/dataSubsetFrom811.csv | 1 + Sankey/csvSankey-v4/energy.json | 372 +++ Sankey/csvSankey-v4/exampleData.csv | 8 + Sankey/csvSankey-v4/exampleData.json | 3111 ++++++++++++++++++++++++ Sankey/csvSankey-v4/index.html | 123 + Sankey/csvSankey-v4/sample.json | 81 + Sankey/csvSankey-v4/sampledTen.json | 217 ++ Sankey/csvSankey-v4/sankey.js | 295 +++ Sankey/csvSankey-v4/sankey.json | 295 +++ Sankey/csvSankey-v4/sankey825.csv | 1 + Sankey/csvSankey-v4/sankey825short.csv | 1 + 12 files changed, 4862 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-senssoft-tap/blob/607675ba/Sankey/csvSankey-v4/d3-sankey.js ---------------------------------------------------------------------- diff --git a/Sankey/csvSankey-v4/d3-sankey.js b/Sankey/csvSankey-v4/d3-sankey.js new file mode 100644 index 0000000..640ae52 --- /dev/null +++ b/Sankey/csvSankey-v4/d3-sankey.js @@ -0,0 +1,357 @@ +/* Modified to work with d3.v4 build */ +/* https://gist.github.com/rschuman/66c8564e8165496d7ef516eae882895c#file-d3-sankey-js-L64*/ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3-arrays'), require('d3-interpolate')) : + typeof define === 'function' && define.amd ? define('d3-sankey', ['exports', 'd3-arrays', 'd3-interpolate'], factory) : + factory((global.d3_sankey = {}),global.d3_arrays,global.d3_interpolate); +}(this, function (exports,d3Arrays,d3Interpolate) { 'use strict'; + + // Stolen from https://github.com/d3/d3-plugins/tree/master/sankey + + function sankey() { + var sankey = {}, + nodeWidth = 24, + nodePadding = 20, + size = [1, 1], + align = 'left', + nodes = [], + links = []; + + + sankey.nodeWidth = function(_) { + if (!arguments.length) return nodeWidth; + nodeWidth = +_; + return sankey; + }; + + sankey.nodePadding = function(_) { + if (!arguments.length) return nodePadding; + nodePadding = +_; + return sankey; + }; + + sankey.nodes = function(_) { + if (!arguments.length) return nodes; + nodes = _; + return sankey; + }; + + sankey.links = function(_) { + if (!arguments.length) return links; + links = _; + return sankey; + }; + + sankey.size = function(_) { + if (!arguments.length) return size; + size = _; + return sankey; + }; + + sankey.layout = function(iterations) { + computeNodeLinks(); + computeNodeValues(); + computeNodeBreadths(); + computeNodeDepths(iterations); + computeLinkDepths(); + return sankey; + }; + + sankey.relayout = function() { + computeLinkDepths(); + return sankey; + }; + + sankey.link = function() { + var curvature = .5; + + function link(d) { + var x0 = d.source.x + d.source.dx, + x1 = d.target.x, + xi = d3.interpolateNumber(x0, x1), + x2 = xi(curvature), + x3 = xi(1 - curvature), + y0 = d.source.y + d.sy + d.dy / 2, + y1 = d.target.y + d.ty + d.dy / 2; + return "M" + x0 + "," + y0 + "C" + x2 + "," + y0 + " " + x3 + "," + y1 + " " + x1 + "," + y1; + } + + link.curvature = function(_) { + if (!arguments.length) return curvature; + curvature = +_; + return link; + }; + + return link; + }; + + // Populate the sourceLinks and targetLinks for each node. + // Also, if the source and target are not objects, assume they are indices. + function computeNodeLinks() { + nodes.forEach(function(node) { + node.sourceLinks = []; + node.targetLinks = []; + }); + links.forEach(function(link) { + var source = link.source, + target = link.target; + if (typeof source === "number") source = link.source = nodes[link.source]; + if (typeof target === "number") target = link.target = nodes[link.target]; + source.sourceLinks.push(link); + target.targetLinks.push(link); + }); + } + + // Compute the value (size) of each node by summing the associated links. + function computeNodeValues() { + nodes.forEach(function(node) { + node.value = Math.max( + d3.sum(node.sourceLinks, value), + d3.sum(node.targetLinks, value) + ); + }); + } + sankey.nodeAlign = function(_) { + return arguments.length ? (align = typeof _ === "function" ? _ : constant(_), sankey) : align; + }; + // Iteratively assign the breadth (x-position) for each node. + // Nodes are assigned the maximum breadth of incoming neighbors plus one; + // nodes with no incoming links are assigned breadth zero, while + // nodes with no outgoing links are assigned the maximum breadth. + function computeNodeBreadths() { + var remainingNodes = nodes, + nextNodes, + x = 0; + + while (remainingNodes.length) { + nextNodes = []; + remainingNodes.forEach(function(node) { + node.x = x; + node.dx = nodeWidth; + node.sourceLinks.forEach(function(link) { + if (nextNodes.indexOf(link.target) < 0) { + nextNodes.push(link.target); + } + }); + }); + remainingNodes = nextNodes; + ++x; + } + + // if (reverse) { + // // Flip nodes horizontally + // nodes.forEach(function(node) { + // node.x *= -1; + // node.x += x - 1; + // }); + // } + + if (align === 'center') { + moveSourcesRight(); + } + if (align === 'justify') { + moveSinksRight(x); + } + + scaleNodeBreadths((size[0] - nodeWidth) / (x - 1)); + } + + function moveSourcesRight() { + nodes.slice() + // Pack nodes from right to left + .sort(function(a, b) { return b.x - a.x; }) + .forEach(function(node) { + if (!node.targetLinks.length) { + node.x = d3Array.min(node.sourceLinks, function(d) { return d.target.x; }) - 1; + } + }); + } + + function moveSinksRight(x) { + nodes.forEach(function(node) { + if (!node.sourceLinks.length) { + node.x = x - 1; + } + }); + } + + function moveSourcesRight() { + nodes.forEach(function(node) { + if (!node.targetLinks.length) { + node.x = d3.min(node.sourceLinks, function(d) { + return d.target.x; + }) - 1; + } + }); + } + + function moveSinksRight(x) { + nodes.forEach(function(node) { + if (!node.sourceLinks.length) { + node.x = x - 1; + } + }); + } + + function scaleNodeBreadths(kx) { + nodes.forEach(function(node) { + node.x *= kx; + }); + } + + function computeNodeDepths(iterations) { + var nodesByBreadth = d3.nest() + .key(function(d) { + return d.x; + }) + .sortKeys(d3.ascending) + .entries(nodes) + .map(function(d) { + return d.values; + }); + + // + initializeNodeDepth(); + resolveCollisions(); + for (var alpha = 1; iterations > 0; --iterations) { + relaxRightToLeft(alpha *= .99); + resolveCollisions(); + relaxLeftToRight(alpha); + resolveCollisions(); + } + + function initializeNodeDepth() { + var ky = d3.min(nodesByBreadth, function(nodes) { + return (size[1] - (nodes.length - 1) * nodePadding) / d3.sum(nodes, value); + }); + + nodesByBreadth.forEach(function(nodes) { + nodes.forEach(function(node, i) { + node.y = i; + node.dy = node.value * ky; + }); + }); + + links.forEach(function(link) { + link.dy = link.value * ky; + }); + } + + function relaxLeftToRight(alpha) { + nodesByBreadth.forEach(function(nodes, breadth) { + nodes.forEach(function(node) { + if (node.targetLinks.length) { + var y = d3.sum(node.targetLinks, weightedSource) / d3.sum(node.targetLinks, value); + node.y += (y - center(node)) * alpha; + } + }); + }); + + function weightedSource(link) { + return center(link.source) * link.value; + } + } + + function relaxRightToLeft(alpha) { + nodesByBreadth.slice().reverse().forEach(function(nodes) { + nodes.forEach(function(node) { + if (node.sourceLinks.length) { + var y = d3.sum(node.sourceLinks, weightedTarget) / d3.sum(node.sourceLinks, value); + node.y += (y - center(node)) * alpha; + } + }); + }); + + function weightedTarget(link) { + return center(link.target) * link.value; + } + } + + function resolveCollisions() { + nodesByBreadth.forEach(function(nodes) { + var node, + dy, + y0 = 0, + n = nodes.length, + i; + + // Push any overlapping nodes down. + nodes.sort(ascendingDepth); + for (i = 0; i < n; ++i) { + node = nodes[i]; + dy = y0 - node.y; + if (dy > 0) node.y += dy; + y0 = node.y + node.dy + nodePadding; + } + + // If the bottommost node goes outside the bounds, push it back up. + dy = y0 - nodePadding - size[1]; + if (dy > 0) { + y0 = node.y -= dy; + + // Push any overlapping nodes back up. + for (i = n - 2; i >= 0; --i) { + node = nodes[i]; + dy = node.y + node.dy + nodePadding - y0; + if (dy > 0) node.y -= dy; + y0 = node.y; + } + } + }); + } + + function ascendingDepth(a, b) { + return a.y - b.y; + } + } + + function computeLinkDepths() { + nodes.forEach(function(node) { + node.sourceLinks.sort(ascendingTargetDepth); + node.targetLinks.sort(ascendingSourceDepth); + }); + nodes.forEach(function(node) { + var sy = 0, + ty = 0; + node.sourceLinks.forEach(function(link) { + link.sy = sy; + sy += link.dy; + }); + node.targetLinks.forEach(function(link) { + link.ty = ty; + ty += link.dy; + }); + }); + + function ascendingSourceDepth(a, b) { + return a.source.y - b.source.y; + } + + function ascendingTargetDepth(a, b) { + return a.target.y - b.target.y; + } + } + + function center(node) { + return node.y + node.dy / 2; + } + + function value(link) { + return link.value; + } + + sankey.align = function(_) { + if (!arguments.length) return align; + align = _.toLowerCase(); + return sankey; + }; + + return sankey; + }; + + var version = "0.2.0"; + + exports.version = version; + exports.sankey = sankey; + +})); http://git-wip-us.apache.org/repos/asf/incubator-senssoft-tap/blob/607675ba/Sankey/csvSankey-v4/dataSubsetFrom811.csv ---------------------------------------------------------------------- diff --git a/Sankey/csvSankey-v4/dataSubsetFrom811.csv b/Sankey/csvSankey-v4/dataSubsetFrom811.csv new file mode 100644 index 0000000..ac62bb5 --- /dev/null +++ b/Sankey/csvSankey-v4/dataSubsetFrom811.csv @@ -0,0 +1 @@ +"���""pathLength""",sequenceID,source,sourceName,target,targetChange,targetName,type,typeChange,value1,Window->#document,1,Window,3,1,#document,focus,1,11,#document->div.expand-trigger,3,#document,2,1,div.expand-trigger,load,1,21,#document->div.expand-trigger,3,#document,2,1,div.expand-trigger,load,1,21,#document->div.contract-trigger,3,#document,5,1,div.contract-trigger,load,1,21,#document->div.contract-trigger,3,#document,5,1,div.contract-trigger,load,1,21,#document->a#dataset-dropdown-link.dropdown-toggle primary ng-binding,3,#document,4,1,a#dataset-dropdown-link.dropdown-toggle primary ng-binding,load,1,11,#document->div.contract-trigger,3,#document,8,1,div.contract-trigger,load,1,18,div.expand-trigger->a#dataset-dropdown-link.dropdown-toggle primary ng-binding,6,div.expand-trigger,9,1,a#dataset-dropdown-link.dropdown-toggle primary ng-binding,scroll,1,18,div.expand-trigger->a#dataset-dropdown-link.dropdown-toggle primary ng-binding,6,div.expand-trigger,7,1,a#data set-dropdown-link.dropdown-toggle primary ng-binding,scroll,1,28,div.contract-trigger->a#dataset-dropdown-link.dropdown-toggle primary ng-binding,8,div.contract-trigger,7,1,a#dataset-dropdown-link.dropdown-toggle primary ng-binding,scroll,1,28,div.contract-trigger->a#dataset-dropdown-link.dropdown-toggle primary ng-binding,8,div.contract-trigger,7,1,a#dataset-dropdown-link.dropdown-toggle primary ng-binding,scroll,1,28,div.contract-trigger->a#dataset-dropdown-link.dropdown-toggle primary ng-binding,8,div.contract-trigger,9,1,a#dataset-dropdown-link.dropdown-toggle primary ng-binding,scroll,1,111,a#dataset-dropdown-link.dropdown-toggle primary ng-binding->ul.dropdown-menu,9,a#dataset-dropdown-link.dropdown-toggle primary ng-binding,10,1,ul.dropdown-menu,click,1,411,a#dataset-dropdown-link.dropdown-toggle primary ng-binding->ul.dropdown-menu,9,a#dataset-dropdown-link.dropdown-toggle primary ng-binding,10,1,ul.dropdown-menu,click,1,411,a#dataset-dropdown-link.dropdown-toggle prim ary ng-binding->ul.dropdown-menu,9,a#dataset-dropdown-link.dropdown-toggle primary ng-binding,10,1,ul.dropdown-menu,click,1,411,a#dataset-dropdown-link.dropdown-toggle primary ng-binding->ul.dropdown-menu,9,a#dataset-dropdown-link.dropdown-toggle primary ng-binding,10,1,ul.dropdown-menu,click,1,4 \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-senssoft-tap/blob/607675ba/Sankey/csvSankey-v4/energy.json ---------------------------------------------------------------------- diff --git a/Sankey/csvSankey-v4/energy.json b/Sankey/csvSankey-v4/energy.json new file mode 100644 index 0000000..a4257b5 --- /dev/null +++ b/Sankey/csvSankey-v4/energy.json @@ -0,0 +1,372 @@ +{ + "nodes": [{ + "name": "Agricultural 'waste'" + }, { + "name": "Bio-conversion" + }, { + "name": "Liquid" + }, { + "name": "Losses" + }, { + "name": "Solid" + }, { + "name": "Gas" + }, { + "name": "Biofuel imports" + }, { + "name": "Biomass imports" + }, { + "name": "Coal imports" + }, { + "name": "Coal" + }, { + "name": "Coal reserves" + }, { + "name": "District heating" + }, { + "name": "Industry" + }, { + "name": "Heating and cooling - commercial" + }, { + "name": "Heating and cooling - homes" + }, { + "name": "Electricity grid" + }, { + "name": "Over generation / exports" + }, { + "name": "H2 conversion" + }, { + "name": "Road transport" + }, { + "name": "Agriculture" + }, { + "name": "Rail transport" + }, { + "name": "Lighting & appliances - commercial" + }, { + "name": "Lighting & appliances - homes" + }, { + "name": "Gas imports" + }, { + "name": "Ngas" + }, { + "name": "Gas reserves" + }, { + "name": "Thermal generation" + }, { + "name": "Geothermal" + }, { + "name": "H2" + }, { + "name": "Hydro" + }, { + "name": "International shipping" + }, { + "name": "Domestic aviation" + }, { + "name": "International aviation" + }, { + "name": "National navigation" + }, { + "name": "Marine algae" + }, { + "name": "Nuclear" + }, { + "name": "Oil imports" + }, { + "name": "Oil" + }, { + "name": "Oil reserves" + }, { + "name": "Other waste" + }, { + "name": "Pumped heat" + }, { + "name": "Solar PV" + }, { + "name": "Solar Thermal" + }, { + "name": "Solar" + }, { + "name": "Tidal" + }, { + "name": "UK land based bioenergy" + }, { + "name": "Wave" + }, { + "name": "Wind" + }], + "links": [{ + "source": 0, + "target": 1, + "value": 124.729 + }, { + "source": 1, + "target": 2, + "value": 0.597 + }, { + "source": 1, + "target": 3, + "value": 26.862 + }, { + "source": 1, + "target": 4, + "value": 280.322 + }, { + "source": 1, + "target": 5, + "value": 81.144 + }, { + "source": 6, + "target": 2, + "value": 35 + }, { + "source": 7, + "target": 4, + "value": 35 + }, { + "source": 8, + "target": 9, + "value": 11.606 + }, { + "source": 10, + "target": 9, + "value": 63.965 + }, { + "source": 9, + "target": 4, + "value": 75.571 + }, { + "source": 11, + "target": 12, + "value": 10.639 + }, { + "source": 11, + "target": 13, + "value": 22.505 + }, { + "source": 11, + "target": 14, + "value": 46.184 + }, { + "source": 15, + "target": 16, + "value": 104.453 + }, { + "source": 15, + "target": 14, + "value": 113.726 + }, { + "source": 15, + "target": 17, + "value": 27.14 + }, { + "source": 15, + "target": 12, + "value": 342.165 + }, { + "source": 15, + "target": 18, + "value": 37.797 + }, { + "source": 15, + "target": 19, + "value": 4.412 + }, { + "source": 15, + "target": 13, + "value": 40.858 + }, { + "source": 15, + "target": 3, + "value": 56.691 + }, { + "source": 15, + "target": 20, + "value": 7.863 + }, { + "source": 15, + "target": 21, + "value": 90.008 + }, { + "source": 15, + "target": 22, + "value": 93.494 + }, { + "source": 23, + "target": 24, + "value": 40.719 + }, { + "source": 25, + "target": 24, + "value": 82.233 + }, { + "source": 5, + "target": 13, + "value": 0.129 + }, { + "source": 5, + "target": 3, + "value": 1.401 + }, { + "source": 5, + "target": 26, + "value": 151.891 + }, { + "source": 5, + "target": 19, + "value": 2.096 + }, { + "source": 5, + "target": 12, + "value": 48.58 + }, { + "source": 27, + "target": 15, + "value": 7.013 + }, { + "source": 17, + "target": 28, + "value": 20.897 + }, { + "source": 17, + "target": 3, + "value": 6.242 + }, { + "source": 28, + "target": 18, + "value": 20.897 + }, { + "source": 29, + "target": 15, + "value": 6.995 + }, { + "source": 2, + "target": 12, + "value": 121.066 + }, { + "source": 2, + "target": 30, + "value": 128.69 + }, { + "source": 2, + "target": 18, + "value": 135.835 + }, { + "source": 2, + "target": 31, + "value": 14.458 + }, { + "source": 2, + "target": 32, + "value": 206.267 + }, { + "source": 2, + "target": 19, + "value": 3.64 + }, { + "source": 2, + "target": 33, + "value": 33.218 + }, { + "source": 2, + "target": 20, + "value": 4.413 + }, { + "source": 34, + "target": 1, + "value": 4.375 + }, { + "source": 24, + "target": 5, + "value": 122.952 + }, { + "source": 35, + "target": 26, + "value": 839.978 + }, { + "source": 36, + "target": 37, + "value": 504.287 + }, { + "source": 38, + "target": 37, + "value": 107.703 + }, { + "source": 37, + "target": 2, + "value": 611.99 + }, { + "source": 39, + "target": 4, + "value": 56.587 + }, { + "source": 39, + "target": 1, + "value": 77.81 + }, { + "source": 40, + "target": 14, + "value": 193.026 + }, { + "source": 40, + "target": 13, + "value": 70.672 + }, { + "source": 41, + "target": 15, + "value": 59.901 + }, { + "source": 42, + "target": 14, + "value": 19.263 + }, { + "source": 43, + "target": 42, + "value": 19.263 + }, { + "source": 43, + "target": 41, + "value": 59.901 + }, { + "source": 4, + "target": 19, + "value": 0.882 + }, { + "source": 4, + "target": 26, + "value": 400.12 + }, { + "source": 4, + "target": 12, + "value": 46.477 + }, { + "source": 26, + "target": 15, + "value": 525.531 + }, { + "source": 26, + "target": 3, + "value": 787.129 + }, { + "source": 26, + "target": 11, + "value": 79.329 + }, { + "source": 44, + "target": 15, + "value": 9.452 + }, { + "source": 45, + "target": 1, + "value": 182.01 + }, { + "source": 46, + "target": 15, + "value": 19.013 + }, { + "source": 47, + "target": 15, + "value": 289.366 + }] +} http://git-wip-us.apache.org/repos/asf/incubator-senssoft-tap/blob/607675ba/Sankey/csvSankey-v4/exampleData.csv ---------------------------------------------------------------------- diff --git a/Sankey/csvSankey-v4/exampleData.csv b/Sankey/csvSankey-v4/exampleData.csv new file mode 100644 index 0000000..a33e985 --- /dev/null +++ b/Sankey/csvSankey-v4/exampleData.csv @@ -0,0 +1,8 @@ +source,target,value +Barry,Elvis,2 +Frodo,Elvis,2 +Frodo,Sarah,2 +Barry,Alice,2 +Elvis,Sarah,2 +Elvis,Alice,2 +Sarah,Alice,4 \ No newline at end of file