Cluester Impurity Visualizer
Last active
January 7, 2024 21:13
-
-
Save nswamy14/e28ec2c438e9e8bd302f to your computer and use it in GitHub Desktop.
ClusterPurityVisualizer
This file contains hidden or 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
| d3 = d3 || {}; | |
| (function(){ | |
| "use strict"; | |
| d3.cluster = function(){ | |
| var containerID,width,height,originalData; | |
| var ParentG,LegendG,legendFilter= []; | |
| var circleR = 0; | |
| var innerRadius =0,eleInRow,noOfCategories,fixAngleLayout; | |
| var colorScale = d3.scale.category10(); | |
| var radiusScale = d3.scale.linear(); | |
| var legendObj = d3.legend(); | |
| var scale_temp = d3.scale.linear(); | |
| var MinMaxTotal = 0; | |
| var pie = d3.layout.pie() | |
| .sort(null) | |
| .value(function(d) { | |
| return d.ele; | |
| }); | |
| var custLayout = d3.custumPieLayout() | |
| .sort(null) | |
| .value(function(d) { | |
| return d.ele; | |
| }); | |
| var arc = d3.svg.arc() | |
| .innerRadius(innerRadius); | |
| var totalCount = 0; | |
| var colorMap = {}; | |
| var chart = function(selection){ | |
| if(fixAngleLayout) | |
| custLayout.fixAngle((360/(noOfCategories- legendFilter.length))/(360/(2*Math.PI))); | |
| width = parseInt(d3.select('#'+containerID).style('width')); | |
| height = parseInt(d3.select('#'+containerID).style('height')); | |
| legendObj.legendOnclickMthod(chart.legendFilter); | |
| selection.each(function(data){ | |
| originalData = data; | |
| data.forEach(function(d){ | |
| d.values.forEach(function(e){ | |
| e.total = d.total; | |
| e.color = colorScale(e.type); | |
| if(!colorMap.hasOwnProperty(e.type)) | |
| colorMap[e.type] = {'key':e.type,'color':e.color}; | |
| }) | |
| }); | |
| var length = data.length, eleInRow = Math.ceil(Math.sqrt(length)); | |
| var container = d3.select(this); | |
| width = width - 100; | |
| var temp_width = data.length > eleInRow?width-0.5*(width/eleInRow):width; | |
| circleR = d3.min([temp_width,height])/eleInRow; | |
| var x_offset = 0,y_offset=0; | |
| radiusScale | |
| .domain([0,d3.extent(data,function(d){return d.total})[1]]) | |
| .range([(circleR/2)*(1/data.length),circleR/2]); | |
| MinMaxTotal = radiusScale.domain(); | |
| container.attr('width',(circleR*eleInRow+0.5*circleR)+200) | |
| .attr('height',circleR*eleInRow) | |
| if(!ParentG){ | |
| ParentG = container.append('g').attr('class','parentG') | |
| .attr('transform','translate('+(data.length > eleInRow?0.5*circleR:0)+','+20+')'); | |
| LegendG = container.append('g').attr('class','legendG'); | |
| } | |
| LegendG.attr('transform','translate('+(width+50)+','+((circleR*eleInRow/2)-(Object.keys(colorMap).length*20)/2)+')') | |
| .datum(colorMap) | |
| .call(legendObj); | |
| var circleG = ParentG | |
| .attr('transform','translate('+(data.length > eleInRow?0.5*circleR:0)+','+20+')') | |
| .selectAll('.circleG') | |
| .data(data | |
| .sort(function(a,b){ | |
| if(a.total < b.total) | |
| return 1; | |
| else if(a.total > b.total) | |
| return -1; | |
| else | |
| return 0; | |
| })); | |
| circleG.enter() | |
| .append('g') | |
| .attr('class','circleG') | |
| .attr('transform',function(d,i){ | |
| return 'translate('+((i%eleInRow)*(circleR))+','+(Math.floor(i/eleInRow)*circleR)+')'; | |
| }) | |
| .append('circle') | |
| .attr('r',circleR/2) | |
| .attr('cx',circleR/2) | |
| .attr('cy',circleR/2) | |
| .style('fill','white') | |
| .style('stroke','black') | |
| .style('stroke-width','1px'); | |
| circleG.exit().remove(); | |
| circleG | |
| .transition() | |
| .duration(1000) | |
| .attr('transform',function(d,i){ | |
| if(Math.floor(i/eleInRow)%2 === 1){ | |
| x_offset = 0.5*circleR; | |
| y_offset = 0.13*circleR*Math.floor(i/eleInRow); | |
| } | |
| else{ | |
| x_offset = 0; | |
| if(Math.floor(i/eleInRow)===0) | |
| y_offset = 0; | |
| else | |
| y_offset = 0.13*circleR*Math.floor(i/eleInRow); | |
| } | |
| return 'translate('+(((i%eleInRow)*(circleR))-x_offset)+','+((Math.floor(i/eleInRow)*circleR)-y_offset)+')'; | |
| }); | |
| circleG | |
| .selectAll('circle') | |
| .attr('r',circleR/2) | |
| .attr('cx',circleR/2) | |
| .attr('cy',circleR/2) | |
| .on('click',function(d){ | |
| // console.log(d); | |
| // console.log((radiusScale(d.total))*0.8) | |
| }); | |
| circleG.each(chart.renderPieChart); | |
| }) | |
| d3.select(window).on('resize.'+containerID, chart.resize) | |
| }; | |
| chart.containerID = function(_){ | |
| containerID = _; | |
| return chart; | |
| }; | |
| chart.noOfCategories= function(_){ | |
| noOfCategories = _; | |
| return chart; | |
| }; | |
| chart.fixAngleLayout = function(_){ | |
| fixAngleLayout = _; | |
| return chart; | |
| }; | |
| chart.legendFilter = function(_){ | |
| if(legendFilter.indexOf(_) == -1) | |
| legendFilter.push(_); | |
| else | |
| legendFilter.splice(legendFilter.indexOf(_),1); | |
| d3.select('#'+containerID).select('svg').datum(originalData).call(chart); | |
| return chart; | |
| }; | |
| chart.change = function(_){ | |
| chart.fixAngleLayout(_); | |
| d3.select('#'+containerID).select('svg').datum(originalData).call(chart); | |
| return chart; | |
| }; | |
| chart.resize = function(){ | |
| d3.select('#'+containerID).select('svg').datum(originalData).call(chart); | |
| }; | |
| chart.renderPieChart = function(data){ | |
| scale_temp | |
| .domain(d3.extent(data.values,function(d){return d.ele;})) | |
| .range([parseInt(radiusScale(data.total)*0.2),parseInt(radiusScale(data.total))*1.2]); | |
| // console.log(scale_temp.domain()) | |
| // console.log(scale_temp.range()) | |
| arc.outerRadius(function (d) { | |
| if(fixAngleLayout){ | |
| return scale_temp(d.value); | |
| } | |
| else{ | |
| return (radiusScale(d.data.total))*0.8; | |
| } | |
| }); | |
| var newData = data.values | |
| .filter(function(d){ | |
| if(legendFilter.indexOf(d.type) === -1) | |
| return true; | |
| else | |
| return false; | |
| }); | |
| var paths = d3.select(this) | |
| .selectAll('path') | |
| .data(fixAngleLayout?custLayout(newData):pie(newData)); | |
| paths.enter() | |
| .append("path") | |
| .attr('transform',function(d,i){ | |
| return 'translate('+(circleR/2)+','+(circleR/2)+')'; | |
| }) | |
| .attr("fill", function(d){ | |
| return d.data.color; | |
| }) | |
| .attr("stroke", "gray") | |
| .attr("class", "outlineArc") | |
| .attr("d", arc) | |
| .each(function(d) { this._current = d; }); | |
| paths.exit().remove(); | |
| paths | |
| .attr('transform',function(d,i){ | |
| return 'translate('+(circleR/2)+','+(circleR/2)+')'; | |
| }) | |
| .attr("fill", function(d){ | |
| return d.data.color; | |
| }) | |
| .transition() | |
| .duration(1000) | |
| .attrTween("d", arcTween); | |
| function arcTween(a) { | |
| var i = d3.interpolate(this._current, a); | |
| this._current = i(10); | |
| return function(t) { | |
| return arc(i(t)); | |
| }; | |
| } | |
| } | |
| return chart; | |
| }; | |
| d3.custumPieLayout = function(){ | |
| var sort,fixAngle, | |
| valueFun, | |
| sortcomparator, | |
| padAngle=0; | |
| var pieLayoutObj = function(startAngle,endAngle,padAngle,value,data){ | |
| this.startAngle =startAngle; | |
| this.endAngle =endAngle; | |
| this.padAngle = padAngle; | |
| this.value = value; | |
| this.data = data; | |
| }; | |
| var layout = function(data){ | |
| if(sortcomparator) | |
| data.sort(sortcomparator); | |
| var previousEndAngle = 0; | |
| var outputObj = []; | |
| data.forEach(function(d){ | |
| outputObj.push(new pieLayoutObj(previousEndAngle,previousEndAngle+fixAngle,padAngle,valueFun(d),d)); | |
| previousEndAngle = previousEndAngle+fixAngle; | |
| }); | |
| return outputObj; | |
| }; | |
| layout.sort = function(_){ | |
| //if(typeof _ !== 'function') return; | |
| sortcomparator = _; | |
| return layout; | |
| } | |
| layout.fixAngle = function(_){ | |
| if(!arguments.length) return; | |
| fixAngle = _; | |
| return layout; | |
| } | |
| layout.value = function(_){ | |
| if(typeof _ !== 'function') return; | |
| valueFun = _; | |
| return layout; | |
| } | |
| layout.padAngle = function(_){ | |
| padAngle = _; | |
| return layout; | |
| } | |
| return layout; | |
| }; | |
| d3.legend = function () { | |
| var legendOnclickMthod, | |
| legendOnHoverMthod, | |
| legendOnmouseHoverMthod, | |
| legendOnmouseOutMthod, | |
| legendOndblclickMthod; | |
| var chart = function(selection){ | |
| selection.each(function(data){ | |
| var legend_container = d3.select(this); | |
| var wrap = legend_container.selectAll('.legendChart').data([data]); | |
| var wrapEnter = wrap.enter().append('g').attr('class', 'legendChart'); | |
| var gEnter = wrapEnter.append('g'); | |
| var g = wrap.select('g'); | |
| var g_ci = g.selectAll('circle') | |
| .data(function(d){ | |
| return Object.keys(d) | |
| }); | |
| g_ci.exit().transition().remove(); | |
| g_ci.enter() | |
| .append('circle') | |
| .attr('r',function(d){return 10;}) | |
| .style('fill', function(d){return data[d].color}) | |
| .style('opacity',1) | |
| .style('stroke', function(d){return data[d].color}) | |
| .style('stroke-width',2) | |
| .attr('cx',function(d,i){ | |
| return 0; | |
| }) | |
| .attr('cy',function(d,i){ | |
| return Math.floor(i)*30; | |
| }) | |
| .on('click',function(d){ | |
| if(d3.select(this).classed("disable_")){ | |
| d3.select(this).style("fill",data[d].color) | |
| .classed("disable_",false); | |
| legendOnclickMthod(data[d].key,true); | |
| } | |
| else | |
| { | |
| d3.select(this).classed("disable_",true) | |
| .style("fill",'white'); | |
| legendOnclickMthod(data[d].key,false); | |
| } | |
| }); | |
| g_ci.style('fill', function(d){ | |
| if(d3.select(this).style('fill')=='rgb(255, 255, 255)') | |
| return 'white'; | |
| else | |
| return data[d].color; | |
| }) | |
| .style('stroke', function(d){return data[d].color}) | |
| .transition() | |
| .duration(1000) | |
| .attr('cx',function(d,i){ | |
| return 0; | |
| }) | |
| .attr('cy',function(d,i){ | |
| return Math.floor(i)*30; | |
| }); | |
| var g_txt = g.selectAll('text') | |
| .data(function(d){ return Object.keys(d)}); | |
| g_txt.exit().transition().remove(); | |
| g_txt.enter() | |
| .append('text'); | |
| g_txt.text(function(d){return data[d].key.substring(0,10)}) | |
| .attr('font-size','18px') | |
| .transition() | |
| .duration(1000) | |
| .attr('x',function(d,i){ | |
| return 30; | |
| }) | |
| .attr('y',function(d,i){ | |
| return i*30+5; | |
| }) | |
| }); | |
| //return chart; | |
| }; | |
| chart.legendOnclickMthod = function(_){ | |
| if(!arguments.length) return legendOnclickMthod; | |
| if(typeof _ != 'function') return legendOnclickMthod; | |
| legendOnclickMthod = _; | |
| return chart; | |
| }; | |
| chart.legendOndblclickMthod = function(_){ | |
| if(!arguments.length) return legendOndblclickMthod; | |
| if(typeof _ != 'function') return legendOndblclickMthod; | |
| legendOndblclickMthod = _; | |
| return chart; | |
| }; | |
| chart.legendOnmouseOutMthod = function(_){ | |
| if(!arguments.length) return legendOnmouseOutMthod; | |
| if(typeof _ != 'function') return legendOnmouseOutMthod; | |
| legendOnmouseOutMthod = _; | |
| return chart; | |
| }; | |
| chart.legendOnmouseHoverMthod = function(){ | |
| if(!arguments.length) return legendOnmouseHoverMthod; | |
| if(typeof _ != 'function') return legendOnmouseHoverMthod; | |
| legendOnmouseHoverMthod = _; | |
| return chart; | |
| }; | |
| return chart; | |
| }; | |
| })() |
This file contains hidden or 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
| [{ | |
| "values":[ | |
| { | |
| "ele":20, | |
| "type":"c1" | |
| }, | |
| { | |
| "ele":40, | |
| "type":"c2" | |
| }, | |
| { | |
| "ele":80, | |
| "type":"c3" | |
| }, | |
| { | |
| "ele":10, | |
| "type":"c4" | |
| }], | |
| "total": 150 | |
| }, | |
| { | |
| "values":[ | |
| { | |
| "ele":50, | |
| "type":"c1" | |
| }, | |
| { | |
| "ele":0, | |
| "type":"c2" | |
| }, | |
| { | |
| "ele":0, | |
| "type":"c3" | |
| }, | |
| { | |
| "ele":10, | |
| "type":"c4" | |
| }], | |
| "total": 60 | |
| }, | |
| { | |
| "values":[ | |
| { | |
| "ele":25, | |
| "type":"c1" | |
| }, | |
| { | |
| "ele":20, | |
| "type":"c2" | |
| }, | |
| { | |
| "ele":25, | |
| "type":"c3" | |
| }, | |
| { | |
| "ele":60, | |
| "type":"c4" | |
| }], | |
| "total": 130 | |
| }, | |
| { | |
| "values":[ | |
| { | |
| "ele":25, | |
| "type":"c1" | |
| }, | |
| { | |
| "ele":25, | |
| "type":"c2" | |
| }, | |
| { | |
| "ele":25, | |
| "type":"c3" | |
| }, | |
| { | |
| "ele":25, | |
| "type":"c4" | |
| }], | |
| "total": 100 | |
| }, | |
| { | |
| "values":[ | |
| { | |
| "ele":30, | |
| "type":"c1" | |
| }, | |
| { | |
| "ele":60, | |
| "type":"c2" | |
| }, | |
| { | |
| "ele":20, | |
| "type":"c3" | |
| }, | |
| { | |
| "ele":90, | |
| "type":"c4" | |
| }], | |
| "total": 190 | |
| }, | |
| { | |
| "values":[ | |
| { | |
| "ele":10, | |
| "type":"c1" | |
| }, | |
| { | |
| "ele":20, | |
| "type":"c2" | |
| }, | |
| { | |
| "ele":30, | |
| "type":"c3" | |
| }, | |
| { | |
| "ele":40, | |
| "type":"c4" | |
| }], | |
| "total": 100 | |
| }, | |
| { | |
| "values":[ | |
| { | |
| "ele":20, | |
| "type":"c1" | |
| }, | |
| { | |
| "ele":60, | |
| "type":"c2" | |
| }, | |
| { | |
| "ele":30, | |
| "type":"c3" | |
| }, | |
| { | |
| "ele":40, | |
| "type":"c4" | |
| }], | |
| "total": 150 | |
| }, | |
| { | |
| "values":[ | |
| { | |
| "ele":30, | |
| "type":"c1" | |
| }, | |
| { | |
| "ele":40, | |
| "type":"c2" | |
| }, | |
| { | |
| "ele":50, | |
| "type":"c3" | |
| }, | |
| { | |
| "ele":60, | |
| "type":"c4" | |
| }], | |
| "total": 180 | |
| }, | |
| { | |
| "values":[ | |
| { | |
| "ele":30, | |
| "type":"c1" | |
| }, | |
| { | |
| "ele":40, | |
| "type":"c2" | |
| }, | |
| { | |
| "ele":50, | |
| "type":"c3" | |
| }, | |
| { | |
| "ele":60, | |
| "type":"c4" | |
| }], | |
| "total": 180 | |
| }] |
This file contains hidden or 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> | |
| <!-- COLORS ARE NOT PERFECT YET. TOOLTIP NEEDS WORK--> | |
| <meta charset="utf-8"> | |
| <head> | |
| <h1> ClusterPurityCheck chart</h1> | |
| <style> | |
| body { | |
| font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; | |
| } | |
| #chart{ | |
| text-align: center; | |
| width: 50%; | |
| height: 700px; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <input id="click_1" type="radio" name="sel" value="true" checked="true">Length representation</input> | |
| <input id="click_2" type="radio" name="sel" value="false">Angle representation</input> | |
| <div id='chart' ></div> | |
| <script src="//d3js.org/d3.v3.min.js" charset="utf-8"></script> | |
| <script src="clusterpurityChart.js"></script> | |
| <script> | |
| var obj; | |
| d3.json('clusterpurityDataSet.json',function(error,data){ | |
| obj = d3.cluster().containerID('chart').noOfCategories(4).fixAngleLayout(true); | |
| d3.select('#chart').append('svg').datum(data).call(obj); | |
| }); | |
| d3.select('#click_1').on('click',clickFun); | |
| d3.select('#click_2').on('click',clickFun); | |
| function clickFun(){ | |
| obj.change(document.getElementById('click_1').checked); | |
| } | |
| </script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment