paul kerl's notes on data, tech and they are transforming the world around us

D3.js is known for its great data viz capabilities for the web, including dynamic and interactive capability. But D3.js can also be used to generate static data visualizations via the command line, including CSS styling and/or stylesheets.

For example, if you want a command line solution for automated visualization creation, if you want to output an SVG into your make workflow, or if you need to prepare a visualization for print (for a research paper, journal article, a newspaper or magazine), a plain old non-interactive SVG can be very useful. The output we’re aiming for is an SVG you can load into Inkscape, Illustrator, or one that we can convert to an EPS, a PDF, render to a PNG or any other image file format you can think of.

Alternatives before diving in

Of course if you’ve already created your visualization on the web, you can directly save the SVG via copying the source code and CSS, or using a handy bookmarklet like the NYTimes SVG-crowbar. So the below is a bit overkill for a case where you just want to download your already-web-based data visualization.

D3.js for Node (install via: “npm install d3”). Note that installing D3.js on Windows via npm can be a bit tough, you may or may not run into some dependency roadblocks that will require some googling, not recommended for the faint of heart

First things first, for your Node.js script, you’ll need to require/import D3. This is similar to including d3.v3.min.js at the top of your HTML file.

d3 = require("d3");

To load json from our local filesystem, we’ll need the fs package, since d3.json won’t work as we’re not loading json via a HTTP request (see further down).

var fs = require("fs")

Next, we’ll need to include the client-side Topojson, Topojson.js. Download the latest Topojson.js here. Often Topojson is used via Node.js to simpify Geojson data (Geojson to Topojson for a smaller file size) via the server side API. However, it also can be used to convert the Topojson back to Geojson, via the client side API when rendering a map. Because the geo data we’re using here is Topojson, we’ll need the client side Topojson API. More information on the Topojson APIs is available here.

Next, almost all the rest of the JS code is the same. However, one difference is that d3.json will need to be replaced by the node JSON parser. d3.json loads JSON via a HTTP request, however, when we’re running via the command line won’t be necessary (or possible, in our case).

var us = JSON.parse(fs.readFileSync("us.json", 'utf8'));

To include the CSS styling, we need to include the CSS within defs tags, within the SVG block. In addition, for compatibility with Adobe Illustrator, or if our CSS includes > or < characters, we need to enclose the CSS within a CDATA block. This ensures that when we output the SVG, the CSS is attached, but not accidentally parsed.

var css_text = "

Because JavaScript isn’t a fan of multi-line strings, we need to backslash (escape) the end of each line. Multiline strings in JS need escape characters at the end of each line, since there is no native support for multiline strings. Note that there are alternatives to escaping the end of each line, so feel free to explore other options if you have a larger style sheet.

Last but not least, we will output the svg to stdout, which we can write to an svg file.

console.log(d3.select('body').html());

This selects the html inside the body tag, which in our case is just the SVG block. From there, we can run our JS code (I saved the source file as “area_choropleth.js”) from the command line via:

node area_choropleth.js > area_choropleth.svg

which will direct the SVG text output from stdout into the file “area_choropleth.svg”. And we’re done!

All together now

Here’s the resulting SVG, rendered as a PNG:

Here is the code in full below, which is also hosted with the us.json data from Mike Bostock as a gist on github:

Turns out it’s just two ingredients: cocoa and powdered sugar (great for the lactose intolerants). Can’t really mess that up. And yeah alright, most of the world has hopefully realized that hot cocoa is pretty damn simple, but if not…

Mix thoroughly in a ziplock bag (Example yields 300 grams for those that cannot add two numbers).

Change proportions to adjust dark chocolate-ness.

Yeah, these ingredients cost next to nothing.

STEPS TO GLORY: Warm up an 8oz-12oz glass (13oz is just too much, c’mon) of milk (soy milk, almond milk, “regular” milk… others are untested). Warming can be done via microwave or via the stove if that’s your style. Mix in 4 Tbsps of the above mixture. Cocoa should sort of melt into the milk. Toughest recipe you’ve seen this year, I know.

Great to see everyone over the break… I brought this site up since I haven’t updated in forever. So as for this blog, I’m going to try to trend towards something new for a change… I’m going to aim to post more content (it’s plausible, right?) with useful things — for instance, trends I see, technology that’s promising, maybe even products I enjoy. We’ll see.

I will be updating this site to accommodate a interesting “feed” (links essentially) items I’m reading which will run parallel to the posts on this blog. I’m pretty sure wordpress can handle this, but it will require a redesign. We’ll see how it turns out. It will be structured something like, “short blog (slog)”, “long blog (blog),” and “permanent blog (plog).”

In addition I will be making bacon chocolate chip cookies soon. Mmmmm…