// Author: Ming Qin (https://github.com/QinMing) // Copyright 2015 Yahoo Inc. // This file is licensed under the MIT License. See LICENSE in the project root for terms /*global d3*/ var SankeyDriver = function (){ var sankey = d3.sankey(); var formatNumber = d3.format(","); //(",.2f"); machlist=["ANNL01","ANNL02","ANNL03","ANNL04","ANNL05","DIFF01","DIFF02","DIFF03","DIFF04","DIFF05","ETCH01","ETCH02","ETCH03","ETCH04","ETCH05","FCOT01","FCOT02","FCOT03","FCOT04","FCOT05","MAIA00","MAIA01","MAIA02","MAIA03","MAIA04","MAIA05","PRNT01A","PRNT01B","PRNT02A","PRNT02B","PRNT03A","PRNT03B","PRNT04A","PRNT04B","TEXT01","TEXT02","TEXT03","TEXT04"]; colorlist=["MediumOrchid","Indigo","Orchid","DarkViolet","DarkMagenta","LightSalmon ","Coral","Tomato","OrangeRed","DarkOrange","MediumSlateBlue ","SteelBlue ","MediumBlue","DarkBlue","CornflowerBlue","Crimson","FireBrick","Maroon ","SaddleBrown","Sienna","Black","Cyan","DarkTurquoise","DeepSkyBlue","MediumTurquoise","PowderBlue","Green","Lime","LawnGreen","SeaGreen","PaleGreen","MediumSeaGreen","LimeGreen","SpringGreen","Gold","Khaki","GoldenRod","DarkGoldenRod"]; var color = d3.scale.ordinal() .domain(machlist) .range(colorlist) ; var graph, width, height; var tooltips = []; var tooltipEnable = true; var tooltipContainer, tbody,barchart,svg,stacked; this.prepare = function (canvas, sz, margin) { width = sz.width - margin.left - margin.right; height= sz.height - margin.top - margin.bottom; graph = canvas .html('') .append('svg') .attr("width", sz.width) .attr("height", sz.height) .append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); tooltipContainer = canvas .append('div') .attr('id', 'tooltip-container'); barchart = canvas .append('div') .attr('class', 'dviz-hbar'); tbody = tooltipContainer .append('table') .attr('class', 'tooltip') .append('tbody'); }; this.draw = function (inputdata) { sankey .nodeWidth(10) .nodePadding(10) .size([width, height]); sankey.nodes(inputdata.nodes) .flows(inputdata.flows) .layout(32); drawNode(sankey.nodes()); drawLink(sankey.links()); function drawNode(nodes) { var group = graph.selectAll('g#node-group').data([0]); group.enter().append('g').attr("id", "node-group"); var node = group.selectAll("g.node").data(nodes); node.exit().remove(); var nodeEnter = node.enter().append("g") .attr("class", "node") .on("click", funcMouseover) .on("contextmenu", funcMouseout) // .on("mouseover", funcMouseover) // .on("mouseout", funcMouseout) // .on('mousemove', funcMousemove) // .on('dblclick', funcTooltipToggle) .call(d3.behavior.drag() .origin(function (d) { return d; }) /* .on("dragstart", function () { d3.event.sourceEvent.stopPropagation(); this.parentNode.appendChild(this); }) */ .on("drag", function dragmove(d) { d3.select(this).attr("transform", "translate(" + ( d.x = Math.max(0, Math.min(width - d.dx, d3.event.x)) ) + "," + ( d.y = Math.max(0, Math.min(height - d.dy, d3.event.y)) ) + ")"); sankey.relayout(); graph.select('g#normal').selectAll('path').attr("d", sankey.link()); graph.select('g#highlight').selectAll('path').attr("d", sankey.link()); }) ); nodeEnter.append("rect");//.append('title'); nodeEnter.append("text"); node .attr("transform", function (d) { return "translate(" + d.x + "," + d.y + ")"; }); node.select('rect') .attr("height", function (d) { return d.dy; }) .attr("width", sankey.nodeWidth()) .style("fill", function (d) { if (!d.color){ d.color = color(d.disp); } return d.color; }) .style("stroke", function (d) { return d3.rgb(d.color).darker(2); }); // .select("title") // .text(function (d) { // var text = formatNumber(d.value) + '\t' + d.disp; // return text; // }); node.select("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) { if(d.dy!=0){ return d.disp;} }) .filter(function (d) { return d.x < width / 2; }) .attr("x", 6 + sankey.nodeWidth()) .attr("text-anchor", "start"); } function drawLink(data) { var group = graph.selectAll('g#normal').data([0]); group.enter().insert("g", ":first-child").attr('id', 'normal'); var link = group.selectAll('path.link').data(data); link.exit().remove(); link.enter().append("path") .attr("class", "link") // .on("click", funcMouseover) .on("contextmenu", funcMouseout) // .on("mouseover", funcMouseover) // .on("mouseout", funcMouseout) // .on('mousemove', funcMousemove) .on('dblclick', red_checked) // .append("title"); link .attr("d", sankey.link()) .style("stroke-width", function (d) { return Math.max(1, d.dy); }) .sort(function (a, b) { return b.dy - a.dy; }); } function drawDLink(data) { return graph.insert("g", ":first-child") .attr('id', 'highlight') .selectAll('path') .data(data) .enter() .append("path") .attr("class", "link highlight") .attr("d", sankey.link()) .style("stroke-width", function (d) { return Math.max(1, d.dy); }) .sort(function (a, b) { return b.dy - a.dy; }); } function drawRLink(data) { return graph.insert("g", ":first-child") .attr('id', 'highlight2') .selectAll('path') .data(data) .enter() .append("path") .attr("class", "link highlight_red") .attr("d", sankey.link()) .style("stroke-width", function (d) { return Math.max(1, d.dy); }) .sort(function (a, b) { return b.dy - a.dy; }); } function funcMouseover(d) { graph.selectAll("g#highlight").remove(); d3.select("#top5").remove(); d3.select("#stackk").remove(); tooltipContainer.style('display', 'none'); red2=[]; for (var i = 0; i < d.flows.length; i++) { red2.push(d.flows[i]) } sankey.dflows(d.flows); drawDLink(sankey.dlinks()); updateTooltip(d); drawChart2(d) drawChart3(d) tooltipContainer.style('display', 'inline-block') .style('height', 200 + 'px') .style("overflow-y", "scroll"); } function funcMouseout() { graph.selectAll("g#highlight").remove(); tooltipContainer.style('display', 'none'); d3.select("#top5").remove(); d3.select("#stackk").remove(); } function funcMousemove() { tooltipContainer .style('top', d3.event.clientY + 'px') .style('left', d3.event.clientX + 'px'); } function funcTooltipToggle(d){ tooltipEnable = !tooltipEnable; updateTooltip(d); } function red_checked(d){ red=[]; for (var i = 1; i < red2.length+1; i++) { var checkBox = document.getElementById("chk_" +i); if (checkBox.checked == true){ red.push(red2[i-1]) } } var sankey = d3.sankey(); sankey.dflows2(d.flows); drawDLink(sankey.dlinks()); } function drawChart2(d) { var line_summary= []; var line_summary=d.summary; var data=[]; var machine=[]; for (var i=0, len=line_summary.length-1;i<8;i++){ if(line_summary[i].machine!=d.disp){ data.push({value:line_summary[i].percent,name:line_summary[i].machine}) } }; //sort bars based on value data = data.sort(function (a, b) { return d3.ascending(a.value, b.value); }) var margin = { top: 25, right: 35, bottom: 15, left: 60 }; var width = 420 - margin.left - margin.right, height = 200 - margin.top - margin.bottom; var x = d3.scale.linear() .range([0, width]) .domain([0, d3.max(data, function (d) { return d.value; })]); var y = d3.scale.ordinal() .rangeRoundBands([height, 0], .1) .domain(data.map(function (d) { return d.name; })); var svg = d3.select("#dviz-hbar").append("svg") .attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom) .attr("id","top5") .append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); //make y axis to show bar names var yAxis = d3.svg.axis() .scale(y) //no tick marks .tickSize(0) .orient("left"); var gy = svg.append("g") .attr("class", "y axis") .call(yAxis) var bars = svg.selectAll(".bar") .data(data); bars.exit().remove(); bars.enter().append("g"); bars.transition() .duration(500); //append rects bars.append("rect") .attr("class", "bar") .attr("y", function (d) { return y(d.name); }) .attr("height", y.rangeBand()) .attr("x", 0) .attr("width", function (d) { return x(d.value); }) .style("fill", function(d) { for (var g = 0; g < machlist.length; g++){ if(d.name==machlist[g]){ return colorlist[g]; } } }); //add a value label to the right of each bar bars.append("text") .attr("class", "label") //y position of the label is halfway down the bar .attr("y", function (d) { return y(d.name) + y.rangeBand() / 2 + 4; }) //x position is 3 pixels to the right of the bar .attr("x", function (d) { return x(d.value) + 3; }) .text(function (d) { return d.value +'%'; }); var title = svg.append("g") .attr("class", "title") .attr("transform", "translate(" + [0, -margin.top / 4] + ")") /* title.append("text") .attr("text-anchor", "stat") .text("Top Machines with Similar Process Flows"); */ } function drawChart3(d) { var line_summary= []; var line_summary=d.summary; var data2=[]; // var machineid = ["TEXT01","TEXT02", "TEXT03","TEXT04","DIFF01","DIFF02","DIFF03","DIFF04","DIFF05","ETCH01","ETCH02","ETCH03","ETCH04","ANNL01","ANNL02","ANNL03","ANNL04","ANNL05","FCOT01","FCOT02","FCOT03","FCOT04","FCOT05","PRNT01A","PRNT01B","PRNT02A","PRNT02B","PRNT03A","PRNT03B","PRNT04A","PRNT04B"]; var machineid = machlist var groups = []; for (var i = 0; i < line_summary.length; i++) { var groupName = line_summary[i].process; var perc=line_summary[i].percent; if (!groups[groupName]) { groups[groupName] = []; } groups[groupName].push({[line_summary[i].machine]:line_summary[i].value}); } data = []; myArray2 = []; for (var groupName in groups) { groups[groupName].push({date: groupName}) for (var j = 0; j < machineid.length; j++) { if (!myArray2[groupName]) { myArray2[groupName] = []; } myArray2[groupName].push({[machineid[j]]:0}); } for (var k = 0; k < groups[groupName].length;k++) { myArray2[groupName].push(groups[groupName][k]); } ; resultObject=[]; var resultObject = myArray2[groupName].reduce(function(result, currentObject) { for(var key in currentObject) { if (currentObject.hasOwnProperty(key)) { result[key] = currentObject[key]; } } return result; }, {}); data.push(resultObject); } var margin = {top: 25, right: 5, bottom: 15, left: 70}, width = 420 - margin.left - margin.right, height = 200 - margin.top - margin.bottom; var x = d3.scale.linear() .range([0, width]); var y = d3.scale.ordinal() .rangeRoundBands([height, 0], .1); //var z = d3.scale.category10(); var z = color; var xAxis = d3.svg.axis() .scale(x) .orient("bottom") var yAxis = d3.svg.axis() .scale(y) .orient("left"); var stacked = d3.select("#dviz-hbar").append("svg") .attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom) .attr("id","stackk") .append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); var layers = d3.layout.stack()(machineid.map(function(c) { return data.map(function(d) { d[c] = +d[c]; return {x: d.date, y: d[c]}; }); })); y.domain(layers[0].map(function(d) { return d.x; })); x.domain([0, d3.max(layers[layers.length - 1], function(d) { return d.y0 + d.y; })]).nice(); // x.domain([0, 100]).nice(); var layer = stacked.selectAll(".layer") .data(layers) .enter().append("g") .attr("class", "layer") .style("fill", function(d, i) { return z(i); }); layer.selectAll("rect") .data(function(d) { return d; }) .enter().append("rect") .attr("class", "bar") .attr("y", function(d) { return y(d.x); }) .attr("x", function(d) {return x(d.y0); }) .attr("width", function(d) {return x(d.y); }) .attr("height", y.rangeBand()-2) ; stacked.append("g") .attr("class", "axis axis--x") .attr("transform", "translate(0," + width + ")") .call(xAxis); stacked.append("g") .attr("class", "axis axis--y") .attr("transform", "translate(" + 0 + ",0)") .call(yAxis); for (var j = 0; j < layers[0].length; j++) { layer.append("text") .attr("class", "label") .attr("y", function(d) {return y(d[j].x)+13 }) .attr("x", function(d) {return x(d[j].y0)+x(d[j].y)/2-17}) .text(function (d,k) { if(d[j].y!=0 && x(d[j].y)>35){ return 'L' + machlist[k].substring(5) + ':' + d[j].y; }}); } }; /////////////////////// //// Tooltips function colorDot(d){ return ''; } sankey.nodes().forEach(function(n){ n.summary=sankey.dflows(n.flows); n.tooltip = { name: formatNumber(n.value) + " Lot(s) through " +colorDot(n) + n.disp, value: formatNumber(n.value), lts: "LTS No.", head: true, }; }); sankey.links().forEach(function(l){ l.tooltip = { name: colorDot(l.source) + l.source.disp + " → " + colorDot(l.target) + l.target.disp, value: formatNumber(l.value), head: true, }; }); sankey.flows().forEach(function(f){ var name = ""; f.thru.forEach(function (n, ind) { if (ind !== 0) name += ' → '; name += colorDot(n) + n.disp +" "+ f.time[ind]; }); var lts=f.LTS; f.tooltip = { name: name, lts: lts, }; }); //param d: data, could be node or link function updateTooltip(d){ tooltips = [d.tooltip]; if (tooltipEnable){ d.flows.forEach(function(f){ tooltips.push(f.tooltip); }); } //no need to use D3 tbody.selectAll('*').remove(); tooltips.forEach(function(tip,i){ var tr = tbody.append('tr'); if (i!=0){ var chk=""; } else{ var chk = ""; var lts = "LTS No."; }; tr.append('td') // .attr('class', 'chkbox') .classed('head', 'head' in tip) .html(chk); tr.append('td') .attr('class', 'lts') .classed('head', 'head' in tip) .html(tip.lts); tr.append('td') .attr('class', 'name') .classed('head', 'head' in tip) .html(tip.name); }); } }; }; function check_all(source){ checkboxes = document.getElementsByName('foo'); for(var i=0, n=checkboxes.length;i