I am making a Sankey Diagram to show mass flows (chemical engineering stuff).
An older .json file with fewer nodes, works perfectly with the same code (below), but if I load in a .json file with more nodes it doesn't show up, giving me a "Uncaught TypeError: Cannot read property 'nodes' of undefined" error. It further says: (anonymous function) @ Sankey_C_11sept15.htm:87 t @ d3.min.js:1 u @ d3.min.js:1 I need these files to work without an internet connection.
The older .json file has 18 nodes while the newer one has 32 nodes, with more connections between them. Otherwise they are identical; I'm confident it's not a syntax error. Another possible reason it doesn't show up is that I exceed the allowed width or something to fit all the connections in. I'm not sure how to change that though (I'm very noob at this).
code:
<!DOCTYPE html>
<meta charset="utf-8">
<title>SANKEY_C 15sept15</title>
<style>
.node rect {
cursor: move;
fill-opacity: .9;
shape-rendering: crispEdges;
}
.node text {
pointer-events: none;
text-shadow: 0 1px 0 #fff;
}
.link {
fill: none;
stroke: #000;
stroke-opacity: .2;
}
.link:hover {
stroke-opacity: .5;
}
</style>
<header>
<a href="http://localhost:8888/">project d3</a>
<span class="date">15 September 2015</span>
</header>
<h1>Wastewater Biorefinery Sankey diagram: Carbon flows</h1>
<p>From formatted JSON, using Malcolm MacLean's book. Not 100% appropriate values yet.<br>
<br>
To Do: Order and distribute streams to load correctly automatically.<br>
To Do: Write macro to export values from .xls sheet into csv and update .htm file with a click of a button - better user interface.
<br>
To change web thingie to local host on UBUNTU, type into terminal:<br>
cd ~/Desktop/project_d3/sankey <br>
then, type <br>
python -m SimpleHTTPServer 8888 &<br>
Error note: this still requires a refresh and choosing the file from the webpage directory. Annoying.<br>
</p>
<body>
<p id="chart">
<script src="d3.min.js"></script>
<script src="sankey.js"></script>
<script> // These are the files you draw the design from - they have to be in the folder. These are not the data (mass flow) files.
var units = "kg C/day";
var margin = {top: 10, right: 10, bottom: 10, left: 10},
width = 1200 - margin.left - margin.right,
height = 600 - margin.top - margin.bottom;
var formatNumber = d3.format(",.0f"), // zero decimal places
format = function(d) { return formatNumber(d) + " " + units; },
color = d3.scale.category20();
// append the svg canvas to the page
var svg = d3.select("#chart").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")");
// Set the sankey diagram properties
var sankey = d3.sankey()
.nodeWidth(36)
.nodePadding(40)
.size([width, height]);
var path = sankey.link();
// load the data (these are your unit processes.)
// TO DO: Write a macro that can create this file with the correct syntax from the excel sheet.)
d3.json("Sankey-formatted_11sept15.json", function(error, graph) { // Sankey_C_flows_6feb15.json is the old file that works
sankey
.nodes(graph.nodes)
.links(graph.links)
.layout(32);
// add in the links
var link = svg.append("g").selectAll(".link")
.data(graph.links)
.enter().append("path")
.attr("class", "link")
.attr("d", path)
.style("stroke-width", function(d) { return Math.max(1, d.dy); })
.sort(function(a, b) { return b.dy - a.dy; });
// add the link titles
link.append("title")
.text(function(d) {
return d.source.name + " → " +
d.target.name + "\n" + format(d.value); });
// add in the nodes
var node = svg.append("g").selectAll(".node")
.data(graph.nodes)
.enter().append("g")
.attr("class", "node")
.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")"; })
.call(d3.behavior.drag()
.origin(function(d) { return d; })
.on("dragstart", function() {
this.parentNode.appendChild(this); })
.on("drag", dragmove));
// add the rectangles for the nodes
node.append("rect")
.attr("height", function(d) { return d.dy; })
.attr("width", sankey.nodeWidth())
.style("fill", function(d) {
return d.color = color(d.name.replace(/ .*/, "")); })
.style("stroke", function(d) {
return d3.rgb(d.color).darker(2); })
.append("title")
.text(function(d) {
return d.name + "\n" + format(d.value); });
// add in the title for the nodes
node.append("text")
.attr("x", -6)
.attr("y", function(d) { return d.dy / 2; })
.attr("dy", ".35em")
.attr("text-anchor", "end")
.attr("transform", null)
.text(function(d) { return d.name; })
.filter(function(d) { return d.x < width / 2; })
.attr("x", 6 + sankey.nodeWidth())
.attr("text-anchor", "start");
// the function for moving the nodes
function dragmove(d) {
d3.select(this).attr("transform",
"translate(" + d.x + "," + (
d.y = Math.max(0, Math.min(height - d.dy, d3.event.y))
) + ")");
sankey.relayout();
link.attr("d", path);
}
});
</script>
</body>
</html>
The 'broken' .json file:
{
"nodes":[
{"node":0,"name":"A1: Raw, unsettled wastewater in"},
{"node":1,"name":"A2: Agricultural waste in"},
{"node":2,"name":"A3: Forestry waste in"},
{"node":3,"name":"A4: Municipal solid waste in"},
{"node":4,"name":"1. Separator (PST)"},
{"node":5,"name":"A. Splitter 1"},
{"node":6,"name":"2. Bacterial Bioreactor"},
{"node":7,"name":"B. Splitter 2"},
{"node":8,"name":"3. Separator 2"},
{"node":9,"name":"4. Algal bioreactor"},
{"node":10,"name":"C. Splitter 3"},
{"node":11,"name":"5. Separator 3"},
{"node":12,"name":"6. Macrophyte Bioreactor"},
{"node":13,"name":"7. Separator 4"},
{"node":14,"name":"8. Solids Bioreactor"},
{"node":15,"name":"9. Separator 5"},
{"node":16,"name":"G. Compliant effluent"},
{"node":17,"name":"I. Bacterial Product"},
{"node":18,"name":"J. Algal Oil"},
{"node":19,"name":"K. Algal bioproducts"},
{"node":20,"name":"L. Algal biomass"},
{"node":21,"name":"N. Cellulosic fibre"},
{"node":22,"name":"O. Cellulosic biomass"},
{"node":23,"name":"P. Fungal biomass products"},
{"node":24,"name":"Q. Compost"},
{"node":25,"name":"I2. Lost through DSP of bacterial product"},
{"node":26,"name":"J2. Lost through DSP of algal products"},
{"node":27,"name":"N2. Lost through DSP of macrophyte products"},
{"node":28,"name":"P2. Lost through DSP of fungal product"},
{"node":29,"name":"C4. CO2 emission (Bacterial)"},
{"node":30,"name":"E4. CO2 uptake (Algal)"},
{"node":31,"name":"M1. CO2 uptake (Macrophyte)"},
{"node":32,"name":"C4. CO2 emission (Fungal)"},
],
"links":[
{"source":0,"target":4,"value":511.098591549296},
{"source":1,"target":4,"value":28.169014084507},
{"source":2,"target":4,"value":63.3802816901409},
{"source":3,"target":4,"value":112.676056338028},
{"source":4,"target":5,"value":711.747323943662},
{"source":5,"target":6,"value":640.572591549296},
{"source":6,"target":7,"value":509.627428006126},
{"source":7,"target":6,"value":50.9627428006126},
{"source":7,"target":8,"value":458.664685205514},
{"source":8,"target":14,"value":179.678358787707},
{"source":8,"target":9,"value":83.2677858626846},
{"source":5,"target":9,"value":71.1747323943662},
{"source":9,"target":10,"value":188.740576962088},
{"source":10,"target":9,"value":18.8740576962088},
{"source":10,"target":11,"value":169.86651926588},
{"source":11,"target":12,"value":57.4187455906397},
{"source":12,"target":13,"value":62.5864326937972},
{"source":13,"target":14,"value":1.69385299492387},
{"source":4,"target":14,"value":3.57661971830986},
{"source":14,"target":15,"value":345.681595177502},
{"source":8,"target":17,"value":146.174970350742},
{"source":11,"target":18,"value":47.3549068819831},
{"source":11,"target":19,"value":1.19362399882216},
{"source":11,"target":20,"value":47.7163991674996},
{"source":13,"target":21,"value":25.7465655228428},
{"source":13,"target":22,"value":6.4366413807107},
{"source":15,"target":23,"value":65.9937590793412},
{"source":15,"target":24,"value":257.689916405047},
{"source":13,"target":16,"value":28.7093727953198},
{"source":6,"target":29,"value":181.906686103341},
{"source":30,"target":9,"value":15.4234825591918},
{"source":31,"target":12,"value":5.16768710315757},
{"source":14,"target":32,"value":282.830396054319},
{"source":8,"target":25,"value":48.7249901169141},
{"source":11,"target":26,"value":16.1828436269351},
{"source":13,"target":27,"value":0},
{"source":15,"target":28,"value":21.9979196931137},
]}
The 'good' .json file:
{
"nodes":[
{"node":0,"name":"WW in"},
{"node":1,"name":"PST"},
{"node":2,"name":"Bacterial Bioreactor"},
{"node":3,"name":"Bact. Separator"},
{"node":4,"name":"Algal bioreactor"},
{"node":5,"name":"Alg. Separator"},
{"node":6,"name":"Macrophyte Bioreactor"},
{"node":7,"name":"Mac. Separator"},
{"node":8,"name":"Solids Bioreactor"},
{"node":9,"name":"Total carbon out"},
{"node":10,"name":"Bacterial Product"},
{"node":11,"name":"Algal Oil"},
{"node":12,"name":"Algal bioproducts"},
{"node":13,"name":"Algal biomass"},
{"node":14,"name":"Compliant effluent"},
{"node":15,"name":"Cellulosic fibre"},
{"node":16,"name":"Cellulosic biomass"},
{"node":17,"name":"Fungal biomass products"},
{"node":18,"name":"Compost"}
],
"links":[
{"source":0,"target":1,"value":14697},
{"source":1,"target":2,"value":13954},
{"source":1,"target":8,"value":743},
{"source":2,"target":3,"value":13954},
{"source":3,"target":10,"value":4186},
{"source":3,"target":4,"value":5623},
{"source":3,"target":8,"value":4144},
{"source":4,"target":5,"value":5623},
{"source":5,"target":6,"value":2811},
{"source":5,"target":11,"value":421},
{"source":5,"target":12,"value":56},
{"source":5,"target":13,"value":2333},
{"source":6,"target":7,"value":2505},
{"source":6,"target":14,"value":281},
{"source":6,"target":8,"value":306},
{"source":7,"target":15,"value":250},
{"source":7,"target":16,"value":2254},
{"source":8,"target":17,"value":1038},
{"source":8,"target":18,"value":4155}
]}