I am trying to make a partitioned sunburst that will have the ability to transition between multiple datasets. So far, all it does is add the datasets together and gives the error path.exit is not a function. I made some changes to the sequence.js based on this blog on how to have updating JSON (http://pothibo.com/2013/09/d3-js-how-to-handle-dynamic-json-data/). However, I still cannot get the sunburst that replaces the original to be in the same position as the original.
Last active
September 15, 2015 19:19
-
-
Save ShepTeck/e79d372b9daabb8d3ccd to your computer and use it in GitHub Desktop.
D3 Sunburst with Changing Datasets
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Fittings|CANADA|DERRICK FITTING CO,137.35 | |
Fittings|CANADA|DERRICK FITTING CO,14.59 | |
Fittings|GULF COAST|JOES FITTING CO,216.44 | |
Fittings|EASTERN|JOES FITTING CO,121.2 | |
Fittings|WESTERN|JANES FITTING CO,1049.12 | |
Fittings|WESTERN|JANES FITTING CO,30.41 | |
Fittings|EASTERN|JOES FITTING CO,1942.38 | |
Fittings|EASTERN|JOES FITTING CO,188.06 | |
Fittings|WESTERN|JANES FITTING CO,210.92 | |
Fittings|WESTERN|DERRICK FITTING CO,2718.9 | |
Flanges|EASTERN|BILBO FLANGE CO,42.26 | |
Flanges|EASTERN|SOLO FALCON CO,1810.42 | |
Flanges|CANADA|BILBO FLANGE CO,471.63 | |
Flanges|CANADA|SOLO FALCON CO,22.93 | |
Flanges|WESTERN|SOLO FALCON CO,2877.55 | |
Flanges|CANADA|LOTS O ENERGY CO,2041.15 | |
Flanges|GULF COAST|LOTS O ENERGY CO,1015.89 | |
Flanges|EASTERN|BILBO FLANGE CO,36.06 | |
Flanges|EASTERN|LOTS O ENERGY CO,106.4 | |
Flanges|EASTERN|SOLO FALCON CO,359.04 | |
Flanges|EASTERN|SOLO FALCON CO,1724.47 | |
Pipe|WESTERN|BILLY D PIPE CO,52352.95 | |
Pipe|GULF COAST|BILLY D PIPE CO,73.5 | |
Pipe|WESTERN|BILLY D PIPE CO,9532.01 | |
Pipe|CANADA|LOTS O ENERGY CO,1272.34 | |
Pipe|GULF COAST|LOTS O ENERGY CO,144.09 | |
Pipe|WESTERN|LOTS O ENERGY CO,2446.5 | |
Pipe|EASTERN|SOLO FALCON CO,734.12 | |
Pipe|WESTERN|SOLO FALCON CO,80 | |
Pipe|EASTERN|SOLO FALCON CO,1534.05 | |
Pipe|EASTERN|SOLO FALCON CO,3790.01 | |
Pipe|EASTERN|SOLO FALCON CO,1504.02 | |
Valves|EASTERN|BIG VALVES CO,221.48 | |
Valves|CANADA|BIG VALVES CO,183.25 | |
Valves|WESTERN|BIG VALVES CO,1760.68 | |
Valves|EASTERN|BIG VALVES CO,585.64 | |
Valves|WESTERN|LOTS O ENERGY CO,759.86 | |
Valves|WESTERN|LOTS O ENERGY CO,9549.6 | |
Valves|WESTERN|LOTS O ENERGY CO,638.93 | |
Valves|WESTERN|LOTS O ENERGY CO,709.45 | |
Valves|EASTERN|SOLO FALCON CO,287.85 | |
Valves|EASTERN|SOLO FALCON CO,401.58 | |
Valves|EASTERN|SOLO FALCON CO,3831.57 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Fittings|EASTERN|JOES FITTING CO,48.1 | |
Fittings|EASTERN|JANES FITTING CO,225.94 | |
Fittings|EASTERN|DERRICK FITTING CO,11.6 | |
Fittings|EASTERN|JOES FITTING CO,44.46 | |
Fittings|EASTERN|JANES FITTING CO,243.4 | |
Fittings|EASTERN|DERRICK FITTING CO,27.56 | |
Fittings|EASTERN|JOES FITTING CO,3376.69 | |
Fittings|EASTERN|JOES FITTING CO,49.98 | |
Fittings|GULF COAST|DERRICK FITTING CO,0 | |
Fittings|WESTERN|JANES FITTING CO,1302.75 | |
Flanges|WESTERN|BILBO FLANGE CO,1195.39 | |
Flanges|WESTERN|BILBO FLANGE CO,434.76 | |
Flanges|WESTERN|SOLO FALCON CO,3603.4 | |
Flanges|GULF COAST|SOLO FALCON CO,239.08 | |
Flanges|GULF COAST|BILBO FLANGE CO,541.34 | |
Flanges|GULF COAST|LOTS O ENERGY CO,636.79 | |
Flanges|EASTERN|SOLO FALCON CO,247.17 | |
Flanges|EASTERN|LOTS O ENERGY CO,48.56 | |
Flanges|EASTERN|BILBO FLANGE CO,2847 | |
Flanges|WESTERN|LOTS O ENERGY CO,1002.35 | |
Flanges|WESTERN|LOTS O ENERGY CO,2418.39 | |
Pipe|WESTERN|SOLO FALCON CO,29402.33 | |
Pipe|WESTERN|SOLO FALCON CO,11636.34 | |
Pipe|WESTERN|BILLY D PIPE CO,55.56 | |
Pipe|GULF COAST|LOTS O ENERGY CO,10357.56 | |
Pipe|GULF COAST|LOTS O ENERGY CO,1952.27 | |
Pipe|GULF COAST|BILLY D PIPE CO,1842.6 | |
Pipe|GULF COAST|SOLO FALCON CO,107.84 | |
Pipe|EASTERN|BILLY D PIPE CO,1794.65 | |
Pipe|EASTERN|SOLO FALCON CO,585.55 | |
Pipe|EASTERN|LOTS O ENERGY CO,479.85 | |
Pipe|EASTERN|LOTS O ENERGY CO,13322.88 | |
Valves|GULF COAST|LOTS O ENERGY CO,75.36 | |
Valves|GULF COAST|LOTS O ENERGY CO,2667.32 | |
Valves|GULF COAST|LOTS O ENERGY CO,1276.62 | |
Valves|GULF COAST|SOLO FALCON CO,5064.04 | |
Valves|GULF COAST|BIG VALVES CO,407.51 | |
Valves|EASTERN|LOTS O ENERGY CO,189.08 | |
Valves|EASTERN|SOLO FALCON CO,392.25 | |
Valves|EASTERN|BIG VALVES CO,772.94 | |
Valves|WESTERN|LOTS O ENERGY CO,105.81 | |
Valves|WESTERN|SOLO FALCON CO,38.92 | |
Valves|WESTERN|BIG VALVES CO,6490.58 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<title>PVF Sales</title> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script> | |
<link rel="stylesheet" type="text/css" | |
href="https://fonts.googleapis.com/css?family=Open+Sans:400,600"> | |
<link rel="stylesheet" type="text/css" href="sequences.css"/> | |
</head> | |
<body> | |
<div> | |
<input name="updateButton" | |
type="button" | |
value="Update" | |
onclick="updateData()" /> | |
</div> | |
<div id="main"> | |
<div id="option"> | |
</div> | |
<div id="sequence"></div> | |
<div id="chart"> | |
<div id="logo"> | |
<p>Logo goes Here </p> | |
<p>PVF Invoiced Sales</p><p>by Region and Customer</p><p>for Accounting YTD</p> | |
</div> | |
<div id="explanation" style="visibility: hidden;"> | |
<span id="percentage"></span><br/> | |
</div> | |
</div> | |
</div> | |
<div id="sidebar"> | |
<!-- <input type="checkbox" id="togglelegend"> Legend<br/> ---> | |
<!-- <div id="legend" style="visibility: hidden;"></div> --> | |
<div style="color: #fff"><br> Legend</br></div> | |
<div id="legend" ></div> | |
<div id="legendSubTitle" style="visibility: hidden;" > | |
<br>PVF Invoiced Sales</br> | |
<br>by Region and Customer</br> | |
<br>for Accounting YTD</br> | |
</div> | |
</div> | |
<script type="text/javascript" src="sequences.js"></script> | |
<script type="text/javascript"> | |
// attempt to make this fix a iframe | |
d3.select("#main").style("height", "700px"); | |
</script> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
body { | |
font-family: 'Open Sans', sans-serif; | |
font-size: 12px; | |
font-weight: 400; | |
background-color: #1c1c1c; | |
width: 960px; | |
height: 700px; | |
margin-top: 10px; | |
} | |
#main { | |
float: left; | |
width: 790px; | |
} | |
#sidebar { | |
float: right; | |
width: 100px; | |
} | |
#sequence { | |
width: 850px; | |
height: 70px; | |
} | |
#legend { | |
padding: 10px 0 0 3px; | |
} | |
#legendSubTitle { | |
height: 700px; | |
width: 210px; | |
text-align: center; | |
z-index: -1; | |
color: #fff; | |
} | |
#sequence text, #legend text { | |
font-weight: 600; | |
fill: #fff; | |
} | |
#chart { | |
position: relative; | |
} | |
#chart path { | |
stroke: #434343; | |
stroke-width:"6"; | |
stroke-opacity:"0.3"; | |
} | |
#explanation { | |
position: absolute; | |
top: 260px; | |
left: 305px; | |
width: 140px; | |
text-align: center; | |
color: #fff; | |
z-index: -1; | |
} | |
#logo { | |
position: absolute; | |
top: 230px; | |
left: 305px; | |
width: 140px; | |
text-align: center; | |
color: #fff; | |
z-index: -1; | |
font-size: 1.25em; | |
} | |
#percentage { | |
font-size: 1.5em; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Dimensions of sunburst. | |
var width = 750; | |
var height = 600; | |
var radius = Math.min(width, height) / 2; | |
// Breadcrumb dimensions: width, height, spacing, width of tip/tail. | |
var b = { | |
w: 225, h: 30, s: 3, t: 10 | |
}; | |
// Mapping of step names to colors. | |
var colors = { | |
/* Orig PVF colors : | |
"Valves": "#A83B22", | |
"Pipe": "#227522", | |
"Flanges": "#F37722", | |
"Fittings": "#38BD83" | |
*/ | |
//New Medium: | |
"Valves": "#A83B22", | |
"Pipe": "#227522", | |
"Flanges": "#F37722", | |
"Fittings": "#38BD83" | |
}; | |
// Total size of all segments; we set this later, after loading the data. | |
var totalSize = 0; | |
var vis = d3.select("#chart").append("svg:svg") | |
.attr("width", width) | |
.attr("height", height) | |
.append("svg:g") | |
.attr("id", "container") | |
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")") | |
var partition = d3.layout.partition() | |
.size([2 * Math.PI, radius * radius]) | |
.value(function(d) { return d.size; }); | |
var arc = d3.svg.arc() | |
.startAngle(function(d) { return d.x; }) | |
.endAngle(function(d) { return d.x + d.dx; }) | |
.innerRadius(function(d) { return Math.sqrt(d.y); }) | |
.outerRadius(function(d) { return Math.sqrt(d.y + d.dy); }); | |
d3.text("data/data1.txt", function(text) { | |
csv = d3.csv.parseRows(text); | |
json = buildHierarchy(csv); | |
createVisualization(json); | |
}); | |
// Main function to draw and set up the visualization, once we have the data. | |
function createVisualization(json) { | |
// Basic setup of page elements. | |
initializeBreadcrumbTrail(); | |
//drawLegend(); | |
d3.select("#legend").style("visibility",""); | |
/*d3.select("#togglelegend").on("click", toggleLegend);*/ | |
// Bounding circle underneath the sunburst, to make it easier to detect | |
// when the mouse leaves the parent g. | |
vis.append("svg:circle") | |
.attr("r", radius) | |
.style("opacity", 0); | |
// For efficiency, filter nodes to keep only those large enough to see. | |
var nodes = partition.nodes(json) | |
.filter(function(d) { | |
return (d.dx > 0.013); // 0.005 radians = 0.29 degrees ; .019 radians = 1.09 degrees | |
}); | |
var path = vis.data([json]).selectAll("path") | |
.data(nodes) | |
.enter().append("svg:path") | |
.attr("display", function(d) { return d.depth ? null : "none"; }) | |
.attr("d", arc) | |
.attr("fill-rule", "evenodd") | |
.style("fill", function(d) { return (d.parent && d.depth > 1) ? ((d.depth == 2) ? d3.rgb(colors[d.parent.name]).brighter(0.4) : d3.rgb(colors[d.parent.parent.name]).brighter(0.8)) : colors[d.name]; }) | |
.style("opacity", 1) | |
.on("mouseover", mouseover); | |
// Add the mouseleave handler to the bounding circle. | |
d3.select("#container").on("mouseleave", mouseleave); | |
// Get total size of the tree = value of root node from partition. | |
totalSize = path.node().__data__.value; | |
}; | |
// Fade all but the current sequence, and show it in the breadcrumb trail. | |
function mouseover(d) { | |
var percentage = (100 * d.value / totalSize).toPrecision(3); | |
var percentageString = percentage + "%"; | |
if (percentage < 0.1) { | |
percentageString = "< 0.1%"; | |
} | |
Number.prototype.formatMoney = function(c, d, t){ | |
var n = this, | |
c = isNaN(c = Math.abs(c)) ? 2 : c, | |
d = d == undefined ? "." : d, | |
t = t == undefined ? "," : t, | |
s = n < 0 ? "-" : "", | |
i = parseInt(n = Math.abs(+n || 0).toFixed(c)) + "", | |
j = (j = i.length) > 3 ? j % 3 : 0; | |
return s + (j ? i.substr(0, j) + t : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + t) + (c ? d + Math.abs(n - i).toFixed(c).slice(2) : ""); | |
}; | |
var salesString = "$" + d.value.formatMoney(2, '.', ',') + " sales"; | |
if (d.value == 1) { | |
salesString = "1 total sales"; | |
} | |
d3.select("#percentage") | |
.text(salesString + " (" + percentageString + ") of invoiced sales - " + d.name); | |
d3.select("#explanation") | |
.style("visibility", ""); | |
d3.select("#legendSubTitle") | |
.style("visibility", ""); | |
d3.select("#logo") | |
.transition() | |
.duration(1000) | |
.style("visibility", "hidden"); | |
var sequenceArray = getAncestors(d); | |
updateBreadcrumbs(sequenceArray, percentageString, salesString); | |
// Fade all the segments. | |
d3.selectAll("path") | |
.style("opacity", 0.65); | |
// Then highlight only those that are an ancestor of the current segment. | |
vis.selectAll("path") | |
.filter(function(node) { | |
return (sequenceArray.indexOf(node) >= 0); | |
}) | |
.style("opacity", 1); | |
} | |
// Restore everything to full opacity when moving off the visualization. | |
function mouseleave(d) { | |
// Hide the breadcrumb trail | |
d3.select("#trail") | |
.style("visibility", "hidden"); | |
/*.style("visibility", ""); test to turn off visibility*/ | |
// Deactivate all segments during transition. | |
d3.selectAll("path").on("mouseover", null); | |
// Transition each segment to full opacity and then reactivate it. | |
d3.selectAll("path") | |
.transition() | |
.duration(1000) | |
.style("opacity", 1) | |
.each("end", function() { | |
d3.select(this).on("mouseover", mouseover); | |
}); | |
d3.select("#explanation") | |
.transition() | |
.duration(1000) | |
.style("visibility", "hidden"); | |
d3.select("#legendSubTitle") | |
.transition() | |
.duration(1000) | |
.style("visibility", "hidden"); | |
d3.select("#logo") | |
.style("visibility", ""); | |
} | |
// Given a node in a partition layout, return an array of all of its ancestor | |
// nodes, highest first, but excluding the root. | |
function getAncestors(node) { | |
var path = []; | |
var current = node; | |
while (current.parent) { | |
path.unshift(current); | |
current = current.parent; | |
} | |
return path; | |
} | |
function initializeBreadcrumbTrail() { | |
// Add the svg area. | |
var trail = d3.select("#sequence").append("svg:svg") | |
.attr("width", width + "#endlabel".length + 60 ) | |
.attr("height", 50) | |
.attr("id", "trail"); | |
// Add the label at the end, for the percentage. | |
trail.append("svg:text") | |
.attr("id", "endlabel") | |
.style("fill", "#fff"); | |
} | |
// Generate a string that describes the points of a breadcrumb polygon. | |
function breadcrumbPoints(d, i) { | |
var points = []; | |
points.push("0,0"); | |
points.push(b.w + ",0"); | |
points.push(b.w + b.t + "," + (b.h / 2)); | |
points.push(b.w + "," + b.h); | |
points.push("0," + b.h); | |
if (i > 0) { // Leftmost breadcrumb; don't include 6th vertex. | |
points.push(b.t + "," + (b.h / 2)); | |
} | |
return points.join(" "); | |
} | |
// Update the breadcrumb trail to show the current sequence and percentage. | |
function updateBreadcrumbs(nodeArray, percentageString, salesString) { | |
// Data join; key function combines name and depth (= position in sequence). | |
var g = d3.select("#trail") | |
.selectAll("g") | |
.data(nodeArray, function(d) { return d.name + d.depth; }); | |
// Add breadcrumb and label for entering nodes. | |
var entering = g.enter().append("svg:g"); | |
entering.append("svg:polygon") | |
.attr("points", breadcrumbPoints) | |
.style("fill", function(d) { return (d.parent && d.depth > 1) ? ((d.depth == 2) ? d3.rgb(colors[d.parent.name]).brighter(0.4) : d3.rgb(colors[d.parent.parent.name]).brighter(0.8)) : colors[d.name]; }); | |
entering.append("svg:text") | |
.attr("x", (b.w + b.t) / 2) | |
.attr("y", b.h / 2) | |
.attr("dy", "0.35em") | |
.attr("text-anchor", "middle") | |
.text(function(d) { return d.name;}); | |
// Set position for entering and updating nodes. | |
g.attr("transform", function(d, i) { | |
return "translate(" + i * (b.w + b.s) + ", 0)"; | |
}); | |
// Remove exiting nodes. | |
g.exit().remove(); | |
// Now move and update the percentage at the end. | |
d3.select("#trail").select("#endlabel") | |
.attr("x", (nodeArray.length + .30 ) * (b.w + b.s)) | |
.attr("y", b.h / 2) | |
.attr("dy", "0.35em") | |
.attr("text-anchor", "middle") | |
.text(salesString); | |
// Make the breadcrumb trail visible, if it's hidden. | |
d3.select("#trail") | |
.style("visibility", ""); | |
} | |
drawLegend(); | |
function drawLegend() { | |
// Dimensions of legend item: width, height, spacing, radius of rounded rect. | |
var li = { | |
w: 190, h: 30, s: 3, r: 3 | |
}; | |
var legend = d3.select("#legend").append("svg:svg") | |
.attr("width", li.w) | |
.attr("height", d3.keys(colors).length * (li.h + li.s)); | |
var g = legend.selectAll("g") | |
.data(d3.entries(colors)) | |
.enter().append("svg:g") | |
.attr("transform", function(d, i) { | |
return "translate(0," + i * (li.h + li.s) + ")"; | |
}); | |
g.append("svg:rect") | |
.attr("rx", li.r) | |
.attr("ry", li.r) | |
.attr("width", li.w) | |
.attr("height", li.h) | |
.style("fill", function(d) { return d.value; }); | |
g.append("svg:text") | |
.attr("x", li.w / 2) | |
.attr("y", li.h / 2) | |
.attr("dy", "0.35em") | |
.attr("text-anchor", "middle") | |
.text(function(d) { return d.key; }) | |
} | |
function updateData(){ | |
setTimeout(function() { | |
// Dimensions of sunburst. | |
var width = 750; | |
var height = 600; | |
var radius = Math.min(width, height) / 2; | |
var x = d3.scale.linear() | |
.range([0, 2 * Math.PI]); | |
var y = d3.scale.sqrt() | |
.range([0, radius]); | |
// Breadcrumb dimensions: width, height, spacing, width of tip/tail. | |
var b = { | |
w: 225, h: 30, s: 3, t: 10 | |
}; | |
// Mapping of step names to colors. | |
var colors = { | |
//New Medium: | |
"Valves": "#A83B22", | |
"Pipe": "#227522", | |
"Flanges": "#F37722", | |
"Fittings": "#38BD83" | |
}; | |
// Total size of all segments; we set this later, after loading the data. | |
var totalSize = 0; | |
var vis = d3.select("#chart").append("svg:svg") | |
.attr("width", width) | |
.attr("height", height) | |
.append("svg:g") | |
.attr("id", "container") | |
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")") | |
var partition = d3.layout.partition() | |
.size([2 * Math.PI, radius * radius]) | |
.value(function(d) { return d.size; }); | |
var arc = d3.svg.arc() | |
.startAngle(function(d) { return d.x; }) | |
.endAngle(function(d) { return d.x + d.dx; }) | |
.innerRadius(function(d) { return Math.sqrt(d.y); }) | |
.outerRadius(function(d) { return Math.sqrt(d.y + d.dy); }); | |
d3.text("data/data2.txt", function(text) { | |
csv = d3.csv.parseRows(text); | |
jsonNew = buildHierarchy(csv); | |
createVisualization2(jsonNew); | |
}); | |
var update_sel1 = d3.selectAll("vis").data(json) | |
update_sel1.exit() | |
.remove() | |
var update_sel2 = d3.selectAll("nodes").data(json) | |
update_sel2.exit() | |
.remove() | |
var update_sel3 = d3.selectAll("path").data(json) | |
update_sel3.exit() | |
.remove() | |
var update_sel4 = d3.selectAll("arc").data(json) | |
update_sel4.exit() | |
.remove() | |
var update_sel5 = d3.selectAll("partition").data(json) | |
update_sel5.exit() | |
.remove() | |
function createVisualization2(json) { | |
// Basic setup of page elements. | |
initializeBreadcrumbTrail(); | |
//drawLegend(); | |
d3.select("#legend").style("visibility",""); | |
/*d3.select("#togglelegend").on("click", toggleLegend);*/ | |
// Bounding circle underneath the sunburst, to make it easier to detect | |
// when the mouse leaves the parent g. | |
vis.append("svg:circle") | |
.attr("r", radius) | |
.style("opacity", 0); | |
// For efficiency, filter nodes to keep only those large enough to see. | |
var nodes = partition.nodes(json) | |
.filter(function(d) { | |
return (d.dx > 0.013); // 0.005 radians = 0.29 degrees ; .019 radians = 1.09 degrees | |
}); | |
var path = vis.data([json]).selectAll("path") | |
.data(nodes) | |
.enter().append("svg:path") | |
.attr("display", function(d) { return d.depth ? null : "none"; }) | |
.attr("d", arc) | |
.attr("fill-rule", "evenodd") | |
.style("fill", function(d) { return (d.parent && d.depth > 1) ? ((d.depth == 2) ? d3.rgb(colors[d.parent.name]).brighter(0.4) : d3.rgb(colors[d.parent.parent.name]).brighter(0.8)) : colors[d.name]; }) | |
.style("opacity", 1) | |
.on("mouseover", mouseover); | |
// Add the mouseleave handler to the bounding circle. | |
d3.select("#container").on("mouseleave", mouseleave); | |
// Get total size of the tree = value of root node from partition. | |
totalSize = path.node().__data__.value; | |
}; | |
}, 1000); | |
} | |
// Take a 2-column CSV and transform it into a hierarchical structure suitable | |
// for a partition layout. The first column is a sequence of step names, from | |
// root to leaf, separated by hyphens. The second column is a count of how | |
// often that sequence occurred. | |
function buildHierarchy(csv) { | |
var root = {"name": "root", "children": []}; | |
for (var i = 0; i < csv.length; i++) { | |
var sequence = csv[i][0]; | |
var size = +csv[i][1]; | |
if (isNaN(size)) { // e.g. if this is a header row | |
continue; | |
} | |
var parts = sequence.split("|"); | |
var currentNode = root; | |
for (var j = 0; j < parts.length; j++) { | |
var children = currentNode["children"]; | |
var nodeName = parts[j]; | |
var childNode; | |
if (j + 1 < parts.length) { | |
// Not yet at the end of the sequence; move down the tree. | |
var foundChild = false; | |
for (var k = 0; k < children.length; k++) { | |
if (children[k]["name"] == nodeName) { | |
childNode = children[k]; | |
foundChild = true; | |
break; | |
} | |
} | |
// If we don't already have a child node for this branch, create it. | |
if (!foundChild) { | |
childNode = {"name": nodeName, "children": []}; | |
children.push(childNode); | |
} | |
currentNode = childNode; | |
} else { | |
// Reached the end of the sequence; create a leaf node. | |
childNode = {"name": nodeName, "size": size}; | |
children.push(childNode); | |
} | |
} | |
} | |
//console.log(root); | |
return root; | |
}; | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment