Last active
December 12, 2015 03:58
-
-
Save adewes/4710330 to your computer and use it in GitHub Desktop.
Hierarchical Pie Chart
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
code_hierarchy_data = [ | |
"", | |
[ | |
416598, | |
11581 | |
], | |
{ | |
"docs": [ | |
"docs", | |
[ | |
14126, | |
374 | |
], | |
{ | |
"conf-py": [ | |
"conf.py", | |
[ | |
8906, | |
270 | |
], | |
{} | |
], | |
"flaskdocext-py": [ | |
"flaskdocext.py", | |
[ | |
345, | |
17 | |
], | |
{} | |
], | |
"flaskext-py": [ | |
"flaskext.py", | |
[ | |
4875, | |
87 | |
], | |
{} | |
] | |
} | |
], | |
"examples": [ | |
"examples", | |
[ | |
21071, | |
677 | |
], | |
{ | |
"blueprintexample": [ | |
"blueprintexample", | |
[ | |
1551, | |
63 | |
], | |
{ | |
"blueprintexample-py": [ | |
"blueprintexample.py", | |
[ | |
282, | |
11 | |
], | |
{} | |
], | |
"blueprintexample_test-py": [ | |
"blueprintexample_test.py", | |
[ | |
867, | |
37 | |
], | |
{} | |
], | |
"simple_page": [ | |
"simple_page", | |
[ | |
402, | |
15 | |
], | |
{ | |
"__init__-py": [ | |
"__init__.py", | |
[ | |
0, | |
1 | |
], | |
{} | |
], | |
"simple_page-py": [ | |
"simple_page.py", | |
[ | |
402, | |
14 | |
], | |
{} | |
] | |
} | |
] | |
} | |
], | |
"flaskr": [ | |
"flaskr", | |
[ | |
5142, | |
178 | |
], | |
{ | |
"flaskr-py": [ | |
"flaskr.py", | |
[ | |
2795, | |
102 | |
], | |
{} | |
], | |
"flaskr_tests-py": [ | |
"flaskr_tests.py", | |
[ | |
2347, | |
76 | |
], | |
{} | |
] | |
} | |
], | |
"jqueryexample": [ | |
"jqueryexample", | |
[ | |
659, | |
30 | |
], | |
{ | |
"jqueryexample-py": [ | |
"jqueryexample.py", | |
[ | |
659, | |
30 | |
], | |
{} | |
] | |
} | |
], | |
"minitwit": [ | |
"minitwit", | |
[ | |
13719, | |
406 | |
], | |
{ | |
"minitwit-py": [ | |
"minitwit.py", | |
[ | |
8481, | |
256 | |
], | |
{} | |
], | |
"minitwit_tests-py": [ | |
"minitwit_tests.py", | |
[ | |
5238, | |
150 | |
], | |
{} | |
] | |
} | |
] | |
} | |
], | |
"flask": [ | |
"flask", | |
[ | |
347807, | |
9474 | |
], | |
{ | |
"__init__-py": [ | |
"__init__.py", | |
[ | |
1584, | |
50 | |
], | |
{} | |
], | |
"app-py": [ | |
"app.py", | |
[ | |
74800, | |
1785 | |
], | |
{} | |
], | |
"blueprints-py": [ | |
"blueprints.py", | |
[ | |
15269, | |
374 | |
], | |
{} | |
], | |
"config-py": [ | |
"config.py", | |
[ | |
6150, | |
169 | |
], | |
{} | |
], | |
"ctx-py": [ | |
"ctx.py", | |
[ | |
11112, | |
304 | |
], | |
{} | |
], | |
"debughelpers-py": [ | |
"debughelpers.py", | |
[ | |
3458, | |
86 | |
], | |
{} | |
], | |
"exceptions-py": [ | |
"exceptions.py", | |
[ | |
1454, | |
49 | |
], | |
{} | |
], | |
"ext": [ | |
"ext", | |
[ | |
842, | |
30 | |
], | |
{ | |
"__init__-py": [ | |
"__init__.py", | |
[ | |
842, | |
30 | |
], | |
{} | |
] | |
} | |
], | |
"exthook-py": [ | |
"exthook.py", | |
[ | |
5055, | |
120 | |
], | |
{} | |
], | |
"globals-py": [ | |
"globals.py", | |
[ | |
1137, | |
45 | |
], | |
{} | |
], | |
"helpers-py": [ | |
"helpers.py", | |
[ | |
32910, | |
830 | |
], | |
{} | |
], | |
"json-py": [ | |
"json.py", | |
[ | |
5591, | |
168 | |
], | |
{} | |
], | |
"logging-py": [ | |
"logging.py", | |
[ | |
1398, | |
46 | |
], | |
{} | |
], | |
"module-py": [ | |
"module.py", | |
[ | |
1363, | |
43 | |
], | |
{} | |
], | |
"sessions-py": [ | |
"sessions.py", | |
[ | |
12023, | |
306 | |
], | |
{} | |
], | |
"signals-py": [ | |
"signals.py", | |
[ | |
1973, | |
53 | |
], | |
{} | |
], | |
"templating-py": [ | |
"templating.py", | |
[ | |
4666, | |
143 | |
], | |
{} | |
], | |
"testing-py": [ | |
"testing.py", | |
[ | |
4958, | |
123 | |
], | |
{} | |
], | |
"testsuite": [ | |
"testsuite", | |
[ | |
150926, | |
4452 | |
], | |
{ | |
"__init__-py": [ | |
"__init__.py", | |
[ | |
6376, | |
225 | |
], | |
{} | |
], | |
"appctx-py": [ | |
"appctx.py", | |
[ | |
3124, | |
103 | |
], | |
{} | |
], | |
"basic-py": [ | |
"basic.py", | |
[ | |
43316, | |
1241 | |
], | |
{} | |
], | |
"blueprints-py": [ | |
"blueprints.py", | |
[ | |
27369, | |
767 | |
], | |
{} | |
], | |
"config-py": [ | |
"config.py", | |
[ | |
11816, | |
301 | |
], | |
{} | |
], | |
"deprecations-py": [ | |
"deprecations.py", | |
[ | |
1074, | |
42 | |
], | |
{} | |
], | |
"examples-py": [ | |
"examples.py", | |
[ | |
942, | |
39 | |
], | |
{} | |
], | |
"ext-py": [ | |
"ext.py", | |
[ | |
4720, | |
124 | |
], | |
{} | |
], | |
"helpers-py": [ | |
"helpers.py", | |
[ | |
19337, | |
512 | |
], | |
{} | |
], | |
"regression-py": [ | |
"regression.py", | |
[ | |
3221, | |
118 | |
], | |
{} | |
], | |
"signals-py": [ | |
"signals.py", | |
[ | |
3082, | |
104 | |
], | |
{} | |
], | |
"subclassing-py": [ | |
"subclassing.py", | |
[ | |
1205, | |
47 | |
], | |
{} | |
], | |
"templating-py": [ | |
"templating.py", | |
[ | |
10738, | |
293 | |
], | |
{} | |
], | |
"test_apps": [ | |
"test_apps", | |
[ | |
2129, | |
122 | |
], | |
{ | |
"blueprintapp": [ | |
"blueprintapp", | |
[ | |
766, | |
34 | |
], | |
{ | |
"__init__-py": [ | |
"__init__.py", | |
[ | |
200, | |
8 | |
], | |
{} | |
], | |
"apps": [ | |
"apps", | |
[ | |
566, | |
26 | |
], | |
{ | |
"__init__-py": [ | |
"__init__.py", | |
[ | |
0, | |
1 | |
], | |
{} | |
], | |
"admin": [ | |
"admin", | |
[ | |
362, | |
16 | |
], | |
{ | |
"__init__-py": [ | |
"__init__.py", | |
[ | |
362, | |
16 | |
], | |
{} | |
] | |
} | |
], | |
"frontend": [ | |
"frontend", | |
[ | |
204, | |
9 | |
], | |
{ | |
"__init__-py": [ | |
"__init__.py", | |
[ | |
204, | |
9 | |
], | |
{} | |
] | |
} | |
] | |
} | |
] | |
} | |
], | |
"config_module_app-py": [ | |
"config_module_app.py", | |
[ | |
101, | |
5 | |
], | |
{} | |
], | |
"config_package_app": [ | |
"config_package_app", | |
[ | |
101, | |
5 | |
], | |
{ | |
"__init__-py": [ | |
"__init__.py", | |
[ | |
101, | |
5 | |
], | |
{} | |
] | |
} | |
], | |
"flask_broken": [ | |
"flask_broken", | |
[ | |
48, | |
4 | |
], | |
{ | |
"__init__-py": [ | |
"__init__.py", | |
[ | |
48, | |
3 | |
], | |
{} | |
], | |
"b-py": [ | |
"b.py", | |
[ | |
0, | |
1 | |
], | |
{} | |
] | |
} | |
], | |
"flask_newext_package": [ | |
"flask_newext_package", | |
[ | |
61, | |
5 | |
], | |
{ | |
"__init__-py": [ | |
"__init__.py", | |
[ | |
26, | |
2 | |
], | |
{} | |
], | |
"submodule-py": [ | |
"submodule.py", | |
[ | |
35, | |
3 | |
], | |
{} | |
] | |
} | |
], | |
"flask_newext_simple-py": [ | |
"flask_newext_simple.py", | |
[ | |
25, | |
2 | |
], | |
{} | |
], | |
"flaskext": [ | |
"flaskext", | |
[ | |
86, | |
8 | |
], | |
{ | |
"__init__-py": [ | |
"__init__.py", | |
[ | |
0, | |
1 | |
], | |
{} | |
], | |
"oldext_package": [ | |
"oldext_package", | |
[ | |
61, | |
5 | |
], | |
{ | |
"__init__-py": [ | |
"__init__.py", | |
[ | |
26, | |
2 | |
], | |
{} | |
], | |
"submodule-py": [ | |
"submodule.py", | |
[ | |
35, | |
3 | |
], | |
{} | |
] | |
} | |
], | |
"oldext_simple-py": [ | |
"oldext_simple.py", | |
[ | |
25, | |
2 | |
], | |
{} | |
] | |
} | |
], | |
"importerror-py": [ | |
"importerror.py", | |
[ | |
46, | |
3 | |
], | |
{} | |
], | |
"lib": [ | |
"lib", | |
[ | |
84, | |
8 | |
], | |
{ | |
"python2-5": [ | |
"python2.5", | |
[ | |
84, | |
8 | |
], | |
{ | |
"site-packages": [ | |
"site-packages", | |
[ | |
84, | |
8 | |
], | |
{ | |
"site_app-py": [ | |
"site_app.py", | |
[ | |
42, | |
4 | |
], | |
{} | |
], | |
"site_package": [ | |
"site_package", | |
[ | |
42, | |
4 | |
], | |
{ | |
"__init__-py": [ | |
"__init__.py", | |
[ | |
42, | |
4 | |
], | |
{} | |
] | |
} | |
] | |
} | |
] | |
} | |
] | |
} | |
], | |
"main_app-py": [ | |
"main_app.py", | |
[ | |
90, | |
5 | |
], | |
{} | |
], | |
"moduleapp": [ | |
"moduleapp", | |
[ | |
605, | |
34 | |
], | |
{ | |
"__init__-py": [ | |
"__init__.py", | |
[ | |
188, | |
8 | |
], | |
{} | |
], | |
"apps": [ | |
"apps", | |
[ | |
417, | |
26 | |
], | |
{ | |
"__init__-py": [ | |
"__init__.py", | |
[ | |
0, | |
1 | |
], | |
{} | |
], | |
"admin": [ | |
"admin", | |
[ | |
259, | |
15 | |
], | |
{ | |
"__init__-py": [ | |
"__init__.py", | |
[ | |
259, | |
15 | |
], | |
{} | |
] | |
} | |
], | |
"frontend": [ | |
"frontend", | |
[ | |
158, | |
10 | |
], | |
{ | |
"__init__-py": [ | |
"__init__.py", | |
[ | |
158, | |
10 | |
], | |
{} | |
] | |
} | |
] | |
} | |
] | |
} | |
], | |
"path": [ | |
"path", | |
[ | |
42, | |
4 | |
], | |
{ | |
"installed_package": [ | |
"installed_package", | |
[ | |
42, | |
4 | |
], | |
{ | |
"__init__-py": [ | |
"__init__.py", | |
[ | |
42, | |
4 | |
], | |
{} | |
] | |
} | |
] | |
} | |
], | |
"subdomaintestmodule": [ | |
"subdomaintestmodule", | |
[ | |
74, | |
5 | |
], | |
{ | |
"__init__-py": [ | |
"__init__.py", | |
[ | |
74, | |
5 | |
], | |
{} | |
] | |
} | |
] | |
} | |
], | |
"testing-py": [ | |
"testing.py", | |
[ | |
7385, | |
244 | |
], | |
{} | |
], | |
"views-py": [ | |
"views.py", | |
[ | |
5092, | |
170 | |
], | |
{} | |
] | |
} | |
], | |
"views-py": [ | |
"views.py", | |
[ | |
5610, | |
151 | |
], | |
{} | |
], | |
"wrappers-py": [ | |
"wrappers.py", | |
[ | |
5528, | |
147 | |
], | |
{} | |
] | |
} | |
], | |
"run-tests-py": [ | |
"run-tests.py", | |
[ | |
140, | |
6 | |
], | |
{} | |
], | |
"scripts": [ | |
"scripts", | |
[ | |
30380, | |
937 | |
], | |
{ | |
"flask-07-upgrade-py": [ | |
"flask-07-upgrade.py", | |
[ | |
10777, | |
300 | |
], | |
{} | |
], | |
"flaskext_compat-py": [ | |
"flaskext_compat.py", | |
[ | |
5023, | |
126 | |
], | |
{} | |
], | |
"flaskext_test-py": [ | |
"flaskext_test.py", | |
[ | |
9665, | |
312 | |
], | |
{} | |
], | |
"make-release-py": [ | |
"make-release.py", | |
[ | |
4029, | |
152 | |
], | |
{} | |
], | |
"testproj": [ | |
"testproj", | |
[ | |
886, | |
47 | |
], | |
{ | |
"test-py": [ | |
"test.py", | |
[ | |
886, | |
47 | |
], | |
{} | |
] | |
} | |
] | |
} | |
], | |
"setup-py": [ | |
"setup.py", | |
[ | |
3074, | |
113 | |
], | |
{} | |
] | |
} | |
]; |
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> | |
<meta charset="utf-8" /> | |
<style> | |
html | |
{ | |
font-family: Century Gothic, Arial, Helvetica; | |
font-size:1em; | |
} | |
body | |
{ | |
padding:10px; | |
} | |
form | |
{ | |
} | |
#code_hierarchy | |
{ | |
position:relative; | |
width:600px; | |
margin:0 auto; | |
} | |
#code_hierarchy_legend | |
{ | |
height:100px; | |
font-size:1.4em; | |
text-align:center; | |
} | |
</style> | |
<head> | |
<script src="http://d3js.org/d3.v3.js"></script> | |
<script lang="text/javascript"> | |
function init_code_hierarchy_plot(element_id,data,count_function,color_function,title_function,legend_function) | |
{ | |
var plot = document.getElementById(element_id); | |
while (plot.hasChildNodes()) | |
{ | |
plot.removeChild(plot.firstChild); | |
} | |
var width = plot.offsetWidth; | |
var height = width; | |
var x_margin = 40; | |
var y_margin = 40; | |
var max_depth=3; | |
var data_slices = []; | |
var max_level = 4; | |
var svg = d3.select("#"+element_id).append("svg") | |
.attr("width", width) | |
.attr("height", height) | |
.append("g") | |
.attr("transform", "translate(" + width / 2 + "," + height * .52 + ")"); | |
function process_data(data,level,start_deg,stop_deg) | |
{ | |
var name = data[0]; | |
var total = count_function(data); | |
var children = data[2]; | |
var current_deg = start_deg; | |
if (level > max_level) | |
{ | |
return; | |
} | |
if (start_deg == stop_deg) | |
{ | |
return; | |
} | |
data_slices.push([start_deg,stop_deg,name,level,data[1]]); | |
for (var key in children) | |
{ | |
child = children[key]; | |
var inc_deg = (stop_deg-start_deg)/total*count_function(child); | |
var child_start_deg = current_deg; | |
current_deg+=inc_deg; | |
var child_stop_deg = current_deg; | |
var span_deg = child_stop_deg-child_start_deg; | |
process_data(child,level+1,child_start_deg,child_stop_deg); | |
} | |
} | |
process_data(data,0,0,360./180.0*Math.PI); | |
var ref = data_slices[0]; | |
var next_ref = ref; | |
var last_refs = []; | |
var thickness = width/2.0/(max_level+2)*1.1; | |
var arc = d3.svg.arc() | |
.startAngle(function(d) { if(d[3]==0){return d[0];}return d[0]+0.01; }) | |
.endAngle(function(d) { if(d[3]==0){return d[1];}return d[1]-0.01; }) | |
.innerRadius(function(d) { return 1.1*d[3]*thickness; }) | |
.outerRadius(function(d) { return (1.1*d[3]+1)*thickness; }); | |
var slices = svg.selectAll(".form") | |
.data(function(d) { return data_slices; }) | |
.enter() | |
.append("g"); | |
slices.append("path") | |
.attr("d", arc) | |
.attr("id",function(d,i){return element_id+i;}) | |
.style("fill", function(d) { return color_function(d);}) | |
.attr("class","form"); | |
slices.on("click",animate); | |
if (title_function != undefined) | |
{ | |
slices.append("svg:title") | |
.text(title_function); | |
} | |
if (legend_function != undefined) | |
{ | |
slices.on("mouseover",update_legend) | |
.on("mouseout",remove_legend); | |
var legend = d3.select("#"+element_id+"_legend") | |
function update_legend(d) | |
{ | |
legend.html(legend_function(d)); | |
legend.transition().duration(200).style("opacity","1"); | |
} | |
function remove_legend(d) | |
{ | |
legend.transition().duration(1000).style("opacity","0"); | |
} | |
} | |
function get_start_angle(d,ref) | |
{ | |
if (ref) | |
{ | |
var ref_span = ref[1]-ref[0]; | |
return (d[0]-ref[0])/ref_span*Math.PI*2.0 | |
} | |
else | |
{ | |
return d[0]; | |
} | |
} | |
function get_stop_angle(d,ref) | |
{ | |
if (ref) | |
{ | |
var ref_span = ref[1]-ref[0]; | |
return (d[1]-ref[0])/ref_span*Math.PI*2.0 | |
} | |
else | |
{ | |
return d[0]; | |
} | |
} | |
function get_level(d,ref) | |
{ | |
if (ref) | |
{ | |
return d[3]-ref[3]; | |
} | |
else | |
{ | |
return d[3]; | |
} | |
} | |
function rebaseTween(new_ref) | |
{ | |
return function(d) | |
{ | |
var level = d3.interpolate(get_level(d,ref),get_level(d,new_ref)); | |
var start_deg = d3.interpolate(get_start_angle(d,ref),get_start_angle(d,new_ref)); | |
var stop_deg = d3.interpolate(get_stop_angle(d,ref),get_stop_angle(d,new_ref)); | |
var opacity = d3.interpolate(100,0); | |
return function(t) | |
{ | |
return arc([start_deg(t),stop_deg(t),d[2],level(t)]); | |
} | |
} | |
} | |
var animating = false; | |
function animate(d) { | |
if (animating) | |
{ | |
return; | |
} | |
animating = true; | |
var revert = false; | |
var new_ref; | |
if (d == ref && last_refs.length > 0) | |
{ | |
revert = true; | |
last_ref = last_refs.pop(); | |
} | |
if (revert) | |
{ | |
d = last_ref; | |
new_ref = ref; | |
svg.selectAll(".form") | |
.filter( | |
function (b) | |
{ | |
if (b[0] >= last_ref[0] && b[1] <= last_ref[1] && b[3] >= last_ref[3]) | |
{ | |
return true; | |
} | |
return false; | |
} | |
) | |
.transition().duration(1000).style("opacity","1").attr("pointer-events","all"); | |
} | |
else | |
{ | |
new_ref = d; | |
svg.selectAll(".form") | |
.filter( | |
function (b) | |
{ | |
if (b[0] < d[0] || b[1] > d[1] || b[3] < d[3]) | |
{ | |
return true; | |
} | |
return false; | |
} | |
) | |
.transition().duration(1000).style("opacity","0").attr("pointer-events","none"); | |
} | |
svg.selectAll(".form") | |
.filter( | |
function (b) | |
{ | |
if (b[0] >= new_ref[0] && b[1] <= new_ref[1] && b[3] >= new_ref[3]) | |
{ | |
return true; | |
} | |
return false; | |
} | |
) | |
.transition().duration(1000).attrTween("d",rebaseTween(d)); | |
setTimeout(function(){ | |
animating = false; | |
if (! revert) | |
{ | |
last_refs.push(ref); | |
ref = d; | |
} | |
else | |
{ | |
ref = d; | |
} | |
},1000); | |
}; | |
} | |
function init_plots() | |
{ | |
function count_function(d) | |
{ | |
return d[1][0]; | |
} | |
function label_function(d) | |
{ | |
return d[2]+": "+d[4][0]+" characters, "+d[4][1]+" lines of code."; | |
} | |
function legend_function(d) | |
{ | |
return "<h2>"+d[2]+" </h2><p>"+d[4][0]+" characters, "+d[4][1]+" lines of code.</p>" | |
} | |
var color = d3.scale.category20c(); | |
function color_function(d) | |
{ | |
return color(d[2]); | |
} | |
d3.select(self.frameElement).style("height", "800px"); | |
init_code_hierarchy_plot("code_hierarchy",code_hierarchy_data,count_function,color_function,label_function,legend_function); | |
} | |
window.onload = init_plots; | |
window.onresize = init_plots; | |
</script> | |
<script type="text/javascript" src="data.js"></script> | |
</head> | |
<body> | |
<p>Click on a segment to get a zoomed-in view of its children.<br />Check out the full example <a href="http://www.andreas-dewes.de/code_is_beautiful" target="_blank">here</a>.</p> | |
<div id="code_hierarchy_legend"> </div> | |
<div id="code_hierarchy"> </div> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment