Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Spiral for John Hunter

A tribute to John Hunter (1968-2012), creator of matplotlib, an open-source plotting library for Python.

I stumbled across this polar-plot example exploring the matplotlib site. The chart title struck me. I know how exciting it can be to break out of the rectilinear coordinate system. Spirals are mysterious and beautiful, reaching from the origin out towards infinity.

Thank you John, for the wonderful plots.

<iframe width="640" height="480" src="http://www.youtube.com/embed/e3lTby5RI54" frameborder="0" allowfullscreen></iframe>

If you appreciate John's work, consider donating to the John Hunter Memorial Fund to help support his childrens' education.

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<title>Archimedean Spiral</title>
<script type="text/javascript" src="http://d3js.org/d3.v2.js"></script>
<style>
body {
font-family: 'Lucida Grande', 'Lucida Sans Unicode', 'Geneva', 'Verdana', sans-serif;
margin: 40px;
}
.axis path {
fill: none;
stroke: #999;
stroke-dasharray: 2 3;
}
.axis text {
font-size: 13px;
stroke: #222;
}
text.title {
font-size: 24px;
}
circle.tick {
fill: #f3f3f3;
stroke: #999;
stroke-dasharray: 2 3;
}
path.spiral {
fill: none;
stroke: #ee8d18;
stroke-width: 3px;
}
</style>
</head>
<body>
<div id="chart"></div>
<script type="text/javascript" src="spiral.js"></script>
</body>
</html>
// a spiral for john hunter, creator of matplotlib
var width = 400,
height = 430
num_axes = 8,
tick_axis = 1,
start = 0
end = 2;
var theta = function(r) {
return -2*Math.PI*r;
};
var arc = d3.svg.arc()
.startAngle(0)
.endAngle(2*Math.PI);
var radius = d3.scale.linear()
.domain([start, end])
.range([0, d3.min([width,height])/2-20]);
var angle = d3.scale.linear()
.domain([0,num_axes])
.range([0,360])
var svg = d3.select("#chart").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width/2 + "," + (height/2+8) +")");
var pieces = d3.range(start, end+0.001, (end-start)/1000);
var spiral = d3.svg.line.radial()
.interpolate("cardinal")
.angle(theta)
.radius(radius);
svg.append("text")
.text("And there was much rejoicing!")
.attr("class", "title")
.attr("x", 0)
.attr("y", -height/2+16)
.attr("text-anchor", "middle")
svg.selectAll("circle.tick")
.data(d3.range(end,start,(start-end)/4))
.enter().append("circle")
.attr("class", "tick")
.attr("cx", 0)
.attr("cy", 0)
.attr("r", function(d) { return radius(d); })
svg.selectAll(".axis")
.data(d3.range(num_axes))
.enter().append("g")
.attr("class", "axis")
.attr("transform", function(d) { return "rotate(" + -angle(d) + ")"; })
.call(radial_tick)
.append("text")
.attr("y", radius(end)+13)
.text(function(d) { return angle(d) + "°"; })
.attr("text-anchor", "middle")
.attr("transform", function(d) { return "rotate(" + -90 + ")" })
svg.selectAll(".spiral")
.data([pieces])
.enter().append("path")
.attr("class", "spiral")
.attr("d", spiral)
.attr("transform", function(d) { return "rotate(" + 90 + ")" });
function radial_tick(selection) {
selection.each(function(axis_num) {
d3.svg.axis()
.scale(radius)
.ticks(5)
.tickValues( axis_num == tick_axis ? null : [])
.orient("bottom")(d3.select(this))
d3.select(this)
.selectAll("text")
.attr("text-anchor", "bottom")
.attr("transform", "rotate(" + angle(axis_num) + ")")
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment