I saw this list of sparse matrices and thought they could be thrown right into a d3 force layout.
I made a small script to process and host the "MM" formatted matrices to a d3 friendly JSON format.
I'd like to add more matrices from the list, and try to adapt this to webgl.
Built with blockbuilder.org
forked from enjalot's block: sparse matrix zoo
xxxxxxxxxx
<head>
<meta charset="utf-8">
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
<style>
body {
margin:0;position:fixed;top:0;right:0;bottom:0;left:0;
background-color: #111;
}
svg { width: 100%; height: 100%; }
line {
pointer-events: none;
}
#matrices {
position: absolute;
top: 10px;
left: 10px;
}
</style>
</head>
<body>
<svg></svg>
<select id="matrices">
</select>
<script>
d3.json("https://enjalot.github.io/sparse-matrix-zoo/json/list.json", function(err, matrices) {
var select = d3.select("#matrices")
select.selectAll("option")
.data(matrices)
.enter().append("option")
.text(function(d) { return d.name })
select.on("change", function() {
var i = this.selectedIndex;
render(matrices[i].url);
})
render(matrices[0].url)
var width = window.innerWidth || 960;
var height = window.outerHeight/1.5 || 500;
var force;
function render(url) {
d3.json(url, function(err, data) {
console.log(data);
var numNodes = d3.max([+data.meta.rows, +data.meta.cols]);
console.log("numNodes", numNodes);
var nodes = d3.range(numNodes).map(function(d) { return {i: d, value: 0}});
var links = []
data.data.forEach(function(d) {
if(d.source !== d.target) {
// the matrix is 1-indexed
links.push(d)
} else {
nodes[d.source].value = d.value
}
})
console.log("nodes", nodes)
console.log("links",links)
var linkScale = d3.scale.sqrt()
.domain(d3.extent(links, function(d) { return d.value }))
.range([1, 10])
var nodeScale = d3.scale.sqrt()
.domain(d3.extent(nodes, function(d) { return d.value }))
.range([3, 8])
delete force;
force = d3.layout.force()
.charge(-180)
.linkDistance(40)
.friction(0.8)
.gravity(0.2)
//.linkStrength(0.9)
.linkStrength(function(d) { return linkScale(d.value)/10 })
.size([width, height]);
force
.nodes(nodes)
.links(links)
.start();
var svg = d3.select("svg");
var link = svg.selectAll(".link")
.data(links)
link.exit().remove();
link
.enter().append("line")
.attr("class", "link")
.style({
stroke: "#adf6fe",
"stroke-opacity": 0.624,
"stroke-width": function(d) { return linkScale(d.value); }
})
.style();
var node = svg.selectAll(".node")
.data(nodes)
node.exit().remove();
node
.enter().append("circle")
.attr("class", "node")
.style("fill", function(d) { return "#8effe8" })
node
//.attr("r", 5)
.attr("r", function(d) { return nodeScale(d.value) })
.call(force.drag);
force.on("tick", function() {
link.attr("x1", function(d) { return d.source.x; })
.attr("y1", function(d) { return d.source.y; })
.attr("x2", function(d) { return d.target.x; })
.attr("y2", function(d) { return d.target.y; });
node.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; });
});
})
}
})
</script>
</body>
https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js