(function() { var angle, apothem, arc_generator, bars, bins, bottom_left, bottom_right, classes, color, distributions, dots, hexbin, inner_radius_scale, max, max_tot, middle_left, middle_right, pie_layout, pies, points, radius, radius_scale, side, subplots, svg, upper_left, upper_right, x_scale, y_scale; d3.select(self.frameElement).style('height', '1440px'); side = 480; distributions = [ d3.range(1500).map(function() { return { x: d3.random.normal(side / 2, 80)(), y: d3.random.normal(side / 2, 80)() }; }), d3.range(1500).map(function() { return { x: d3.random.normal(side / 2, 80)() - 50, y: 100 + d3.random.normal(side / 2, 80)() }; }), d3.range(1500).map(function() { return { x: d3.random.normal(side / 2, 80)(), y: d3.random.normal(side / 2, 80)() - 100 }; }), d3.range(1000).map(function() { return { x: d3.random.normal(3.5 * side / 4, 80)(), y: d3.random.normal(side / 2, 80)() }; }) ]; classes = distributions.length; points = _.chain(distributions).map(function(distribution, klass) { distribution.forEach(function(point) { return point["class"] = klass; }); return distribution; }).flatten(true).value(); radius = 18; apothem = Math.sqrt(3) / 2 * radius; hexbin = d3.hexbin().size([side, side]).radius(radius).x(function(d) { return d.x; }).y(function(d) { return d.y; }); bins = _.chain(hexbin(points)).forEach(function(bin) { return bin.classes_count = _.chain(_.range(classes)).map(function(klass) { return bin.filter(function(point) { return point["class"] === klass; }).length; }).value(); }).value(); max_tot = d3.max(bins, function(bin) { return bin.length; }); max = d3.max(bins, function(bin) { return d3.max(bin.classes_count); }); angle = 2 * Math.PI / classes; svg = d3.select('svg'); upper_left = svg.append('g').attr('id', 'dots').attr('clip-path', 'url(#square_window)'); upper_right = svg.append('g').attr('id', 'bars').attr('clip-path', 'url(#square_window)').attr('transform', "translate(" + side + ",0)"); middle_left = svg.append('g').attr('id', 'pies').attr('clip-path', 'url(#square_window)').attr('transform', "translate(0," + side + ")"); middle_right = svg.append('g').attr('id', 'arcs').attr('clip-path', 'url(#square_window)').attr('transform', "translate(" + side + "," + side + ")"); bottom_left = svg.append('g').attr('id', 'polar_length').attr('clip-path', 'url(#square_window)').attr('transform', "translate(0," + (2 * side) + ")"); bottom_right = svg.append('g').attr('id', 'polar_area').attr('clip-path', 'url(#square_window)').attr('transform', "translate(" + side + "," + (2 * side) + ")"); svg.append('line').attr({ "class": 'separator', x1: 0, x2: 2 * side, y1: side, y2: side }); svg.append('line').attr({ "class": 'separator', x1: 0, x2: 2 * side, y1: 2 * side, y2: 2 * side }); svg.append('line').attr({ "class": 'separator', x1: side, x2: side, y1: 0, y2: 3 * side }); color = d3.scale.category10(); dots = d3.select('#dots').selectAll('.dot').data(points); dots.enter().append('circle').attr({ "class": 'dot', r: 1, cx: function(p) { return p.x; }, cy: function(p) { return p.y; }, fill: function(d) { return color(d["class"]); } }); subplots = d3.select('#bars').selectAll('.subplot').data(bins); subplots.enter().append('g').attr({ "class": 'subplot', transform: function(bin) { return "translate(" + bin.x + "," + bin.y + ")"; } }); y_scale = d3.scale.linear().domain([0, max]).range([0, radius]); x_scale = d3.scale.ordinal().domain(_.range(classes)).rangeRoundBands([-radius / 2, radius / 2], 0.05); bars = subplots.selectAll('.bar').data(function(bin) { return bin.classes_count; }); bars.enter().append('rect').attr({ "class": 'bar', x: function(count, klass) { return x_scale(klass); }, y: function(count) { return y_scale(max - count); }, width: x_scale.rangeBand(), height: function(count) { return y_scale(count); }, fill: function(count, klass) { return color(klass); }, transform: "translate(0," + (-radius) + ")" }); subplots = d3.select('#pies').selectAll('.subplot').data(bins); subplots.enter().append('g').attr({ "class": 'subplot', transform: function(bin) { return "translate(" + bin.x + "," + bin.y + ")"; } }); pie_layout = d3.layout.pie().sort(null); radius_scale = d3.scale.sqrt().domain([0, max_tot]).range([0, apothem]); arc_generator = d3.svg.arc().outerRadius(function(count) { return radius_scale(d3.select(this.parentNode).datum().length); }).innerRadius(0); pies = subplots.selectAll('.pie').data(function(bin) { return pie_layout(bin.classes_count); }); pies.enter().append('path').attr({ "class": 'pie', d: arc_generator, fill: function(count, klass) { return color(klass); } }); subplots = d3.select('#arcs').selectAll('.subplot').data(bins); subplots.enter().append('g').attr({ "class": 'subplot', transform: function(bin) { return "translate(" + bin.x + "," + bin.y + ")"; } }); radius_scale = d3.scale.linear().domain([0, max]).range([0, apothem * 0.9]); inner_radius_scale = d3.scale.linear().domain([0, max]).range([apothem * 0.4, apothem * 0.9]); arc_generator = d3.svg.arc().innerRadius(function(count) { return inner_radius_scale(max - count); }).outerRadius(function(count) { return radius_scale(max); }).startAngle(function(count, klass) { return klass * angle - angle / 2; }).endAngle(function(count, klass) { return klass * angle + angle / 2; }); pies = subplots.selectAll('.pie').data(function(bin) { return bin.classes_count; }); pies.enter().append('path').attr({ "class": 'pie', d: arc_generator, fill: function(count, klass) { return color(klass); } }); subplots = d3.select('#polar_length').selectAll('.subplot').data(bins); subplots.enter().append('g').attr({ "class": 'subplot', transform: function(bin) { return "translate(" + bin.x + "," + bin.y + ")"; } }); radius_scale = d3.scale.linear().domain([0, max]).range([0, apothem]); arc_generator = d3.svg.arc().innerRadius(0).outerRadius(function(count) { return radius_scale(count); }).startAngle(function(count, klass) { return klass * angle - angle / 2; }).endAngle(function(count, klass) { return klass * angle + angle / 2; }); pies = subplots.selectAll('.pie').data(function(bin) { return bin.classes_count; }); pies.enter().append('path').attr({ "class": 'pie', d: arc_generator, fill: function(count, klass) { return color(klass); } }); subplots = d3.select('#polar_area').selectAll('.subplot').data(bins); subplots.enter().append('g').attr({ "class": 'subplot', transform: function(bin) { return "translate(" + bin.x + "," + bin.y + ")"; } }); radius_scale = d3.scale.sqrt().domain([0, max]).range([0, apothem]); arc_generator = d3.svg.arc().innerRadius(0).outerRadius(function(count) { return radius_scale(count); }).startAngle(function(count, klass) { return klass * angle - angle / 2; }).endAngle(function(count, klass) { return klass * angle + angle / 2; }); pies = subplots.selectAll('.pie').data(function(bin) { return bin.classes_count; }); pies.enter().append('path').attr({ "class": 'pie', d: arc_generator, fill: function(count, klass) { return color(klass); } }); }).call(this);