EVOLUTION-MANAGER
Edit File: sequence_sunburst.js
// Wrapper function function do_sequence_sunburst(circle_name,sequence_name,refresh,update_url,url_params,title,units) { var graph = new SequenceSunburst(circle_name,sequence_name,refresh,update_url,url_params,title,units); graph.setInterval(window.setInterval(function(){graph.update();}, refresh)); // Return new class instance, with return [graph]; } function SequenceSunburst(circle_name,sequence_name,refresh,update_url,url_params,title,units) { // Add object properties like this this.circle_name = circle_name; this.sequence_name = sequence_name; this.update_url = update_url; this.url_params = url_params; this.units = units; this.refresh = refresh; this.sunburstInterval; var oldPieData = []; var filteredPieData = []; var rsp = create_sequence_sunburst(circle_name,sequence_name,title,units); var color = rsp[0]; var partition = rsp[1]; var totalSize = rsp[2]; var arc = rsp[3]; var arc_group = rsp[4]; var trail = rsp[5]; var whiteCircle = rsp[6]; var totalLabel = rsp[7]; var totalValue = rsp[8]; var totalUnits = rsp[9]; var radius = rsp[10]; var width = rsp[11]; var height = rsp[12]; var b = rsp[13]; var last_process = ""; var last_byte = 0; var substring_limit = 8; // to run each time data is generated this.update = function () { $.ajax({ type: 'GET', url: this.update_url, data: this.url_params, success: function(content) { update_sequence_sunburst(jQuery.parseJSON(content)); }, error: function(content) { console.log("error"); } }); } /////////////////////////////////////////////////////////// // STREAKER CONNECTION //////////////////////////////////// /////////////////////////////////////////////////////////// // Needed to draw the pie immediately this.update(); // var updateInterval = window.setInterval(update, refresh); /////////////////////////////////////////////////////////// // UPDATE FUNCTIONS //////////////////////////////////// /////////////////////////////////////////////////////////// this.flashUpdate = function (start,end) { arc_group.selectAll("path").style("opacity", start) .transition().duration(200).style("opacity", end); } function update_sequence_sunburst(data) { streakerDataAdded = data; // console.log(data); oldPieData = filteredPieData; pieData = partition.nodes(streakerDataAdded); filteredPieData = pieData.filter(function(d) { return (d.dx > 0.005); // 0.005 radians = 0.29 degrees }); if((filteredPieData.length > 0) && (oldPieData.length > 0)) { //REMOVE PLACEHOLDER CIRCLE arc_group.selectAll("circle").remove(); arc_group.selectAll("path").remove(); // alert("Update"); } paths = arc_group.selectAll("path").data(filteredPieData); paths.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 color(d.name+d.id); }) .style("opacity", 1) .on("mouseover", mouseover) .on("dblclick",function(d) {if(d.url) window.location.href = d.url; }); // Add the mouseleave handler to the bounding circle. d3.select("#container"+circle_name).on("mouseleave", mouseleave); // Get total size of the tree = value of root node from partition. totalSize = paths.node().__data__.value; filteredPieData.forEach(function(d) { if ((last_process.localeCompare(d.name) == 0) && (d.name != "")){ var data = bytesToVolumeAndLabel(d.value); var value = data[0] if (last_byte < d.value) { value = data[0]+ ' \uf062'; }else if (last_byte > d.value) { value = data[0]+ ' \uf063'; } else { value = data[0]+ ' \uf068'; } var name = d.name.substring(0,substring_limit); if (d.name.length > substring_limit) {name = name + "..";} totalValue.text(value); totalLabel.text(name); totalUnits.text(data[1]); }; }); } /////////////////////////////////////////////////////////// // UTILS FUNCTIONS //////////////////////////////////// /////////////////////////////////////////////////////////// function mouseover(d) { var percentage = (100 * d.value / totalSize).toPrecision(3); var percentageString = percentage + "%"; if (percentage < 0.1) { percentageString = "< 0.1%"; } var data = bytesToVolumeAndLabel(d.value); totalValue.text(data[0]); totalLabel.text(d.name); totalUnits.text(data[1]); last_process = d.name; last_byte = d.value; var sequenceArray = getAncestors(d); updateBreadcrumbs(sequenceArray, percentageString); // Fade all the segments. arc_group.selectAll("path") .style("opacity", 0.3); // Then highlight only those that are an ancestor of the current segment. arc_group.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 trail.style("visibility", "hidden"); // Deactivate all segments during transition. arc_group.selectAll("path").on("mouseover", null); // Transition each segment to full opacity and then reactivate it. arc_group.selectAll("path") .transition() .duration(500) .style("opacity", 1) .each("end", function() { d3.select(this).on("mouseover", mouseover); }); }; // 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; } // Initialize the Breadcrumb as default function initializeBreadcrumbTrail(circle_name,sequence_name) { // Add the svg area. var trail = d3.select("#"+sequence_name).append("svg:svg") .attr("width", width) .attr("height", 50) .attr("id", "trail"); // Add the label at the end, for the percentage. trail.append("svg:text") .attr("id", "endlabel") .style("fill", "#000"); return trail; } // 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) { // Data join; key function combines name and depth (= position in sequence). var g = 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 color(d.name+d.id); }); 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) { var name = d.name.substring(0,substring_limit); if (d.name.length > substring_limit) {name = name + "..";} return (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. trail.select("#endlabel") .attr("x", (nodeArray.length + 0.5) * (b.w + b.s)) .attr("y", b.h / 2) .attr("dy", "0.35em") .attr("text-anchor", "middle") .text(percentageString); // Make the breadcrumb trail visible, if it's hidden. trail.style("visibility", ""); } /////////////////////////////////////////////////////////// // INIT FUNCTIONS //////////////////////////////////// /////////////////////////////////////////////////////////// function create_sequence_sunburst(circle_name, sequence_name,title,units) { // Dimensions of sunburst. var width = 600; var height = 280; var radius = 120; // Total size of all segments; we set this later, after loading the data. var totalSize = 0; // Breadcrumb dimensions: width, height, spacing, width of tip/tail. var b = { w: 60, h: 25, s: 3, t: 10 }; //D3 helper function to create colors from an ordinal scale var color = d3.scale.category20c(); var partition = d3.layout.partition() .size([2 * Math.PI, radius * radius]) .value(function(d) { return d.size; }); var totalSize = 0; //D3 helper function to draw arcs, populates parameter "d" in path object 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); }); var vis = d3.select("#"+circle_name).append("svg:svg") .attr("width", width) .attr("height", height); var arc_group = vis.append("svg:g") .attr("id", "container"+circle_name) .attr("transform", "translate(" + (width / 2) + "," + (height / 2) + ")"); // Basic setup of page elements. var trail = initializeBreadcrumbTrail(circle_name,sequence_name,width); var whiteCircle = arc_group.append("svg:circle") .attr("fill", "white") .attr("r", radius); // LABEL totalLabel = arc_group.append("svg:text") .attr("class", "label_sunburst") .attr("dy", -25) .attr("text-anchor", "middle") .attr('font-family', 'FontAwesome') .text(""); //PERCENT totalValue = arc_group.append("svg:text") .attr("class", "total") .attr("dy", 7) .attr("text-anchor", "middle") .attr('font-family', 'FontAwesome') .text(""); //UNITS LABEL totalUnits = arc_group.append("svg:text") .attr("class", "units") .attr("dy",30) .attr("text-anchor", "middle") .text(""); return([color, partition, totalSize, arc, arc_group, trail, whiteCircle, totalLabel, totalValue, totalUnits, radius,width,height,b]); } //End function create_sequence_sunburst this.resetCentralCirleText = function (){ totalValue.text(" "); totalLabel.text(" "); totalUnits.text(""); } } /////////////////////////////////////////////////////////// // PUBLIC FUNCTIONS //////////////////////////////////// /////////////////////////////////////////////////////////// SequenceSunburst.prototype.setUrlParams = function(url_params) { this.url_params = url_params; this.resetCentralCirleText(); this.forceUpdate(); } SequenceSunburst.prototype.forceUpdate = function(url_params) { // this.stopInterval(); this.flashUpdate(0,1); this.update(); // this.startInterval(); } SequenceSunburst.prototype.setInterval = function(p_sunburstInterval) { this.sunburstInterval = p_sunburstInterval; } SequenceSunburst.prototype.stopInterval = function() { //disabled graph interval window.clearInterval(this.sunburstInterval); } SequenceSunburst.prototype.startInterval = function() { this.sunburstInterval = window.setInterval(this.update(), this.refresh) }