1

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}
]}
indiebio
  • 11
  • 3
  • D3 doesn't impose any such limits. It's almost certainly a problem with your data. – Lars Kotthoff Sep 15 '15 at 13:16
  • I agree with @LarsKotthoff. You'll need to show us your complete data to troubleshoot further. Also, try loading a *non-minified* version of d3 so you can see where it is really breaking. – Mark Sep 15 '15 at 15:07
  • Can you attach your json files too (both "good" and "bad" one)? – VividD Oct 05 '15 at 05:14
  • Thanks all, apologies for the delay. Both .json versions now included. Mark, can you send me a link explaining the non-minified version of d3? (I found this: http://alignedleft.com/tutorials/d3/setup - yes?) Can one put both these versions in the same folder and use them interchangeably? (By editing the "" section?) – indiebio Oct 11 '15 at 11:09

1 Answers1

0

'I need these files to work without an internet connection.' D3 requires a web server to 'serve' the json files or you will receive undefined errors, in short it won't work. Test it...Swap out your json file for something else, like this which works...https://bost.ocks.org/mike/sankey/energy.json and then test your script. If if works then the problem is in your data. If you are trying to run this from your local hard drive it won't work. In that case either deploy the files to a shared hosting account, or download your web server of choice, setup on your machine and then test it. I personally use Microsoft's Visual Studio Web Developer express which is free and includes a web server. Hope that helps.

Rob
  • 1,226
  • 3
  • 23
  • 41