%load_ext py_d3

"""
Explanation: While reflecting on the state of my GitHub repos yesterday, I was thinking how cool things would be if I used D3.
Previously I came across Mike Irvine's personal website <i class="fa fa-github"></i> and I really like how he made the dynamic D3 visual, showcasing the spread of disease in a community (ie. related to his work), as the first thing one notices when they come across his page.
I want to do something similar for my personal website.
Editor for D3
Before I begin, I want an interactive development environment (IDE) for D3. In my search I came across the following:
| IDE | Rating |
|-----|--------|
| D3.js playground | <i class="fa fa-star"></i> |
| Tributary | |
| JSFiddle | <i class="fa fa-star"></i><i class="fa fa-star"></i> |
Embedding D3 in Jupyter Notebooks
I also came across embedding D3 in Jupyter Notebooks with py_d3.

Install py_d3 with pip install py_d3
Run %load_ext py_d3 in Jupyter Notebook for Jupyter notebook D3 block magic
End of explanation
"""


%%d3
<script src="https://d3js.org/d3.v3.js"></script>

"""
Explanation: Include D3 script:
End of explanation
"""


%%d3

<div></div>

<script>
d3.select("div").text("Hello world")
</script>

"""
Explanation: Example 01: Hello world
End of explanation
"""


%%d3

<g></g>

<script>
    d3.select("g").append("svg").append("rect")
      .attr("x", 150)
      .attr("y", 50)
      .attr("width", 50)
      .attr("height", 140);
</script>

"""
Explanation: Example 02: Simple rectangle
End of explanation
"""


%%d3

<g></g>

<script>
function CalculateStarPoints(centerX, centerY, arms, outerRadius, innerRadius) {
  var results = "";
  var angle = Math.PI / arms * 2;

  for (var i = 0; i < 2 * arms; i++) {
    var r = (i & 1) == 0 ? outerRadius : innerRadius;
    var pointX = centerX + Math.cos(i * angle) * r;
    var pointY = centerY + Math.sin(i * angle) * r;
    // Our first time we simply append the coordinates, subsequet times
    // we append a ", " to distinguish each coordinate pair.
    if (i == 0) {
      results = pointX + "," + pointY;
    } else {
      results += ", " + pointX + "," + pointY;
    }
  }
  return results;
}

d3.select("g").append("svg")
  .append("polygon")
  .attr("visibility", "visible")
  .attr("points", CalculateStarPoints(100, 100, 5, 30, 15));

d3.select("g").append("svg")
  .append("polygon")
  .attr("visibility", "visible")
  .attr("points", CalculateStarPoints(100, 100, 5, 30, 15))
  .style("fill", "lime")
  .style("stroke", "purple")
  .style("stroke-width", "5")
  .style("fill-rule","evenodd");
</script>

"""
Explanation: Example 03: Functions, style, and polygons
End of explanation
"""


%%d3

<script src="https://d3js.org/d3.v3.js"></script>

This example is modified from <a href="https://bl.ocks.org/mbostock/3231298">https://bl.ocks.org/mbostock/3231298</a>

<body></body>

<script>
var width = 500,
  height = 500;

var nodes = d3.range(200).map(function() {
    return {
      radius: Math.random() * 12 + 4
    };
  }),
  root = nodes[0],
  color = d3.scale.category10();

root.radius = 0;
root.fixed = true;

var force = d3.layout.force()
  .gravity(0.05)
  .charge(function(d, i) {
    return i ? 0 : -1500;
  })
  .nodes(nodes)
  .size([width, height]);

force.start();

var svg = d3.select("body").append("svg")
  .attr("width", width)
  .attr("height", height);

svg.selectAll("circle")
  .data(nodes.slice(1))
  .enter().append("circle")
  .attr("r", function(d) {
    return d.radius;
  })
  .style("fill", function(d, i) {
    return color(i % 3);
  });

force.on("tick", function(e) {
  var q = d3.geom.quadtree(nodes),
    i = 0,
    n = nodes.length;

  while (++i < n) q.visit(collide(nodes[i]));

  svg.selectAll("circle")
    .attr("cx", function(d) {
      return d.x;
    })
    .attr("cy", function(d) {
      return d.y;
    });
});

svg.on("mousemove", function() {
  var p1 = d3.mouse(this);
  root.px = p1[0];
  root.py = p1[1];
  force.resume();
});

function collide(node) {
  var r = node.radius + 16,
    nx1 = node.x - r,
    nx2 = node.x + r,
    ny1 = node.y - r,
    ny2 = node.y + r;
  return function(quad, x1, y1, x2, y2) {
    if (quad.point && (quad.point !== node)) {
      var x = node.x - quad.point.x,
        y = node.y - quad.point.y,
        l = Math.sqrt(x * x + y * y),
        r = node.radius + quad.point.radius;
      if (l < r) {
        l = (l - r) / l * .5;
        node.x -= x *= l;
        node.y -= y *= l;
        quad.point.x += x;
        quad.point.y += y;
      }
    }
    return x1 > nx2 || x2 < nx1 || y1 > ny2 || y2 < ny1;
  };
}
</script>

"""
Explanation: Kink with using Jupyter Notebook
When I load the Collision Detection example by Mike Bostock in the Jupyter Notebook, it doesn't work. Nothing is rendered (see following). However, this is not an issue with JSFiddle.
End of explanation
"""


