You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@senssoft.apache.org by ms...@apache.org on 2017/09/05 18:08:09 UTC

[3/3] incubator-senssoft-tap git commit: Added modified d3-sankey.js library to repository. Now can handle alignment changes.

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 <rb...@draper.com>
Authored: Fri Sep 1 13:30:09 2017 -0400
Committer: Ryan-Brill <rb...@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