block by enjalot 42a531c5d87bfc91036e

sparse matrix zoo: canvas

Full Screen

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: canvas

index.html

<!DOCTYPE html>
<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%;
      position:absolute;
    }
    canvas { 

      position:absolute;
    }
    line {
      pointer-events: none;
    }
    #matrices {
      position: absolute;
      top: 10px;
      left: 10px;
    }
  </style>
</head>

<body>

  <canvas></canvas>
  <svg></svg>
  <select id="matrices">
  </select>
  <script>
    
    d3.json("//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);
    })
    
    
    
    
    var width = window.innerWidth || 960;
    var height = window.innerHeight || 500;
    
    var canvas = d3.select("canvas").node();
    canvas.width = width;
    canvas.height = height;
    var ctx = canvas.getContext("2d");
    ctx.globalCompositeOperation = "lighter";
    
    render(matrices[0].url)
    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();


        function draw() {
          ctx.clearRect(0, 0, width, height);
          ctx.strokeStyle = "rgba(142, 255, 232, 0.2)";
          ctx.lineCap = "round";
          links.forEach(function(l) {
            ctx.beginPath();
            ctx.lineWidth = linkScale(l.value);
            ctx.moveTo(l.source.x, l.source.y);
            ctx.lineTo(l.target.x, l.target.y);
            ctx.stroke();
          })
        }

        var svg = d3.select("svg");

        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() {
          draw();
         node.attr("cx", function(d) { return d.x; })
              .attr("cy", function(d) { return d.y; });
        });
      })
    }
      
    })
  </script>
</body>

08blocks.json

can_61.json