A basic scatterplot matrix allows for brushing of data points in a scatter plot and linking of corresponding subsets of the queried data. The VisDock toolkit has been integrated into the scatterpplot matrix example built with D3.js (found here) by M. Bostock. Using selection tools, brushing can be done in various shapes, ellipses, polygons, and lassos, to query a multi-variate scatterplot dataset.
xxxxxxxxxx
<meta charset="utf-8">
<style>
svg {
font: 10px sans-serif;
Padding: 10px;
}
.axis,
.frame {
shape-rendering: crispEdges;
}
.axis line {
stroke: #ddd;
}
.axis path {
display: none;
}
.frame {
fill: none;
stroke: #aaa;
}
.Circ {
fill-opacity: .7;
}
</style>
<body>
<link href="https://rawgithub.com/VisDockHub/NewVisDock/master/master/visdock.css" rel="stylesheet" type="text/css"/>
<script src="https://d3js.org/d3.v3.min.js"></script>
<script src="https://rawgithub.com/visdockhub/newvisdock/master/master/visdock.js"></script>
<script src="https://rawgithub.com/visdockhub/newvisdock/master/master/2d.js"></script>
<script src="https://rawgithub.com/visdockhub/newvisdock/master/master/intersectionutilities.js"></script>
<script src="https://rawgithub.com/visdockhub/newvisdock/master/master/visdock.utils.js"></script>
<script>
var width = 960,
size = 150,
Padding = 19.5;
VisDock.init("body", {width: 1000, height: 900});
var viewport = VisDock.getViewport();
var circle_query = [];
var x = d3.scale.linear()
.range([Padding / 2, size - Padding / 2]);
var y = d3.scale.linear()
.range([size - Padding / 2, Padding / 2]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
.ticks(5);
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.ticks(5);
var color = d3.scale.category10();
d3.csv("flowers.csv", function(error, data) {
VisDock.startChrome();
var domainByTrait = {},
traits = d3.keys(data[0]).filter(function(d) { return d !== "species"; }),
n = traits.length;
traits.forEach(function(trait) {
domainByTrait[trait] = d3.extent(data, function(d) { return d[trait]; });
});
xAxis.tickSize(size * n);
yAxis.tickSize(-size * n);
var svg = viewport;
svg.selectAll(".x.axis")
.data(traits)
.enter().append("g")
.attr("class", "x axis")
.attr("transform", function(d, i) { return "translate(" + (n - i - 1) * size + ",0)"; })
.each(function(d) { x.domain(domainByTrait[d]); d3.select(this).call(xAxis); });
svg.selectAll(".y.axis")
.data(traits)
.enter().append("g")
.attr("class", "y axis")
.attr("transform", function(d, i) { return "translate(0," + i * size + ")"; })
.each(function(d) { y.domain(domainByTrait[d]); d3.select(this).call(yAxis); });
var cell = svg.selectAll(".cell")
.data(cross(traits, traits))
.enter().append("g")
.attr("class", "cell")
.each(plot);
// Titles for the diagonal.
cell.filter(function(d) { return d.i === d.j; }).append("text")
.attr("x", Padding)
.attr("y", Padding)
.attr("dy", ".71em")
.attr("transform", function(d) {
return "translate(" + (n - d.i - 1) * size + "," + d.j * size + ")"; })
.text(function(d) { return d.x; });
function plot(p) {
VisDock.startChrome();
var cell = d3.select(this);
x.domain(domainByTrait[p.x]);
y.domain(domainByTrait[p.y]);
cell.append("rect")
.attr("class", "frame")
.attr("x", Padding / 2)
.attr("y", Padding / 2)
.attr("width", size - Padding)
.attr("height", size - Padding)
.attr("transform", function(d) {
return "translate(" + (n - d.i - 1) * size + "," + d.j * size + ")"; });
cell.selectAll("circle")
.data(data)
.enter().append("circle")
.attr("class", "Circ")
.attr("cx", function(d) { return (n - p.i - 1) * size + x(d[p.x]); })
.attr("cy", function(d) { return p.j * size+y(d[p.y]); })
.attr("r", 3)
.style("fill", function(d) { return color(d.species); });
VisDock.finishChrome();
}
function cross(a, b) {
var c = [], n = a.length, m = b.length, i, j;
for (i = -1; ++i < n;) for (j = -1; ++j < m;) c.push({x: a[i], i: i, y: b[j], j: j});
return c;
}
//d3.select(self.frameElement).style("height", size * n + Padding + 20 + "px");
VisDock.finishChrome();
});
VisDock.eventHandler = {
getHitsPolygon: function(points, inclusive){
var shapebound = new createPolygon(points);
return selectionLoop(shapebound, inclusive);
},
getHitsEllipse: function(points, inclusive){
var shapebound = new createEllipse(points);
return selectionLoop(shapebound, inclusive);
},
getHitsLine: function(points, inclusive){
alert("Please use a different selection tool")
},
setColor: function(hits){
var query = brushed(hits)
for (var i = 0; i < query.length; i++){
VisDock.utils.addEllipseLayer(query[i], null, num - 1);
}
},
changeColor: function(color, query, index){
var visibility = VisDock.utils.getQueryVisibility(index);
for (var i = 0; i < query.length; i++){
query[i].attr("style", "opacity:" + visibility + "; fill: " + color)
}
},
changeVisibility: function(vis, query, index){
var color = VisDock.utils.getQueryColor(index);
for (var i = 0; i < query.length; i++){
query[i].attr("style", "opacity: " + vis + ";fill: " + color)
}
},
removeColor: function(hits, index){
for (var i = 0; i < hits.length; i++){
hits[i].remove();
}
}
}
function selectionLoop(shapebound, inclusive){
var cells = d3.selectAll(".cell")[0]
var hits = [];
if (circle_query[num] == undefined) circle_query[num] = [];
for (var i = 0; i < cells.length; i++){
for (var j = 1; j < cells[i].children.length; j++){
var circles = cells[i].children[j]
var captured = shapebound.intersectEllipse([circles], inclusive)
if (captured.length == 1){
hits.push(captured[0])
if (circle_query[num].indexOf(j) == -1) circle_query[num].push(j)
}
}
}
return hits;
}
function brushed(hits){
var cells = d3.selectAll(".cell")[0]
var query = hits;
if (circle_query[num-1] == undefined) circle_query[num-1]=[];
for (var i=0;i<cells.length;i++){
for (var j=1;j<cells[i].children.length;j++){
if (circle_query[num-1].length >= 1){
if (circle_query[num-1].indexOf(j) != -1){
query.push(cells[i].children[j])
}
}
}
}
return query;
}
BirdView.init(viewport, 1000, 900)
d3.select(self.frameElement).style("width", "1000px")
d3.select(self.frameElement).style("height", "900px")
</script>
Modified http://d3js.org/d3.v3.min.js to a secure url
Modified http://rawgithub.com/VisDockHub/NewVisDock/master/master/visdock.js to a secure url
Modified http://rawgithub.com/VisDockHub/NewVisDock/master/master/2D.js to a secure url
Modified http://rawgithub.com/VisDockHub/NewVisDock/master/master/IntersectionUtilities.js to a secure url
Modified http://rawgithub.com/VisDockHub/NewVisDock/master/master/visdock.utils.js to a secure url
https://d3js.org/d3.v3.min.js
https://rawgithub.com/VisDockHub/NewVisDock/master/master/visdock.js
https://rawgithub.com/VisDockHub/NewVisDock/master/master/2D.js
https://rawgithub.com/VisDockHub/NewVisDock/master/master/IntersectionUtilities.js
https://rawgithub.com/VisDockHub/NewVisDock/master/master/visdock.utils.js